diff options
Diffstat (limited to 'chromium/chrome/renderer/resources/extensions/ad_view.js')
-rw-r--r-- | chromium/chrome/renderer/resources/extensions/ad_view.js | 498 |
1 files changed, 0 insertions, 498 deletions
diff --git a/chromium/chrome/renderer/resources/extensions/ad_view.js b/chromium/chrome/renderer/resources/extensions/ad_view.js deleted file mode 100644 index da7792c1ac1..00000000000 --- a/chromium/chrome/renderer/resources/extensions/ad_view.js +++ /dev/null @@ -1,498 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Shim that simulates a <adview> tag via Mutation Observers. -// -// The actual tag is implemented via the browser plugin. The internals of this -// are hidden via Shadow DOM. - -// TODO(rpaquay): This file is currently very similar to "web_view.js". Do we -// want to refactor to extract common pieces? - -var eventBindings = require('event_bindings'); -var process = requireNative('process'); -var addTagWatcher = require('tagWatcher').addTagWatcher; - -/** - * Define "allowCustomAdNetworks" function such that the - * "kEnableAdviewSrcAttribute" flag is respected. - */ -function allowCustomAdNetworks() { - return process.HasSwitch('enable-adview-src-attribute'); -} - -/** - * List of attribute names to "blindly" sync between <adview> tag and internal - * browser plugin. - */ -var AD_VIEW_ATTRIBUTES = [ - 'name', -]; - -/** - * List of custom attributes (and their behavior). - * - * name: attribute name. - * onMutation(adview, mutation): callback invoked when attribute is mutated. - * isProperty: True if the attribute should be exposed as a property. - */ -var AD_VIEW_CUSTOM_ATTRIBUTES = [ - { - name: 'ad-network', - onMutation: function(adview, mutation) { - adview.handleAdNetworkMutation(mutation); - }, - isProperty: function() { - return true; - } - }, - { - name: 'src', - onMutation: function(adview, mutation) { - adview.handleSrcMutation(mutation); - }, - isProperty: function() { - return allowCustomAdNetworks(); - } - } -]; - -/** - * List of api methods. These are forwarded to the browser plugin. - */ -var AD_VIEW_API_METHODS = [ - // Empty for now. -]; - -var createEvent = function(name) { - var eventOpts = {supportsListeners: true, supportsFilters: true}; - return new eventBindings.Event(name, undefined, eventOpts); -}; - -var AdviewLoadAbortEvent = createEvent('adview.onLoadAbort'); -var AdviewLoadCommitEvent = createEvent('adview.onLoadCommit'); - -var AD_VIEW_EXT_EVENTS = { - 'loadabort': { - evt: AdviewLoadAbortEvent, - fields: ['url', 'isTopLevel', 'reason'] - }, - 'loadcommit': { - customHandler: function(adview, event) { - if (event.isTopLevel) { - adview.browserPluginNode_.setAttribute('src', event.url); - } - }, - evt: AdviewLoadCommitEvent, - fields: ['url', 'isTopLevel'] - } -}; - -/** - * List of supported ad-networks. - * - * name: identifier of the ad-network, corresponding to a valid value - * of the "ad-network" attribute of an <adview> element. - * url: url to navigate to when initially displaying the <adview>. - * origin: origin of urls the <adview> is allowed navigate to. - */ -var AD_VIEW_AD_NETWORKS_WHITELIST = [ - { - name: 'admob', - url: 'https://admob-sdk.doubleclick.net/chromeapps', - origin: 'https://double.net' - }, -]; - -/** - * Return the whitelisted ad-network entry named |name|. - */ -function getAdNetworkInfo(name) { - var result = null; - $Array.forEach(AD_VIEW_AD_NETWORKS_WHITELIST, function(item) { - if (item.name === name) - result = item; - }); - return result; -} - -/** - * @constructor - */ -function AdView(adviewNode) { - this.adviewNode_ = adviewNode; - this.browserPluginNode_ = this.createBrowserPluginNode_(); - var shadowRoot = this.adviewNode_.webkitCreateShadowRoot(); - shadowRoot.appendChild(this.browserPluginNode_); - - this.setupCustomAttributes_(); - this.setupAdviewNodeObservers_(); - this.setupAdviewNodeMethods_(); - this.setupAdviewNodeProperties_(); - this.setupAdviewNodeEvents_(); - this.setupBrowserPluginNodeObservers_(); -} - -/** - * @private - */ -AdView.prototype.createBrowserPluginNode_ = function() { - var browserPluginNode = document.createElement('object'); - browserPluginNode.type = 'application/browser-plugin'; - // The <object> node fills in the <adview> container. - browserPluginNode.style.width = '100%'; - browserPluginNode.style.height = '100%'; - $Array.forEach(AD_VIEW_ATTRIBUTES, function(attributeName) { - // Only copy attributes that have been assigned values, rather than copying - // a series of undefined attributes to BrowserPlugin. - if (this.adviewNode_.hasAttribute(attributeName)) { - browserPluginNode.setAttribute( - attributeName, this.adviewNode_.getAttribute(attributeName)); - } - }, this); - - return browserPluginNode; -} - -/** - * @private - */ -AdView.prototype.setupCustomAttributes_ = function() { - $Array.forEach(AD_VIEW_CUSTOM_ATTRIBUTES, function(attributeInfo) { - if (attributeInfo.onMutation) { - attributeInfo.onMutation(this); - } - }, this); -} - -/** - * @private - */ -AdView.prototype.setupAdviewNodeMethods_ = function() { - // this.browserPluginNode_[apiMethod] are not necessarily defined immediately - // after the shadow object is appended to the shadow root. - var self = this; - $Array.forEach(AD_VIEW_API_METHODS, function(apiMethod) { - self.adviewNode_[apiMethod] = function(var_args) { - return $Function.apply(self.browserPluginNode_[apiMethod], - self.browserPluginNode_, arguments); - }; - }, this); -} - -/** - * @private - */ -AdView.prototype.setupAdviewNodeObservers_ = function() { - // Map attribute modifications on the <adview> tag to property changes in - // the underlying <object> node. - var handleMutation = $Function.bind(function(mutation) { - this.handleAdviewAttributeMutation_(mutation); - }, this); - var observer = new MutationObserver(function(mutations) { - $Array.forEach(mutations, handleMutation); - }); - observer.observe( - this.adviewNode_, - {attributes: true, attributeFilter: AD_VIEW_ATTRIBUTES}); - - this.setupAdviewNodeCustomObservers_(); -} - -/** - * @private - */ -AdView.prototype.setupAdviewNodeCustomObservers_ = function() { - var handleMutation = $Function.bind(function(mutation) { - this.handleAdviewCustomAttributeMutation_(mutation); - }, this); - var observer = new MutationObserver(function(mutations) { - $Array.forEach(mutations, handleMutation); - }); - var customAttributeNames = - AD_VIEW_CUSTOM_ATTRIBUTES.map(function(item) { return item.name; }); - observer.observe( - this.adviewNode_, - {attributes: true, attributeFilter: customAttributeNames}); -} - -/** - * @private - */ -AdView.prototype.setupBrowserPluginNodeObservers_ = function() { - var handleMutation = $Function.bind(function(mutation) { - this.handleBrowserPluginAttributeMutation_(mutation); - }, this); - var objectObserver = new MutationObserver(function(mutations) { - $Array.forEach(mutations, handleMutation); - }); - objectObserver.observe( - this.browserPluginNode_, - {attributes: true, attributeFilter: AD_VIEW_ATTRIBUTES}); -} - -/** - * @private - */ -AdView.prototype.setupAdviewNodeProperties_ = function() { - var browserPluginNode = this.browserPluginNode_; - // Expose getters and setters for the attributes. - $Array.forEach(AD_VIEW_ATTRIBUTES, function(attributeName) { - Object.defineProperty(this.adviewNode_, attributeName, { - get: function() { - return browserPluginNode[attributeName]; - }, - set: function(value) { - browserPluginNode[attributeName] = value; - }, - enumerable: true - }); - }, this); - - // Expose getters and setters for the custom attributes. - var adviewNode = this.adviewNode_; - $Array.forEach(AD_VIEW_CUSTOM_ATTRIBUTES, function(attributeInfo) { - if (attributeInfo.isProperty()) { - var attributeName = attributeInfo.name; - Object.defineProperty(this.adviewNode_, attributeName, { - get: function() { - return adviewNode.getAttribute(attributeName); - }, - set: function(value) { - adviewNode.setAttribute(attributeName, value); - }, - enumerable: true - }); - } - }, this); - - this.setupAdviewContentWindowProperty_(); -} - -/** - * @private - */ -AdView.prototype.setupAdviewContentWindowProperty_ = function() { - var browserPluginNode = this.browserPluginNode_; - // We cannot use {writable: true} property descriptor because we want dynamic - // getter value. - Object.defineProperty(this.adviewNode_, 'contentWindow', { - get: function() { - // TODO(fsamuel): This is a workaround to enable - // contentWindow.postMessage until http://crbug.com/152006 is fixed. - if (browserPluginNode.contentWindow) - return browserPluginNode.contentWindow.self; - console.error('contentWindow is not available at this time. ' + - 'It will become available when the page has finished loading.'); - }, - // No setter. - enumerable: true - }); -} - -/** - * @private - */ -AdView.prototype.handleAdviewAttributeMutation_ = function(mutation) { - // This observer monitors mutations to attributes of the <adview> and - // updates the BrowserPlugin properties accordingly. In turn, updating - // a BrowserPlugin property will update the corresponding BrowserPlugin - // attribute, if necessary. See BrowserPlugin::UpdateDOMAttribute for more - // details. - this.browserPluginNode_[mutation.attributeName] = - this.adviewNode_.getAttribute(mutation.attributeName); -}; - -/** - * @private - */ -AdView.prototype.handleAdviewCustomAttributeMutation_ = function(mutation) { - $Array.forEach(AD_VIEW_CUSTOM_ATTRIBUTES, function(item) { - if (mutation.attributeName.toUpperCase() == item.name.toUpperCase()) { - if (item.onMutation) { - $Function.bind(item.onMutation, item)(this, mutation); - } - } - }, this); -}; - -/** - * @private - */ -AdView.prototype.handleBrowserPluginAttributeMutation_ = function(mutation) { - // This observer monitors mutations to attributes of the BrowserPlugin and - // updates the <adview> attributes accordingly. - if (!this.browserPluginNode_.hasAttribute(mutation.attributeName)) { - // If an attribute is removed from the BrowserPlugin, then remove it - // from the <adview> as well. - this.adviewNode_.removeAttribute(mutation.attributeName); - } else { - // Update the <adview> attribute to match the BrowserPlugin attribute. - // Note: Calling setAttribute on <adview> will trigger its mutation - // observer which will then propagate that attribute to BrowserPlugin. In - // cases where we permit assigning a BrowserPlugin attribute the same value - // again (such as navigation when crashed), this could end up in an infinite - // loop. Thus, we avoid this loop by only updating the <adview> attribute - // if the BrowserPlugin attributes differs from it. - var oldValue = this.adviewNode_.getAttribute(mutation.attributeName); - var newValue = this.browserPluginNode_.getAttribute(mutation.attributeName); - if (newValue != oldValue) { - this.adviewNode_.setAttribute(mutation.attributeName, newValue); - } - } -}; - -/** - * @private - */ -AdView.prototype.navigateToUrl_ = function(url) { - var newValue = url; - var oldValue = this.browserPluginNode_.getAttribute('src'); - - if (newValue === oldValue) - return; - - if (url != null) { - // Note: Setting the 'src' property directly, as calling setAttribute has no - // effect due to implementation details of BrowserPlugin. - this.browserPluginNode_['src'] = url; - if (allowCustomAdNetworks()) { - this.adviewNode_.setAttribute('src', url); - } - } - else { - // Note: Setting the 'src' property directly, as calling setAttribute has no - // effect due to implementation details of BrowserPlugin. - // TODO(rpaquay): Due to another implementation detail of BrowserPlugin, - // this line will leave the "src" attribute value untouched. - this.browserPluginNode_['src'] = null; - if (allowCustomAdNetworks()) { - this.adviewNode_.removeAttribute('src'); - } - } -} - -/** - * @public - */ -AdView.prototype.handleAdNetworkMutation = function(mutation) { - if (this.adviewNode_.hasAttribute('ad-network')) { - var value = this.adviewNode_.getAttribute('ad-network'); - var item = getAdNetworkInfo(value); - if (item) { - this.navigateToUrl_(item.url); - } - else if (allowCustomAdNetworks()) { - console.log('The ad-network "' + value + '" is not recognized, ' + - 'but custom ad-networks are enabled.'); - - if (mutation) { - this.navigateToUrl_(''); - } - } - else { - // Ignore the new attribute value and set it to empty string. - // Avoid infinite loop by checking for empty string as new value. - if (value != '') { - console.error('The ad-network "' + value + '" is not recognized.'); - this.adviewNode_.setAttribute('ad-network', ''); - } - this.navigateToUrl_(''); - } - } - else { - this.navigateToUrl_(''); - } -} - -/** - * @public - */ -AdView.prototype.handleSrcMutation = function(mutation) { - if (allowCustomAdNetworks()) { - if (this.adviewNode_.hasAttribute('src')) { - var newValue = this.adviewNode_.getAttribute('src'); - // Note: Setting the 'src' property directly, as calling setAttribute has - // no effect due to implementation details of BrowserPlugin. - this.browserPluginNode_['src'] = newValue; - } - else { - // If an attribute is removed from the <adview>, then remove it - // from the BrowserPlugin as well. - // Note: Setting the 'src' property directly, as calling setAttribute has - // no effect due to implementation details of BrowserPlugin. - // TODO(rpaquay): Due to another implementation detail of BrowserPlugin, - // this line will leave the "src" attribute value untouched. - this.browserPluginNode_['src'] = null; - } - } - else { - if (this.adviewNode_.hasAttribute('src')) { - var value = this.adviewNode_.getAttribute('src'); - // Ignore the new attribute value and set it to empty string. - // Avoid infinite loop by checking for empty string as new value. - if (value != '') { - console.error('Setting the "src" attribute of an <adview> ' + - 'element is not supported. Use the "ad-network" attribute ' + - 'instead.'); - this.adviewNode_.setAttribute('src', ''); - } - } - } -} - -/** - * @private - */ -AdView.prototype.setupAdviewNodeEvents_ = function() { - var self = this; - var onInstanceIdAllocated = function(e) { - var detail = e.detail ? JSON.parse(e.detail) : {}; - self.instanceId_ = detail.windowId; - var params = { - 'api': 'adview' - }; - self.browserPluginNode_['-internal-attach'](params); - - for (var eventName in AD_VIEW_EXT_EVENTS) { - self.setupExtEvent_(eventName, AD_VIEW_EXT_EVENTS[eventName]); - } - }; - this.browserPluginNode_.addEventListener('-internal-instanceid-allocated', - onInstanceIdAllocated); -} - -/** - * @private - */ -AdView.prototype.setupExtEvent_ = function(eventName, eventInfo) { - var self = this; - var adviewNode = this.adviewNode_; - eventInfo.evt.addListener(function(event) { - var adviewEvent = new Event(eventName, {bubbles: true}); - $Array.forEach(eventInfo.fields, function(field) { - adviewEvent[field] = event[field]; - }); - if (eventInfo.customHandler) { - eventInfo.customHandler(self, event); - } - adviewNode.dispatchEvent(adviewEvent); - }, {instanceId: self.instanceId_}); -}; - -/** - * @public - */ -AdView.prototype.dispatchEvent = function(eventname, detail) { - // Create event object. - var evt = new Event(eventname, { bubbles: true }); - for(var item in detail) { - evt[item] = detail[item]; - } - - // Dispatch event. - this.adviewNode_.dispatchEvent(evt); -} - -addTagWatcher('ADVIEW', function(addedNode) { new AdView(addedNode); }); |