228 lines
8.7 KiB
CoffeeScript
228 lines
8.7 KiB
CoffeeScript
WebViewImpl = require './web-view'
|
|
guestViewInternal = require './guest-view-internal'
|
|
webViewConstants = require './web-view-constants'
|
|
remote = require 'remote'
|
|
|
|
# Helper function to resolve url set in attribute.
|
|
a = document.createElement 'a'
|
|
resolveUrl = (url) ->
|
|
a.href = url
|
|
a.href
|
|
|
|
# Attribute objects.
|
|
# Default implementation of a WebView attribute.
|
|
class WebViewAttribute
|
|
constructor: (name, webViewImpl) ->
|
|
@name = name
|
|
@webViewImpl = webViewImpl
|
|
@ignoreMutation = false
|
|
|
|
@defineProperty()
|
|
|
|
# Retrieves and returns the attribute's value.
|
|
getValue: -> @webViewImpl.webviewNode.getAttribute(@name) || ''
|
|
|
|
# Sets the attribute's value.
|
|
setValue: (value) -> @webViewImpl.webviewNode.setAttribute(@name, value || '')
|
|
|
|
# Changes the attribute's value without triggering its mutation handler.
|
|
setValueIgnoreMutation: (value) ->
|
|
@ignoreMutation = true
|
|
@setValue value
|
|
@ignoreMutation = false
|
|
|
|
# Defines this attribute as a property on the webview node.
|
|
defineProperty: ->
|
|
Object.defineProperty @webViewImpl.webviewNode, @name,
|
|
get: => @getValue()
|
|
set: (value) => @setValue value
|
|
enumerable: true
|
|
|
|
# Called when the attribute's value changes.
|
|
handleMutation: ->
|
|
|
|
# An attribute that is treated as a Boolean.
|
|
class BooleanAttribute extends WebViewAttribute
|
|
constructor: (name, webViewImpl) ->
|
|
super name, webViewImpl
|
|
|
|
getValue: -> @webViewImpl.webviewNode.hasAttribute @name
|
|
|
|
setValue: (value) ->
|
|
unless value
|
|
@webViewImpl.webviewNode.removeAttribute @name
|
|
else
|
|
@webViewImpl.webviewNode.setAttribute @name, ''
|
|
|
|
# Attribute that specifies whether transparency is allowed in the webview.
|
|
class AllowTransparencyAttribute extends BooleanAttribute
|
|
constructor: (webViewImpl) ->
|
|
super webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY, webViewImpl
|
|
|
|
handleMutation: (oldValue, newValue) ->
|
|
return unless @webViewImpl.guestInstanceId
|
|
guestViewInternal.setAllowTransparency @webViewImpl.guestInstanceId, @getValue()
|
|
|
|
# Attribute used to define the demension limits of autosizing.
|
|
class AutosizeDimensionAttribute extends WebViewAttribute
|
|
constructor: (name, webViewImpl) ->
|
|
super name, webViewImpl
|
|
|
|
getValue: -> parseInt(@webViewImpl.webviewNode.getAttribute(@name)) || 0
|
|
|
|
handleMutation: (oldValue, newValue) ->
|
|
return unless @webViewImpl.guestInstanceId
|
|
guestViewInternal.setSize @webViewImpl.guestInstanceId,
|
|
enableAutoSize: @webViewImpl.attributes[webViewConstants.ATTRIBUTE_AUTOSIZE].getValue()
|
|
min:
|
|
width: parseInt @webViewImpl.attributes[webViewConstants.ATTRIBUTE_MINWIDTH].getValue() || 0
|
|
height: parseInt @webViewImpl.attributes[webViewConstants.ATTRIBUTE_MINHEIGHT].getValue() || 0
|
|
max:
|
|
width: parseInt @webViewImpl.attributes[webViewConstants.ATTRIBUTE_MAXWIDTH].getValue() || 0
|
|
height: parseInt @webViewImpl.attributes[webViewConstants.ATTRIBUTE_MAXHEIGHT].getValue() || 0
|
|
|
|
# Attribute that specifies whether the webview should be autosized.
|
|
class AutosizeAttribute extends BooleanAttribute
|
|
constructor: (webViewImpl) ->
|
|
super webViewConstants.ATTRIBUTE_AUTOSIZE, webViewImpl
|
|
|
|
handleMutation: AutosizeDimensionAttribute::handleMutation
|
|
|
|
# Attribute representing the state of the storage partition.
|
|
class PartitionAttribute extends WebViewAttribute
|
|
constructor: (webViewImpl) ->
|
|
super webViewConstants.ATTRIBUTE_PARTITION, webViewImpl
|
|
@validPartitionId = true
|
|
|
|
handleMutation: (oldValue, newValue) ->
|
|
newValue = newValue || ''
|
|
|
|
# The partition cannot change if the webview has already navigated.
|
|
unless @webViewImpl.beforeFirstNavigation
|
|
window.console.error webViewConstants.ERROR_MSG_ALREADY_NAVIGATED
|
|
@setValueIgnoreMutation oldValue
|
|
return
|
|
|
|
if newValue is 'persist:'
|
|
@validPartitionId = false
|
|
window.console.error webViewConstants.ERROR_MSG_INVALID_PARTITION_ATTRIBUTE
|
|
|
|
# Attribute that handles the location and navigation of the webview.
|
|
class SrcAttribute extends WebViewAttribute
|
|
constructor: (webViewImpl) ->
|
|
super webViewConstants.ATTRIBUTE_SRC, webViewImpl
|
|
@setupMutationObserver()
|
|
|
|
getValue: ->
|
|
if @webViewImpl.webviewNode.hasAttribute @name
|
|
resolveUrl @webViewImpl.webviewNode.getAttribute(@name)
|
|
else
|
|
''
|
|
|
|
setValueIgnoreMutation: (value) ->
|
|
WebViewAttribute::setValueIgnoreMutation value
|
|
# takeRecords() is needed to clear queued up src mutations. Without it, it
|
|
# is possible for this change to get picked up asyncronously by src's
|
|
# mutation observer |observer|, and then get handled even though we do not
|
|
# want to handle this mutation.
|
|
@observer.takeRecords()
|
|
|
|
handleMutation: (oldValue, newValue) ->
|
|
# Once we have navigated, we don't allow clearing the src attribute.
|
|
# Once <webview> enters a navigated state, it cannot return to a
|
|
# placeholder state.
|
|
if not newValue and oldValue
|
|
# src attribute changes normally initiate a navigation. We suppress
|
|
# the next src attribute handler call to avoid reloading the page
|
|
# on every guest-initiated navigation.
|
|
@setValueIgnoreMutation oldValue
|
|
return
|
|
@parse()
|
|
|
|
# The purpose of this mutation observer is to catch assignment to the src
|
|
# attribute without any changes to its value. This is useful in the case
|
|
# where the webview guest has crashed and navigating to the same address
|
|
# spawns off a new process.
|
|
setupMutationObserver: ->
|
|
@observer = new MutationObserver (mutations) =>
|
|
for mutation in mutations
|
|
oldValue = mutation.oldValue
|
|
newValue = @getValue()
|
|
return if oldValue isnt newValue
|
|
@handleMutation oldValue, newValue
|
|
params =
|
|
attributes: true,
|
|
attributeOldValue: true,
|
|
attributeFilter: [@name]
|
|
@observer.observe @webViewImpl.webviewNode, params
|
|
|
|
parse: ->
|
|
if not @webViewImpl.elementAttached or
|
|
not @webViewImpl.attributes[webViewConstants.ATTRIBUTE_PARTITION].validPartitionId or
|
|
not @.getValue()
|
|
return
|
|
|
|
unless @webViewImpl.guestInstanceId?
|
|
if @webViewImpl.beforeFirstNavigation
|
|
@webViewImpl.beforeFirstNavigation = false
|
|
@webViewImpl.createGuest()
|
|
return
|
|
|
|
# Navigate to |this.src|.
|
|
opts = {}
|
|
httpreferrer = @webViewImpl.attributes[webViewConstants.ATTRIBUTE_HTTPREFERRER].getValue()
|
|
if httpreferrer then opts.httpReferrer = httpreferrer
|
|
|
|
useragent = @webViewImpl.attributes[webViewConstants.ATTRIBUTE_USERAGENT].getValue()
|
|
if useragent then opts.userAgent = useragent
|
|
|
|
guestContents = remote.getGuestWebContents(@webViewImpl.guestInstanceId)
|
|
guestContents.loadUrl @getValue(), opts
|
|
|
|
# Attribute specifies HTTP referrer.
|
|
class HttpReferrerAttribute extends WebViewAttribute
|
|
constructor: (webViewImpl) ->
|
|
super webViewConstants.ATTRIBUTE_HTTPREFERRER, webViewImpl
|
|
|
|
# Attribute specifies user agent
|
|
class UserAgentAttribute extends WebViewAttribute
|
|
constructor: (webViewImpl) ->
|
|
super webViewConstants.ATTRIBUTE_USERAGENT, webViewImpl
|
|
|
|
# Attribute that set preload script.
|
|
class PreloadAttribute extends WebViewAttribute
|
|
constructor: (webViewImpl) ->
|
|
super webViewConstants.ATTRIBUTE_PRELOAD, webViewImpl
|
|
|
|
getValue: ->
|
|
return '' unless @webViewImpl.webviewNode.hasAttribute @name
|
|
preload = resolveUrl @webViewImpl.webviewNode.getAttribute(@name)
|
|
protocol = preload.substr 0, 5
|
|
unless protocol is 'file:'
|
|
console.error webViewConstants.ERROR_MSG_INVALID_PRELOAD_ATTRIBUTE
|
|
preload = ''
|
|
preload
|
|
|
|
# Sets up all of the webview attributes.
|
|
WebViewImpl::setupWebViewAttributes = ->
|
|
@attributes = {}
|
|
|
|
@attributes[webViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY] = new AllowTransparencyAttribute(this)
|
|
@attributes[webViewConstants.ATTRIBUTE_AUTOSIZE] = new AutosizeAttribute(this)
|
|
@attributes[webViewConstants.ATTRIBUTE_PARTITION] = new PartitionAttribute(this)
|
|
@attributes[webViewConstants.ATTRIBUTE_SRC] = new SrcAttribute(this)
|
|
@attributes[webViewConstants.ATTRIBUTE_HTTPREFERRER] = new HttpReferrerAttribute(this)
|
|
@attributes[webViewConstants.ATTRIBUTE_USERAGENT] = new UserAgentAttribute(this)
|
|
@attributes[webViewConstants.ATTRIBUTE_NODEINTEGRATION] = new BooleanAttribute(webViewConstants.ATTRIBUTE_NODEINTEGRATION, this)
|
|
@attributes[webViewConstants.ATTRIBUTE_PLUGINS] = new BooleanAttribute(webViewConstants.ATTRIBUTE_PLUGINS, this)
|
|
@attributes[webViewConstants.ATTRIBUTE_DISABLEWEBSECURITY] = new BooleanAttribute(webViewConstants.ATTRIBUTE_DISABLEWEBSECURITY, this)
|
|
@attributes[webViewConstants.ATTRIBUTE_PRELOAD] = new PreloadAttribute(this)
|
|
|
|
autosizeAttributes = [
|
|
webViewConstants.ATTRIBUTE_MAXHEIGHT
|
|
webViewConstants.ATTRIBUTE_MAXWIDTH
|
|
webViewConstants.ATTRIBUTE_MINHEIGHT
|
|
webViewConstants.ATTRIBUTE_MINWIDTH
|
|
]
|
|
for attribute in autosizeAttributes
|
|
@attributes[attribute] = new AutosizeDimensionAttribute(attribute, this)
|