parent
e0f1433c12
commit
d7eae69587
5 changed files with 145 additions and 91 deletions
1
atom.gyp
1
atom.gyp
|
@ -49,6 +49,7 @@
|
|||
'atom/renderer/lib/override.coffee',
|
||||
'atom/renderer/lib/web-view/guest-view-internal.coffee',
|
||||
'atom/renderer/lib/web-view/web-view.coffee',
|
||||
'atom/renderer/lib/web-view/web-view-attributes.coffee',
|
||||
'atom/renderer/lib/web-view/web-view-constants.coffee',
|
||||
'atom/renderer/api/lib/ipc.coffee',
|
||||
'atom/renderer/api/lib/remote.coffee',
|
||||
|
|
|
@ -36,17 +36,19 @@ for arg in process.argv
|
|||
|
||||
if location.protocol is 'chrome-devtools:'
|
||||
# Override some inspector APIs.
|
||||
require path.join(__dirname, 'inspector')
|
||||
require './inspector'
|
||||
nodeIntegration = 'true'
|
||||
else if location.protocol is 'chrome-extension:'
|
||||
# Add implementations of chrome API.
|
||||
require path.join(__dirname, 'chrome-api')
|
||||
require './chrome-api'
|
||||
nodeIntegration = 'true'
|
||||
else
|
||||
# Override default web functions.
|
||||
require path.join(__dirname, 'override')
|
||||
require './override'
|
||||
# Load webview tag implementation.
|
||||
require path.join(__dirname, 'web-view/web-view') unless process.guestInstanceId?
|
||||
unless process.guestInstanceId?
|
||||
require './web-view/web-view'
|
||||
require './web-view/web-view-attributes'
|
||||
|
||||
if nodeIntegration in ['true', 'all', 'except-iframe', 'manual-enable-iframe']
|
||||
# Export node bindings to global.
|
||||
|
|
71
atom/renderer/lib/web-view/web-view-attributes.coffee
Normal file
71
atom/renderer/lib/web-view/web-view-attributes.coffee
Normal file
|
@ -0,0 +1,71 @@
|
|||
WebView = require './web-view'
|
||||
webViewConstants = require './web-view-constants'
|
||||
|
||||
# Attribute objects.
|
||||
# Default implementation of a WebView attribute.
|
||||
class WebViewAttribute
|
||||
constructor: (name, webViewImpl) ->
|
||||
@name = name
|
||||
@value = ''
|
||||
@webViewImpl = webViewImpl
|
||||
|
||||
getValue: -> @value || ''
|
||||
|
||||
setValue: (value) -> @value = value
|
||||
|
||||
# Attribute representing the state of the storage partition.
|
||||
class Partition extends WebViewAttribute
|
||||
constructor: (webViewImpl) ->
|
||||
super webViewConstants.ATTRIBUTE_PARTITION, webViewImpl
|
||||
|
||||
@validPartitionId = true
|
||||
@persistStorage = false
|
||||
@storagePartitionId = ''
|
||||
@webViewImpl = webViewImpl
|
||||
|
||||
getValue: ->
|
||||
return '' unless @validPartitionId
|
||||
(if @persistStorage then 'persist:' else '') + @storagePartitionId
|
||||
|
||||
setValue: (value) ->
|
||||
result = {}
|
||||
hasNavigated = !@webViewImpl.beforeFirstNavigation
|
||||
if hasNavigated
|
||||
result.error = webViewConstants.ERROR_MSG_ALREADY_NAVIGATED
|
||||
return result
|
||||
value = '' unless value
|
||||
LEN = 'persist:'.length
|
||||
if value.substr(0, LEN) == 'persist:'
|
||||
value = value.substr LEN
|
||||
unless value
|
||||
@validPartitionId = false
|
||||
result.error = webViewConstants.ERROR_MSG_INVALID_PARTITION_ATTRIBUTE
|
||||
return result
|
||||
@persistStorage = true
|
||||
else
|
||||
@persistStorage = false
|
||||
@storagePartitionId = value
|
||||
result
|
||||
|
||||
# Sets up all of the webview attributes.
|
||||
WebView::setupWebViewAttributes = ->
|
||||
@attributes = {}
|
||||
|
||||
# Initialize the attributes with special behavior (and custom attribute
|
||||
# objects).
|
||||
@attributes[webViewConstants.ATTRIBUTE_PARTITION] = new Partition(this)
|
||||
|
||||
# Initialize the remaining attributes, which have default behavior.
|
||||
defaultAttributes = [
|
||||
webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY
|
||||
webViewConstants.ATTRIBUTE_AUTOSIZE
|
||||
webViewConstants.ATTRIBUTE_MAXHEIGHT
|
||||
webViewConstants.ATTRIBUTE_MAXWIDTH
|
||||
webViewConstants.ATTRIBUTE_MINHEIGHT
|
||||
webViewConstants.ATTRIBUTE_MINWIDTH
|
||||
webViewConstants.ATTRIBUTE_SRC
|
||||
webViewConstants.ATTRIBUTE_HTTPREFERRER
|
||||
]
|
||||
|
||||
for attribute in defaultAttributes
|
||||
@attributes[attribute] = new WebViewAttribute(attribute, this)
|
|
@ -6,11 +6,17 @@ module.exports =
|
|||
ATTRIBUTE_MAXWIDTH: 'maxwidth'
|
||||
ATTRIBUTE_MINHEIGHT: 'minheight'
|
||||
ATTRIBUTE_MINWIDTH: 'minwidth'
|
||||
ATTRIBUTE_NAME: 'name'
|
||||
ATTRIBUTE_PARTITION: 'partition'
|
||||
ATTRIBUTE_SRC: 'src'
|
||||
ATTRIBUTE_HTTPREFERRER: 'httpreferrer'
|
||||
ATTRIBUTE_NODEINTEGRATION: 'nodeintegration'
|
||||
ATTRIBUTE_PLUGINS: 'plugins'
|
||||
ATTRIBUTE_PRELOAD: 'preload'
|
||||
|
||||
# Internal attribute.
|
||||
ATTRIBUTE_INTERNALINSTANCEID: 'internalinstanceid'
|
||||
|
||||
# Error messages.
|
||||
ERROR_MSG_ALREADY_NAVIGATED: 'The object has already navigated, so its partition cannot be changed.'
|
||||
ERROR_MSG_CANNOT_INJECT_SCRIPT: '<webview>: ' +
|
||||
|
|
|
@ -4,6 +4,7 @@ webViewConstants = require './web-view-constants'
|
|||
webFrame = require 'web-frame'
|
||||
remote = require 'remote'
|
||||
|
||||
# Attributes.
|
||||
AUTO_SIZE_ATTRIBUTES = [
|
||||
webViewConstants.ATTRIBUTE_AUTOSIZE,
|
||||
webViewConstants.ATTRIBUTE_MAXHEIGHT,
|
||||
|
@ -16,38 +17,6 @@ AUTO_SIZE_ATTRIBUTES = [
|
|||
nextId = 0
|
||||
getNextId = -> ++nextId
|
||||
|
||||
# Represents the state of the storage partition.
|
||||
class Partition
|
||||
constructor: ->
|
||||
@validPartitionId = true
|
||||
@persistStorage = false
|
||||
@storagePartitionId = ''
|
||||
|
||||
toAttribute: ->
|
||||
return '' unless @validPartitionId
|
||||
(if @persistStorage then 'persist:' else '') + @storagePartitionId
|
||||
|
||||
fromAttribute: (value, hasNavigated) ->
|
||||
result = {}
|
||||
if hasNavigated
|
||||
result.error = webViewConstants.ERROR_MSG_ALREADY_NAVIGATED
|
||||
return result
|
||||
value ?= ''
|
||||
|
||||
LEN = 'persist:'.length
|
||||
if value.substr(0, LEN) == 'persist:'
|
||||
value = value.substr LEN
|
||||
unless value
|
||||
@validPartitionId = false
|
||||
result.error = webViewConstants.ERROR_MSG_INVALID_PARTITION_ATTRIBUTE
|
||||
return result
|
||||
@persistStorage = true
|
||||
else
|
||||
@persistStorage = false
|
||||
|
||||
@storagePartitionId = value
|
||||
result
|
||||
|
||||
# Represents the internal state of the WebView node.
|
||||
class WebView
|
||||
constructor: (@webviewNode) ->
|
||||
|
@ -70,8 +39,7 @@ class WebView
|
|||
|
||||
@browserPluginNode = @createBrowserPluginNode()
|
||||
shadowRoot = @webviewNode.createShadowRoot()
|
||||
@partition = new Partition()
|
||||
|
||||
@setupWebViewAttributes()
|
||||
@setupWebViewSrcAttributeMutationObserver()
|
||||
@setupFocusPropagation()
|
||||
@setupWebviewNodeProperties()
|
||||
|
@ -107,7 +75,7 @@ class WebView
|
|||
@guestInstanceId = undefined
|
||||
@beforeFirstNavigation = true
|
||||
@validPartitionId = true
|
||||
@partition.validPartitionId = true
|
||||
@attributes[webViewConstants.ATTRIBUTE_PARTITION].validPartitionId = true
|
||||
@contentWindow = null
|
||||
@internalInstanceId = 0
|
||||
|
||||
|
@ -135,9 +103,9 @@ class WebView
|
|||
|
||||
setupAutoSizeProperties: ->
|
||||
for attributeName in AUTO_SIZE_ATTRIBUTES
|
||||
this[attributeName] = @webviewNode.getAttribute attributeName
|
||||
@attributes[attributeName].setValue @webviewNode.getAttribute(attributeName)
|
||||
Object.defineProperty @webviewNode, attributeName,
|
||||
get: => this[attributeName]
|
||||
get: => @attributes[attributeName].getValue()
|
||||
set: (value) => @webviewNode.setAttribute attributeName, value
|
||||
enumerable: true
|
||||
|
||||
|
@ -145,7 +113,7 @@ class WebView
|
|||
@setupAutoSizeProperties()
|
||||
|
||||
Object.defineProperty @webviewNode, webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY,
|
||||
get: => @allowtransparency
|
||||
get: => @attributes[webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY].getValue()
|
||||
set: (value) =>
|
||||
@webviewNode.setAttribute webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY, value
|
||||
enumerable: true
|
||||
|
@ -159,25 +127,24 @@ class WebView
|
|||
# No setter.
|
||||
enumerable: true
|
||||
|
||||
Object.defineProperty @webviewNode, 'partition',
|
||||
get: => @partition.toAttribute()
|
||||
Object.defineProperty @webviewNode, webViewConstants.ATTRIBUTE_PARTITION,
|
||||
get: => @attributes[webViewConstants.ATTRIBUTE_PARTITION].getValue()
|
||||
set: (value) =>
|
||||
result = @partition.fromAttribute value, @hasNavigated()
|
||||
result = @attributes[webViewConstants.ATTRIBUTE_PARTITION].setValue value
|
||||
throw result.error if result.error?
|
||||
@webviewNode.setAttribute 'partition', value
|
||||
@webviewNode.setAttribute webViewConstants.ATTRIBUTE_PARTITION, value
|
||||
enumerable: true
|
||||
|
||||
@src = @webviewNode.getAttribute 'src'
|
||||
Object.defineProperty @webviewNode, 'src',
|
||||
get: => @src
|
||||
set: (value) => @webviewNode.setAttribute 'src', value
|
||||
# No setter.
|
||||
@attributes[webViewConstants.ATTRIBUTE_SRC].setValue @webviewNode.getAttribute(webViewConstants.ATTRIBUTE_SRC)
|
||||
Object.defineProperty @webviewNode, webViewConstants.ATTRIBUTE_SRC,
|
||||
get: => @attributes[webViewConstants.ATTRIBUTE_SRC].getValue()
|
||||
set: (value) => @webviewNode.setAttribute webViewConstants.ATTRIBUTE_SRC, value
|
||||
enumerable: true
|
||||
|
||||
@httpreferrer = @webviewNode.getAttribute 'httpreferrer'
|
||||
Object.defineProperty @webviewNode, 'httpreferrer',
|
||||
get: => @httpreferrer
|
||||
set: (value) => @webviewNode.setAttribute 'httpreferrer', value
|
||||
@attributes[webViewConstants.ATTRIBUTE_HTTPREFERRER].setValue @webviewNode.getAttribute(webViewConstants.ATTRIBUTE_HTTPREFERRER)
|
||||
Object.defineProperty @webviewNode, webViewConstants.ATTRIBUTE_HTTPREFERRER,
|
||||
get: => @attributes[webViewConstants.ATTRIBUTE_HTTPREFERRER].getValue()
|
||||
set: (value) => @webviewNode.setAttribute webViewConstants.ATTRIBUTE_HTTPREFERRER, value
|
||||
enumerable: true
|
||||
|
||||
# The purpose of this mutation observer is to catch assignment to the src
|
||||
|
@ -194,7 +161,11 @@ class WebView
|
|||
params =
|
||||
attributes: true,
|
||||
attributeOldValue: true,
|
||||
attributeFilter: ['src', 'partition', 'httpreferrer']
|
||||
attributeFilter: [
|
||||
webViewConstants.ATTRIBUTE_SRC
|
||||
webViewConstants.ATTRIBUTE_PARTITION
|
||||
webViewConstants.ATTRIBUTE_HTTPREFERRER
|
||||
]
|
||||
@srcAndPartitionObserver.observe @webviewNode, params
|
||||
|
||||
# This observer monitors mutations to attributes of the <webview> and
|
||||
|
@ -204,18 +175,18 @@ class WebView
|
|||
# details.
|
||||
handleWebviewAttributeMutation: (name, oldValue, newValue) ->
|
||||
if name in AUTO_SIZE_ATTRIBUTES
|
||||
this[name] = newValue
|
||||
@attributes[name].setValue newValue
|
||||
return unless @guestInstanceId
|
||||
# Convert autosize attribute to boolean.
|
||||
autosize = @webviewNode.hasAttribute webViewConstants.ATTRIBUTE_AUTOSIZE
|
||||
guestViewInternal.setAutoSize @guestInstanceId,
|
||||
enableAutoSize: autosize,
|
||||
min:
|
||||
width: parseInt @minwidth || 0
|
||||
height: parseInt @minheight || 0
|
||||
width: parseInt @attributes[webViewConstants.ATTRIBUTE_MINWIDTH].getValue() || 0
|
||||
height: parseInt @attributes[webViewConstants.ATTRIBUTE_MINHEIGHT].getValue() || 0
|
||||
max:
|
||||
width: parseInt @maxwidth || 0
|
||||
height: parseInt @maxheight || 0
|
||||
width: parseInt @attributes[webViewConstants.ATTRIBUTE_MAXWIDTH].getValue() || 0
|
||||
height: parseInt @attributes[webViewConstants.ATTRIBUTE_MAXHEIGHT].getValue() || 0
|
||||
else if name is webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY
|
||||
# We treat null attribute (attribute removed) and the empty string as
|
||||
# one case.
|
||||
|
@ -223,19 +194,19 @@ class WebView
|
|||
newValue ?= ''
|
||||
|
||||
return if oldValue is newValue
|
||||
@allowtransparency = newValue != ''
|
||||
@attributes[webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY].setValue(newValue != '')
|
||||
|
||||
return unless @guestInstanceId
|
||||
|
||||
guestViewInternal.setAllowTransparency @guestInstanceId, @allowtransparency
|
||||
else if name is 'httpreferrer'
|
||||
guestViewInternal.setAllowTransparency @guestInstanceId, @attributes[webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY].getValue()
|
||||
else if name is webViewConstants.ATTRIBUTE_HTTPREFERRER
|
||||
oldValue ?= ''
|
||||
newValue ?= ''
|
||||
|
||||
if newValue == '' and oldValue != ''
|
||||
@webviewNode.setAttribute 'httpreferrer', oldValue
|
||||
@webviewNode.setAttribute webViewConstants.ATTRIBUTE_HTTPREFERRER, oldValue
|
||||
|
||||
@httpreferrer = newValue
|
||||
@attributes[webViewConstants.ATTRIBUTE_HTTPREFERRER].setValue newValue
|
||||
|
||||
result = {}
|
||||
# If the httpreferrer changes treat it as though the src changes and reload
|
||||
|
@ -243,7 +214,7 @@ class WebView
|
|||
@parseSrcAttribute result
|
||||
|
||||
throw result.error if result.error?
|
||||
else if name is 'src'
|
||||
else if name is webViewConstants.ATTRIBUTE_SRC
|
||||
# We treat null attribute (attribute removed) and the empty string as
|
||||
# one case.
|
||||
oldValue ?= ''
|
||||
|
@ -256,7 +227,7 @@ class WebView
|
|||
# the next src attribute handler call to avoid reloading the page
|
||||
# on every guest-initiated navigation.
|
||||
@ignoreNextSrcAttributeChange = true
|
||||
@webviewNode.setAttribute 'src', oldValue
|
||||
@webviewNode.setAttribute webViewConstants.ATTRIBUTE_SRC, oldValue
|
||||
@src = newValue
|
||||
if @ignoreNextSrcAttributeChange
|
||||
# Don't allow the src mutation observer to see this change.
|
||||
|
@ -267,13 +238,13 @@ class WebView
|
|||
@parseSrcAttribute result
|
||||
|
||||
throw result.error if result.error?
|
||||
else if name is 'partition'
|
||||
else if name is webViewConstants.ATTRIBUTE_PARTITION
|
||||
# Note that throwing error here won't synchronously propagate.
|
||||
@partition.fromAttribute newValue, @hasNavigated()
|
||||
@attributes[webViewConstants.ATTRIBUTE_PARTITION].setValue newValue
|
||||
|
||||
handleBrowserPluginAttributeMutation: (name, oldValue, newValue) ->
|
||||
if name is 'internalinstanceid' and !oldValue and !!newValue
|
||||
@browserPluginNode.removeAttribute 'internalinstanceid'
|
||||
if name is webViewConstants.ATTRIBUTE_INTERNALINSTANCEID and !oldValue and !!newValue
|
||||
@browserPluginNode.removeAttribute webViewConstants.ATTRIBUTE_INTERNALINSTANCEID
|
||||
@internalInstanceId = parseInt newValue
|
||||
|
||||
if !!@guestInstanceId and @guestInstanceId != 0
|
||||
|
@ -337,12 +308,12 @@ class WebView
|
|||
not @beforeFirstNavigation
|
||||
|
||||
parseSrcAttribute: (result) ->
|
||||
unless @partition.validPartitionId
|
||||
unless @attributes[webViewConstants.ATTRIBUTE_PARTITION].validPartitionId
|
||||
result.error = webViewConstants.ERROR_MSG_INVALID_PARTITION_ATTRIBUTE
|
||||
return
|
||||
@src = @webviewNode.getAttribute 'src'
|
||||
@attributes[webViewConstants.ATTRIBUTE_SRC].setValue @webviewNode.getAttribute(webViewConstants.ATTRIBUTE_SRC)
|
||||
|
||||
return unless @src
|
||||
return unless @attributes[webViewConstants.ATTRIBUTE_SRC].getValue()
|
||||
|
||||
unless @guestInstanceId?
|
||||
if @beforeFirstNavigation
|
||||
|
@ -351,14 +322,15 @@ class WebView
|
|||
return
|
||||
|
||||
# Navigate to |this.src|.
|
||||
urlOptions = if @httpreferrer then {@httpreferrer} else {}
|
||||
remote.getGuestWebContents(@guestInstanceId).loadUrl @src, urlOptions
|
||||
httpreferrer = @attributes[webViewConstants.ATTRIBUTE_HTTPREFERRER].getValue()
|
||||
urlOptions = if httpreferrer then {httpreferrer} else {}
|
||||
remote.getGuestWebContents(@guestInstanceId).loadUrl @attributes[webViewConstants.ATTRIBUTE_SRC].getValue(), urlOptions
|
||||
|
||||
parseAttributes: ->
|
||||
return unless @elementAttached
|
||||
hasNavigated = @hasNavigated()
|
||||
attributeValue = @webviewNode.getAttribute 'partition'
|
||||
result = @partition.fromAttribute attributeValue, hasNavigated
|
||||
attributeValue = @webviewNode.getAttribute webViewConstants.ATTRIBUTE_PARTITION
|
||||
result = @attributes[webViewConstants.ATTRIBUTE_PARTITION].setValue attributeValue
|
||||
@parseSrcAttribute result
|
||||
|
||||
createGuest: ->
|
||||
|
@ -408,34 +380,34 @@ class WebView
|
|||
|
||||
# Updates state upon loadcommit.
|
||||
onLoadCommit: (@baseUrlForDataUrl, @currentEntryIndex, @entryCount, @processId, url, isTopLevel) ->
|
||||
oldValue = @webviewNode.getAttribute 'src'
|
||||
oldValue = @webviewNode.getAttribute webViewConstants.ATTRIBUTE_SRC
|
||||
newValue = url
|
||||
if isTopLevel and (oldValue != newValue)
|
||||
# Touching the src attribute triggers a navigation. To avoid
|
||||
# triggering a page reload on every guest-initiated navigation,
|
||||
# we use the flag ignoreNextSrcAttributeChange here.
|
||||
this.ignoreNextSrcAttributeChange = true
|
||||
this.webviewNode.setAttribute 'src', newValue
|
||||
this.webviewNode.setAttribute webViewConstants.ATTRIBUTE_SRC, newValue
|
||||
|
||||
onAttach: (storagePartitionId) ->
|
||||
@webviewNode.setAttribute 'partition', storagePartitionId
|
||||
@partition.fromAttribute storagePartitionId, this.hasNavigated()
|
||||
@webviewNode.setAttribute webViewConstants.ATTRIBUTE_PARTITION, storagePartitionId
|
||||
@attributes[webViewConstants.ATTRIBUTE_PARTITION].setValue storagePartitionId
|
||||
|
||||
buildAttachParams: (isNewWindow) ->
|
||||
allowtransparency: @allowtransparency || false
|
||||
allowtransparency: @attributes[webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY].getValue() || false
|
||||
autosize: @webviewNode.hasAttribute webViewConstants.ATTRIBUTE_AUTOSIZE
|
||||
instanceId: @viewInstanceId
|
||||
maxheight: parseInt @maxheight || 0
|
||||
maxwidth: parseInt @maxwidth || 0
|
||||
minheight: parseInt @minheight || 0
|
||||
minwidth: parseInt @minwidth || 0
|
||||
maxheight: parseInt @attributes[webViewConstants.ATTRIBUTE_MAXHEIGHT].getValue() || 0
|
||||
maxwidth: parseInt @attributes[webViewConstants.ATTRIBUTE_MAXWIDTH].getValue() || 0
|
||||
minheight: parseInt @attributes[webViewConstants.ATTRIBUTE_MINHEIGHT].getValue() || 0
|
||||
minwidth: parseInt @attributes[webViewConstants.ATTRIBUTE_MINWIDTH].getValue() || 0
|
||||
# We don't need to navigate new window from here.
|
||||
src: if isNewWindow then undefined else @src
|
||||
src: if isNewWindow then undefined else @attributes[webViewConstants.ATTRIBUTE_SRC].getValue()
|
||||
# If we have a partition from the opener, that will also be already
|
||||
# set via this.onAttach().
|
||||
storagePartitionId: @partition.toAttribute()
|
||||
storagePartitionId: @attributes[webViewConstants.ATTRIBUTE_PARTITION].getValue()
|
||||
userAgentOverride: @userAgentOverride
|
||||
httpreferrer: @httpreferrer
|
||||
httpreferrer: @attributes[webViewConstants.ATTRIBUTE_HTTPREFERRER].getValue()
|
||||
|
||||
attachWindow: (guestInstanceId, isNewWindow) ->
|
||||
@guestInstanceId = guestInstanceId
|
||||
|
@ -552,3 +524,5 @@ listener = (event) ->
|
|||
registerWebViewElement()
|
||||
window.removeEventListener event.type, listener, useCapture
|
||||
window.addEventListener 'readystatechange', listener, true
|
||||
|
||||
module.exports = WebView
|
||||
|
|
Loading…
Add table
Reference in a new issue