summaryrefslogtreecommitdiffstats
path: root/chrome/renderer
diff options
context:
space:
mode:
authorfsamuel@chromium.org <fsamuel@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-05 06:03:44 +0000
committerfsamuel@chromium.org <fsamuel@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-05 06:03:44 +0000
commitd30c5d41bea758225fa56f57ea848b0309fdb44f (patch)
treec085c72424e33748b544572733dc7697e7054169 /chrome/renderer
parent0f8e48e91bd7bc8cad19c5f163f888096ad4fac7 (diff)
downloadchromium_src-d30c5d41bea758225fa56f57ea848b0309fdb44f.zip
chromium_src-d30c5d41bea758225fa56f57ea848b0309fdb44f.tar.gz
chromium_src-d30c5d41bea758225fa56f57ea848b0309fdb44f.tar.bz2
<webview>: Refactor web_view.js for readability
web_view.js was getting unwieldy. This CL borrows refactorings from ad_view.js to clean up web_view.js. Eventually the common code between the two should be moved into a common file. However, I'll leave that until after the big API refactor lands by the end of this quarter. BUG=none Review URL: https://chromiumcodereview.appspot.com/16371002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@204169 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/renderer')
-rw-r--r--chrome/renderer/resources/extensions/web_view.js214
-rw-r--r--chrome/renderer/resources/extensions/web_view_experimental.js67
2 files changed, 164 insertions, 117 deletions
diff --git a/chrome/renderer/resources/extensions/web_view.js b/chrome/renderer/resources/extensions/web_view.js
index 3bb6f06..4138215 100644
--- a/chrome/renderer/resources/extensions/web_view.js
+++ b/chrome/renderer/resources/extensions/web_view.js
@@ -48,135 +48,177 @@ window.addEventListener('DOMContentLoaded', function() {
/**
* @constructor
*/
-function WebView(node) {
- this.node_ = node;
- var shadowRoot = node.webkitCreateShadowRoot();
+function WebView(webviewNode) {
+ this.webviewNode_ = webviewNode;
+ this.browserPluginNode_ = this.createBrowserPluginNode_();
+ var shadowRoot = this.webviewNode_.webkitCreateShadowRoot();
+ shadowRoot.appendChild(this.browserPluginNode_);
- this.objectNode_ = document.createElement('object');
- this.objectNode_.type = 'application/browser-plugin';
+ this.setupFocusPropagation_();
+ this.setupWebviewNodeMethods_();
+ this.setupWebviewNodeProperties_();
+ this.setupWebviewNodeAttributes_();
+ this.setupWebviewNodeEvents_();
+
+ // Experimental API
+ this.maybeSetupExperimentalAPI_();
+}
+
+/**
+ * @private
+ */
+WebView.prototype.createBrowserPluginNode_ = function() {
+ var browserPluginNode = document.createElement('object');
+ browserPluginNode.type = 'application/browser-plugin';
// The <object> node fills in the <webview> container.
- this.objectNode_.style.width = '100%';
- this.objectNode_.style.height = '100%';
+ browserPluginNode.style.width = '100%';
+ browserPluginNode.style.height = '100%';
forEach(WEB_VIEW_ATTRIBUTES, function(i, attributeName) {
// Only copy attributes that have been assigned values, rather than copying
// a series of undefined attributes to BrowserPlugin.
- if (this.node_.hasAttribute(attributeName)) {
- this.objectNode_.setAttribute(
- attributeName, this.node_.getAttribute(attributeName));
+ if (this.webviewNode_.hasAttribute(attributeName)) {
+ browserPluginNode.setAttribute(
+ attributeName, this.webviewNode_.getAttribute(attributeName));
}
}, this);
- if (!this.node_.hasAttribute('tabIndex')) {
+ return browserPluginNode;
+}
+
+/**
+ * @private
+ */
+WebView.prototype.setupFocusPropagation_ = function() {
+ if (!this.webviewNode_.hasAttribute('tabIndex')) {
// <webview> needs a tabIndex in order to respond to keyboard focus.
// TODO(fsamuel): This introduces unexpected tab ordering. We need to find
// a way to take keyboard focus without messing with tab ordering.
// See http://crbug.com/231664.
- this.node_.setAttribute('tabIndex', 0);
+ this.webviewNode_.setAttribute('tabIndex', 0);
}
var self = this;
- this.node_.addEventListener('focus', function(e) {
+ this.webviewNode_.addEventListener('focus', function(e) {
// Focus the BrowserPlugin when the <webview> takes focus.
- self.objectNode_.focus();
+ self.browserPluginNode_.focus();
});
- this.node_.addEventListener('blur', function(e) {
+ this.webviewNode_.addEventListener('blur', function(e) {
// Blur the BrowserPlugin when the <webview> loses focus.
- self.objectNode_.blur();
+ self.browserPluginNode_.blur();
});
+}
- shadowRoot.appendChild(this.objectNode_);
-
- // this.objectNode_[apiMethod] are not necessarily defined immediately after
- // the shadow object is appended to the shadow root.
+/**
+ * @private
+ */
+WebView.prototype.setupWebviewNodeMethods_ = function() {
+ // this.browserPluginNode_[apiMethod] are not necessarily defined immediately
+ // after the shadow object is appended to the shadow root.
+ var self = this;
forEach(WEB_VIEW_API_METHODS, function(i, apiMethod) {
- node[apiMethod] = function(var_args) {
- return self.objectNode_[apiMethod].apply(self.objectNode_, arguments);
+ self.webviewNode_[apiMethod] = function(var_args) {
+ return self.browserPluginNode_[apiMethod].apply(
+ self.browserPluginNode_, arguments);
};
}, this);
+}
- // Map attribute modifications on the <webview> tag to property changes in
- // the underlying <object> node.
- var handleMutation = function(i, mutation) {
- this.handleMutation_(mutation);
- }.bind(this);
- var observer = new WebKitMutationObserver(function(mutations) {
- forEach(mutations, handleMutation);
- });
- observer.observe(
- this.node_,
- {attributes: true, attributeFilter: WEB_VIEW_ATTRIBUTES});
-
- var handleObjectMutation = function(i, mutation) {
- this.handleObjectMutation_(mutation);
- }.bind(this);
- var objectObserver = new WebKitMutationObserver(function(mutations) {
- forEach(mutations, handleObjectMutation);
- });
- objectObserver.observe(
- this.objectNode_,
- {attributes: true, attributeFilter: WEB_VIEW_ATTRIBUTES});
-
- var objectNode = this.objectNode_;
+/**
+ * @private
+ */
+WebView.prototype.setupWebviewNodeProperties_ = function() {
+ var browserPluginNode = this.browserPluginNode_;
// Expose getters and setters for the attributes.
forEach(WEB_VIEW_ATTRIBUTES, function(i, attributeName) {
- Object.defineProperty(this.node_, attributeName, {
+ Object.defineProperty(this.webviewNode_, attributeName, {
get: function() {
- return objectNode[attributeName];
+ return browserPluginNode[attributeName];
},
set: function(value) {
- objectNode[attributeName] = value;
+ browserPluginNode[attributeName] = value;
},
enumerable: true
});
}, this);
-
// We cannot use {writable: true} property descriptor because we want dynamic
// getter value.
- Object.defineProperty(this.node_, 'contentWindow', {
+ Object.defineProperty(this.webviewNode_, 'contentWindow', {
get: function() {
// TODO(fsamuel): This is a workaround to enable
// contentWindow.postMessage until http://crbug.com/152006 is fixed.
- if (objectNode.contentWindow)
- return objectNode.contentWindow.self;
+ 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
});
+}
- for (var eventName in WEB_VIEW_EVENTS) {
- this.setupEvent_(eventName, WEB_VIEW_EVENTS[eventName]);
- }
- this.maybeSetupNewWindowEvent_();
- this.maybeSetupPermissionEvent_();
- this.maybeSetupExecuteCodeAPI_();
- this.maybeSetupWebRequestEvents_();
+/**
+ * @private
+ */
+WebView.prototype.setupWebviewNodeAttributes_ = function() {
+ this.setupWebviewNodeObservers_();
+ this.setupBrowserPluginNodeObservers_();
}
/**
* @private
*/
-WebView.prototype.handleMutation_ = function(mutation) {
+WebView.prototype.setupWebviewNodeObservers_ = function() {
+ // Map attribute modifications on the <webview> tag to property changes in
+ // the underlying <object> node.
+ var handleMutation = function(i, mutation) {
+ this.handleWebviewAttributeMutation_(mutation);
+ }.bind(this);
+ var observer = new WebKitMutationObserver(function(mutations) {
+ forEach(mutations, handleMutation);
+ });
+ observer.observe(
+ this.webviewNode_,
+ {attributes: true, attributeFilter: WEB_VIEW_ATTRIBUTES});
+}
+
+/**
+ * @private
+ */
+WebView.prototype.setupBrowserPluginNodeObservers_ = function() {
+ var handleMutation = function(i, mutation) {
+ this.handleBrowserPluginAttributeMutation_(mutation);
+ }.bind(this);
+ var objectObserver = new WebKitMutationObserver(function(mutations) {
+ forEach(mutations, handleMutation);
+ });
+ objectObserver.observe(
+ this.browserPluginNode_,
+ {attributes: true, attributeFilter: WEB_VIEW_ATTRIBUTES});
+}
+
+/**
+ * @private
+ */
+WebView.prototype.handleWebviewAttributeMutation_ = function(mutation) {
// This observer monitors mutations to attributes of the <webview> 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.objectNode_[mutation.attributeName] =
- this.node_.getAttribute(mutation.attributeName);
+ this.browserPluginNode_[mutation.attributeName] =
+ this.webviewNode_.getAttribute(mutation.attributeName);
};
/**
* @private
*/
-WebView.prototype.handleObjectMutation_ = function(mutation) {
+WebView.prototype.handleBrowserPluginAttributeMutation_ = function(mutation) {
// This observer monitors mutations to attributes of the BrowserPlugin and
// updates the <webview> attributes accordingly.
- if (!this.objectNode_.hasAttribute(mutation.attributeName)) {
+ if (!this.browserPluginNode_.hasAttribute(mutation.attributeName)) {
// If an attribute is removed from the BrowserPlugin, then remove it
// from the <webview> as well.
- this.node_.removeAttribute(mutation.attributeName);
+ this.webviewNode_.removeAttribute(mutation.attributeName);
} else {
// Update the <webview> attribute to match the BrowserPlugin attribute.
// Note: Calling setAttribute on <webview> will trigger its mutation
@@ -185,10 +227,10 @@ WebView.prototype.handleObjectMutation_ = function(mutation) {
// again (such as navigation when crashed), this could end up in an infinite
// loop. Thus, we avoid this loop by only updating the <webview> attribute
// if the BrowserPlugin attributes differs from it.
- var oldValue = this.node_.getAttribute(mutation.attributeName);
- var newValue = this.objectNode_.getAttribute(mutation.attributeName);
+ var oldValue = this.webviewNode_.getAttribute(mutation.attributeName);
+ var newValue = this.browserPluginNode_.getAttribute(mutation.attributeName);
if (newValue != oldValue) {
- this.node_.setAttribute(mutation.attributeName, newValue);
+ this.webviewNode_.setAttribute(mutation.attributeName, newValue);
}
}
};
@@ -196,15 +238,25 @@ WebView.prototype.handleObjectMutation_ = function(mutation) {
/**
* @private
*/
+WebView.prototype.setupWebviewNodeEvents_ = function() {
+ for (var eventName in WEB_VIEW_EVENTS) {
+ this.setupEvent_(eventName, WEB_VIEW_EVENTS[eventName]);
+ }
+}
+
+/**
+ * @private
+ */
WebView.prototype.setupEvent_ = function(eventname, attribs) {
- var node = this.node_;
- this.objectNode_.addEventListener('-internal-' + eventname, function(e) {
+ var webviewNode = this.webviewNode_;
+ var internalname = '-internal-' + eventname;
+ this.browserPluginNode_.addEventListener(internalname, function(e) {
var evt = new Event(eventname, { bubbles: true });
var detail = e.detail ? JSON.parse(e.detail) : {};
forEach(attribs, function(i, attribName) {
evt[attribName] = detail[attribName];
});
- node.dispatchEvent(evt);
+ webviewNode.dispatchEvent(evt);
});
};
@@ -212,24 +264,6 @@ WebView.prototype.setupEvent_ = function(eventname, attribs) {
* Implemented when the experimental API is available.
* @private
*/
-WebView.prototype.maybeSetupNewWindowEvent_ = function() {};
-
-/**
- * Implemented when experimental permission is available.
- * @private
- */
-WebView.prototype.maybeSetupPermissionEvent_ = function() {};
-
-/**
- * Implemented when experimental permission is available.
- * @private
- */
-WebView.prototype.maybeSetupExecuteScript_ = function() {};
-
-/**
- * Implemented when experimental permission is available.
- * @private
- */
-WebView.prototype.maybeSetupWebRequestEvents_ = function() {};
+WebView.prototype.maybeSetupExperimentalAPI_ = function() {};
exports.WebView = WebView;
diff --git a/chrome/renderer/resources/extensions/web_view_experimental.js b/chrome/renderer/resources/extensions/web_view_experimental.js
index b36271c..93eaa22 100644
--- a/chrome/renderer/resources/extensions/web_view_experimental.js
+++ b/chrome/renderer/resources/extensions/web_view_experimental.js
@@ -43,13 +43,24 @@ var ERROR_MSG_NEWWINDOW_ACTION_ALREADY_TAKEN = '<webview>: ' +
var ERROR_MSG_WEBVIEW_EXPECTED = '<webview> element expected.';
/**
+ * @private
+ */
+WebView.prototype.maybeSetupExperimentalAPI_ = function() {
+ this.setupNewWindowEvent_();
+ this.setupPermissionEvent_();
+ this.setupExecuteCodeAPI_();
+ this.setupWebRequestEvents_();
+}
+
+/**
* @param {!Object} detail The event details, originated from <object>.
* @private
*/
-WebView.prototype.maybeSetupPermissionEvent_ = function() {
- var node = this.node_;
- var objectNode = this.objectNode_;
- this.objectNode_.addEventListener('-internal-permissionrequest', function(e) {
+WebView.prototype.setupPermissionEvent_ = function() {
+ var node = this.webviewNode_;
+ var browserPluginNode = this.browserPluginNode_;
+ var internalevent = '-internal-permissionrequest';
+ browserPluginNode.addEventListener(internalevent, function(e) {
var evt = new Event('permissionrequest', {bubbles: true, cancelable: true});
var detail = e.detail ? JSON.parse(e.detail) : {};
forEach(EXPOSED_PERMISSION_EVENT_ATTRIBS, function(i, attribName) {
@@ -69,7 +80,7 @@ WebView.prototype.maybeSetupPermissionEvent_ = function() {
if (decisionMade) {
throw new Error(ERROR_MSG_PERMISSION_ALREADY_DECIDED);
} else {
- objectNode['-internal-setPermission'](requestId, true);
+ browserPluginNode['-internal-setPermission'](requestId, true);
decisionMade = true;
}
},
@@ -77,7 +88,7 @@ WebView.prototype.maybeSetupPermissionEvent_ = function() {
if (decisionMade) {
throw new Error(ERROR_MSG_PERMISSION_ALREADY_DECIDED);
} else {
- objectNode['-internal-setPermission'](requestId, false);
+ browserPluginNode['-internal-setPermission'](requestId, false);
decisionMade = true;
}
}
@@ -85,13 +96,13 @@ WebView.prototype.maybeSetupPermissionEvent_ = function() {
evt.request = request;
// Make browser plugin track lifetime of |request|.
- objectNode['-internal-persistObject'](
+ browserPluginNode['-internal-persistObject'](
request, detail.permission, requestId);
var defaultPrevented = !node.dispatchEvent(evt);
if (!decisionMade && !defaultPrevented) {
decisionMade = true;
- objectNode['-internal-setPermission'](requestId, false);
+ browserPluginNode['-internal-setPermission'](requestId, false);
}
}
});
@@ -100,17 +111,17 @@ WebView.prototype.maybeSetupPermissionEvent_ = function() {
/**
* @private
*/
-WebView.prototype.maybeSetupExecuteCodeAPI_ = function() {
+WebView.prototype.setupExecuteCodeAPI_ = function() {
var self = this;
- this.node_['executeScript'] = function(var_args) {
- var args = [self.objectNode_.getProcessId(),
- self.objectNode_.getRouteId()].concat(
+ this.webviewNode_['executeScript'] = function(var_args) {
+ var args = [self.browserPluginNode_.getProcessId(),
+ self.browserPluginNode_.getRouteId()].concat(
Array.prototype.slice.call(arguments));
chrome.webview.executeScript.apply(null, args);
}
- this.node_['insertCSS'] = function(var_args) {
- var args = [self.objectNode_.getProcessId(),
- self.objectNode_.getRouteId()].concat(
+ this.webviewNode_['insertCSS'] = function(var_args) {
+ var args = [self.browserPluginNode_.getProcessId(),
+ self.browserPluginNode_.getRouteId()].concat(
Array.prototype.slice.call(arguments));
chrome.webview.insertCSS.apply(null, args);
}
@@ -119,7 +130,7 @@ WebView.prototype.maybeSetupExecuteCodeAPI_ = function() {
/**
* @private
*/
-WebView.prototype.maybeSetupNewWindowEvent_ = function() {
+WebView.prototype.setupNewWindowEvent_ = function() {
var NEW_WINDOW_EVENT_ATTRIBUTES = [
'initialHeight',
'initialWidth',
@@ -128,9 +139,9 @@ WebView.prototype.maybeSetupNewWindowEvent_ = function() {
'name'
];
- var node = this.node_;
- var objectNode = this.objectNode_;
- objectNode.addEventListener('-internal-newwindow', function(e) {
+ var node = this.webviewNode_;
+ var browserPluginNode = this.browserPluginNode_;
+ browserPluginNode.addEventListener('-internal-newwindow', function(e) {
var evt = new Event('newwindow', { bubbles: true, cancelable: true });
var detail = e.detail ? JSON.parse(e.detail) : {};
@@ -158,7 +169,8 @@ WebView.prototype.maybeSetupNewWindowEvent_ = function() {
// asynchronously.
setTimeout(function() {
var attached =
- objectNode['-internal-attachWindowTo'](webview, detail.windowId);
+ browserPluginNode['-internal-attachWindowTo'](webview,
+ detail.windowId);
if (!attached) {
console.error('Unable to attach the new window to the provided ' +
'webview.');
@@ -167,24 +179,24 @@ WebView.prototype.maybeSetupNewWindowEvent_ = function() {
// then we will fail and it will be treated as if the new window
// was rejected. The permission API plumbing is used here to clean
// up the state created for the new window if attaching fails.
- objectNode['-internal-setPermission'](requestId, attached);
+ browserPluginNode['-internal-setPermission'](requestId, attached);
}, 0);
},
discard: function() {
validateCall();
- objectNode['-internal-setPermission'](requestId, false);
+ browserPluginNode['-internal-setPermission'](requestId, false);
}
};
evt.window = window;
// Make browser plugin track lifetime of |window|.
- objectNode['-internal-persistObject'](
+ browserPluginNode['-internal-persistObject'](
window, detail.permission, requestId);
var defaultPrevented = !node.dispatchEvent(evt);
if (!actionTaken && !defaultPrevented) {
actionTaken = true;
// The default action is to discard the window.
- objectNode['-internal-setPermission'](requestId, false);
+ browserPluginNode['-internal-setPermission'](requestId, false);
console.warn('<webview>: A new window was blocked.');
}
});
@@ -193,14 +205,15 @@ WebView.prototype.maybeSetupNewWindowEvent_ = function() {
/**
* @private
*/
-WebView.prototype.maybeSetupWebRequestEvents_ = function() {
+WebView.prototype.setupWebRequestEvents_ = function() {
var self = this;
// Populate the WebRequest events from the API definition.
var webRequestDefinition = GetExtensionAPIDefinitions().filter(function(api) {
return api.namespace == 'webRequest';
})[0];
for (var i = 0; i < webRequestDefinition.events.length; ++i) {
- Object.defineProperty(self.node_, webRequestDefinition.events[i].name, {
+ Object.defineProperty(self.webviewNode_,
+ webRequestDefinition.events[i].name, {
get: function(webRequestEvent) {
return function() {
if (!self[webRequestEvent.name + '_']) {
@@ -209,7 +222,7 @@ WebView.prototype.maybeSetupWebRequestEvents_ = function() {
'webview.' + webRequestEvent.name,
webRequestEvent.parameters,
webRequestEvent.extraParameters, null,
- self.objectNode_.getInstanceId());
+ self.browserPluginNode_.getInstanceId());
}
return self[webRequestEvent.name + '_'];
}