Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2604)

Unified Diff: chrome/renderer/resources/extensions/web_view.js

Issue 299753011: Move allocate instance id to chrome/. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: HasPermission function moved Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/renderer/resources/extensions/web_view.js
diff --git a/chrome/renderer/resources/extensions/web_view.js b/chrome/renderer/resources/extensions/web_view.js
index f0578f7ae76c0d5be08fe63fa17a66c46c24723f..50253872eb5ddaa44daa8feb048deff71e644f21 100644
--- a/chrome/renderer/resources/extensions/web_view.js
+++ b/chrome/renderer/resources/extensions/web_view.js
@@ -8,6 +8,8 @@
var DocumentNatives = requireNative('document_natives');
var EventBindings = require('event_bindings');
+var GuestViewInternal =
+ require('binding').Binding.create('guestViewInternal').generate();
var IdGenerator = requireNative('id_generator');
var MessagingNatives = requireNative('messaging_natives');
var WebRequestEvent = require('webRequestInternal').WebRequestEvent;
@@ -21,18 +23,63 @@ var WEB_VIEW_ATTRIBUTE_MAXHEIGHT = 'maxheight';
var WEB_VIEW_ATTRIBUTE_MAXWIDTH = 'maxwidth';
var WEB_VIEW_ATTRIBUTE_MINHEIGHT = 'minheight';
var WEB_VIEW_ATTRIBUTE_MINWIDTH = 'minwidth';
+var WEB_VIEW_ATTRIBUTE_PARTITION = 'partition';
+
+var ERROR_MSG_ALREADY_NAVIGATED =
+ 'The object has already navigated, so its partition cannot be changed.';
+var ERROR_MSG_INVALID_PARTITION_ATTRIBUTE = 'Invalid partition attribute.';
/** @type {Array.<string>} */
var WEB_VIEW_ATTRIBUTES = [
'allowtransparency',
'autosize',
- 'partition',
WEB_VIEW_ATTRIBUTE_MINHEIGHT,
WEB_VIEW_ATTRIBUTE_MINWIDTH,
WEB_VIEW_ATTRIBUTE_MAXHEIGHT,
WEB_VIEW_ATTRIBUTE_MAXWIDTH
];
+/** @class representing state of storage partition. */
+function Partition() {
+ this.validPartitionId = true;
+ this.persist_storage_ = false;
+ this.storage_partition_id = '';
+};
+
+Partition.prototype.toAttribute = function() {
+ if (!this.validPartitionId) {
+ return '';
+ }
+ return (this.persist_storage_ ? 'persist:' : '') + this.storage_partition_id;
+};
+
+Partition.prototype.fromAttribute = function(value, hasNavigated) {
+ var result = {};
+ if (hasNavigated) {
+ result.error = ERROR_MSG_ALREADY_NAVIGATED;
+ return result;
+ }
+ if (!value) {
+ value = '';
+ }
+
+ var LEN = 'persist:'.length;
+ if (value.substr(0, LEN) == 'persist:') {
+ value = value.substr(LEN);
+ if (!value) {
+ this.validPartitionId = false;
+ result.error = ERROR_MSG_INVALID_PARTITION_ATTRIBUTE;
+ return result;
+ }
+ this.persist_storage_ = true;
+ } else {
+ this.persist_storage_ = false;
+ }
+
+ this.storage_partition_id = value;
+ return result;
+};
+
var CreateEvent = function(name) {
var eventOpts = {supportsListeners: true, supportsFilters: true};
return new EventBindings.Event(name, undefined, eventOpts);
@@ -176,6 +223,10 @@ function WebViewInternal(webviewNode) {
privates(webviewNode).internal = this;
this.webviewNode = webviewNode;
this.attached = false;
+
+ this.beforeFirstNavigation = true;
+ this.validPartitionId = true;
+
this.browserPluginNode = this.createBrowserPluginNode();
var shadowRoot = this.webviewNode.createShadowRoot();
shadowRoot.appendChild(this.browserPluginNode);
@@ -183,6 +234,12 @@ function WebViewInternal(webviewNode) {
this.setupWebviewNodeAttributes();
this.setupFocusPropagation();
this.setupWebviewNodeProperties();
+
+ this.viewInstanceId = IdGenerator.GetNextId();
+
+ this.partition = new Partition();
+ this.parseAttributes();
+
this.setupWebviewNodeEvents();
}
@@ -195,8 +252,7 @@ WebViewInternal.prototype.createBrowserPluginNode = function() {
var browserPluginNode = new WebViewInternal.BrowserPlugin();
privates(browserPluginNode).internal = this;
- var ALL_ATTRIBUTES = WEB_VIEW_ATTRIBUTES.concat(['src']);
- $Array.forEach(ALL_ATTRIBUTES, function(attributeName) {
+ $Array.forEach(WEB_VIEW_ATTRIBUTES, function(attributeName) {
// Only copy attributes that have been assigned values, rather than copying
// a series of undefined attributes to BrowserPlugin.
if (this.webviewNode.hasAttribute(attributeName)) {
@@ -217,6 +273,17 @@ WebViewInternal.prototype.createBrowserPluginNode = function() {
/**
* @private
+ * Resets some state upon reattaching <webview> element to the DOM.
+ */
+WebViewInternal.prototype.resetUponReattachment = function() {
+ this.instanceId = undefined;
+ this.beforeFirstNavigation = true;
+ this.validPartitionId = true;
+ this.partition.validPartitionId = true;
+};
+
+/**
+ * @private
*/
WebViewInternal.prototype.setupFocusPropagation = function() {
if (!this.webviewNode.hasAttribute('tabIndex')) {
@@ -399,6 +466,20 @@ WebViewInternal.prototype.setupWebviewNodeProperties = function() {
enumerable: true
});
+ Object.defineProperty(this.webviewNode, 'partition', {
+ get: function() {
+ return self.partition.toAttribute();
+ },
+ set: function(value) {
+ var result = self.partition.fromAttribute(value, self.hasNavigated());
+ if (result.error) {
+ throw result.error;
+ }
+ self.webviewNode.setAttribute('partition', value);
+ },
+ enumerable: true
+ });
+
// We cannot use {writable: true} property descriptor because we want a
// dynamic getter value.
Object.defineProperty(this.webviewNode, 'contentWindow', {
@@ -429,7 +510,7 @@ WebViewInternal.prototype.setupWebViewSrcAttributeMutationObserver =
// where the webview guest has crashed and navigating to the same address
// spawns off a new process.
var self = this;
- this.srcObserver = new MutationObserver(function(mutations) {
+ this.srcAndPartitionObserver = new MutationObserver(function(mutations) {
$Array.forEach(mutations, function(mutation) {
var oldValue = mutation.oldValue;
var newValue = self.webviewNode.getAttribute(mutation.attributeName);
@@ -443,9 +524,9 @@ WebViewInternal.prototype.setupWebViewSrcAttributeMutationObserver =
var params = {
attributes: true,
attributeOldValue: true,
- attributeFilter: ['src']
+ attributeFilter: ['src', 'partition']
};
- this.srcObserver.observe(this.webviewNode, params);
+ this.srcAndPartitionObserver.observe(this.webviewNode, params);
};
/**
@@ -492,11 +573,26 @@ WebViewInternal.prototype.handleWebviewAttributeMutation =
this.src = newValue;
if (this.ignoreNextSrcAttributeChange) {
// Don't allow the src mutation observer to see this change.
- this.srcObserver.takeRecords();
+ this.srcAndPartitionObserver.takeRecords();
this.ignoreNextSrcAttributeChange = false;
return;
}
+ var result = {};
+ this.parseSrcAttribute(result);
+
+ if (result.error) {
+ throw result.error;
+ }
+ } else if (name == 'partition') {
+ // Note that throwing error here won't synchronously propagate.
+ this.partition.fromAttribute(newValue, this.hasNavigated());
}
+
+ // No <webview> -> <object> mutation propagation for these attributes.
+ if (name == 'src' || name == 'partition') {
+ return;
+ }
+
if (this.browserPluginNode.hasOwnProperty(name)) {
this.browserPluginNode[name] = newValue;
} else {
@@ -597,23 +693,68 @@ WebViewInternal.prototype.handleSizeChangedEvent =
node.dispatchEvent(webViewEvent);
};
+WebViewInternal.prototype.hasNavigated = function() {
+ return !this.beforeFirstNavigation;
+};
+
+/** @return {boolean} */
+WebViewInternal.prototype.parseSrcAttribute = function(result) {
+ if (!this.partition.validPartitionId) {
+ result.error = ERROR_MSG_INVALID_PARTITION_ATTRIBUTE;
+ return false;
+ }
+ this.src = this.webviewNode.getAttribute('src');
+
+ if (!this.src) {
+ return true;
+ }
+
+ if (!this.hasGuestInstanceID()) {
+ if (this.beforeFirstNavigation) {
+ this.beforeFirstNavigation = false;
+ this.allocateInstanceId();
+ }
+ return true;
+ }
+
+ // Navigate to this.src.
+ WebView.navigate(this.instanceId, this.src);
+ return true;
+};
+
+/** @return {boolean} */
+WebViewInternal.prototype.parseAttributes = function() {
+ var hasNavigated = this.hasNavigated();
+ var attributeValue = this.webviewNode.getAttribute('partition');
+ var result = this.partition.fromAttribute(attributeValue, hasNavigated);
+ return this.parseSrcAttribute(result);
+};
+
+WebViewInternal.prototype.hasGuestInstanceID = function() {
+ return this.instanceId != undefined;
+};
+
+WebViewInternal.prototype.allocateInstanceId = function() {
+ // Parse .src and .partition.
+ var self = this;
+ GuestViewInternal.allocateInstanceId(
+ function(instanceId) {
+ self.instanceId = instanceId;
+ // TODO(lazyboy): Make sure this.autoNavigate_ stuff correctly updated
+ // |self.src| at this point.
+ self.attachWindowAndSetUpEvents(self.instanceId, self.src);
+ });
+};
+
/**
* @private
*/
WebViewInternal.prototype.setupWebviewNodeEvents = function() {
- var self = this;
- this.viewInstanceId = IdGenerator.GetNextId();
- var onInstanceIdAllocated = function(e) {
- var detail = e.detail ? JSON.parse(e.detail) : {};
- self.attachWindowAndSetUpEvents(detail.windowId);
- };
- this.browserPluginNode.addEventListener('-internal-instanceid-allocated',
- onInstanceIdAllocated);
this.setupWebRequestEvents();
this.setupExperimentalContextMenus_();
this.on = {};
- var events = self.getEvents();
+ var events = this.getEvents();
for (var eventName in events) {
this.setupEventProperty(eventName);
}
@@ -845,8 +986,18 @@ WebViewInternal.prototype.handleNewWindowEvent =
// asynchronously.
setTimeout(function() {
var webViewInternal = privates(webview).internal;
+ if (event.storagePartitionId) {
+ webViewInternal.webviewNode.setAttribute('partition',
+ event.storagePartitionId);
+ var partition = new Partition();
+ partition.fromAttribute(event.storagePartitionId,
+ webViewInternal.hasNavigated());
+ webViewInternal.partition = partition;
+ }
+
var attached =
- webViewInternal.attachWindowAndSetUpEvents(event.windowId);
+ webViewInternal.attachWindowAndSetUpEvents(
+ event.windowId, undefined, event.storagePartitionId);
if (!attached) {
window.console.error(ERROR_MSG_NEWWINDOW_UNABLE_TO_ATTACH);
@@ -1100,16 +1251,22 @@ WebViewInternal.prototype.setUserAgentOverride = function(userAgentOverride) {
};
/** @private */
-WebViewInternal.prototype.attachWindowAndSetUpEvents = function(instanceId) {
+WebViewInternal.prototype.attachWindowAndSetUpEvents = function(
+ instanceId, opt_src, opt_partitionId) {
this.instanceId = instanceId;
+ // If we have a partition from the opener, use that instead.
+ var storagePartitionId =
+ opt_partitionId ||
+ this.webviewNode.getAttribute(WEB_VIEW_ATTRIBUTE_PARTITION) ||
+ this.webviewNode[WEB_VIEW_ATTRIBUTE_PARTITION];
var params = {
'api': 'webview',
'instanceId': this.viewInstanceId,
- 'name': this.name
+ 'name': this.name,
+ 'src': opt_src,
+ 'storagePartitionId': storagePartitionId,
+ 'userAgentOverride': this.userAgentOverride
};
- if (this.userAgentOverride) {
- params['userAgentOverride'] = this.userAgentOverride;
- }
this.setupNameAttribute();
var events = this.getEvents();
for (var eventName in events) {
@@ -1161,6 +1318,8 @@ function registerWebViewElement() {
new WebViewInternal(this);
};
+ proto.customElementDetached = false;
+
proto.attributeChangedCallback = function(name, oldValue, newValue) {
var internal = privates(this).internal;
if (!internal) {
@@ -1169,6 +1328,19 @@ function registerWebViewElement() {
internal.handleWebviewAttributeMutation(name, oldValue, newValue);
};
+ proto.detachedCallback = function() {
+ this.customElementDetached = true;
+ };
+
+ proto.attachedCallback = function() {
+ if (this.customElementDetached) {
+ var webViewInternal = privates(this).internal;
+ webViewInternal.resetUponReattachment();
+ webViewInternal.allocateInstanceId();
+ }
+ this.customElementDetached = false;
+ };
+
proto.back = function() {
this.go(-1);
};
« no previous file with comments | « chrome/common/extensions/api/webview.json ('k') | chrome/test/data/extensions/platform_apps/web_view/shim/main.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698