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

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: refactor one method, Created 6 years, 7 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 f00fb9b2e6a3440181199217b7d9d4a3e8bba2c3..29bd7b29840e18819a51474348cc2b2ff2ab34da 100644
--- a/chrome/renderer/resources/extensions/web_view.js
+++ b/chrome/renderer/resources/extensions/web_view.js
@@ -21,18 +21,73 @@ var WEB_VIEW_ATTRIBUTE_MAXHEIGHT = 'maxheight';
var WEB_VIEW_ATTRIBUTE_MAXWIDTH = 'maxwidth';
var WEB_VIEW_ATTRIBUTE_MINHEIGHT = 'minheight';
var WEB_VIEW_ATTRIBUTE_MINWIDTH = 'minwidth';
Fady Samuel 2014/05/27 14:19:06 I think we might start needing to think about refa
lazyboy 2014/05/27 20:43:00 Right, I was going in that direction by starting t
+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.';
+
+var LOG = function(msg) {
+ window.console.log(msg);
+};
/** @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() {
+ LOG('Partition.toAttribute');
+ if (!this.validPartitionId_) {
+ LOG('Warning we have invalid partition id');
+ return '';
+ }
+ return (this.persist_storage_ ? 'persist:' : '') + this.storage_partition_id_;
+};
+
+Partition.prototype.fromAttribute = function(value, hasNavigated) {
+ LOG('Partition.fromAttribute');
+ LOG('value: ' + value + ', hasNavigated: ' + hasNavigated);
+ var result = {};
+ if (hasNavigated) {
+ result.error = ERROR_MSG_ALREADY_NAVIGATED;
+ return result;
+ }
+ if (!value) {
+ LOG('Partition.fromAttribute got empty 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);
@@ -173,9 +228,14 @@ WebViewInternal.maybeRegisterExperimentalAPIs = function(proto) {}
* @constructor
*/
function WebViewInternal(webviewNode) {
+ LOG('WebViewInternal.constructor');
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 +243,13 @@ function WebViewInternal(webviewNode) {
this.setupWebviewNodeAttributes();
this.setupFocusPropagation();
this.setupWebviewNodeProperties();
+
+ this.viewInstanceId = IdGenerator.GetNextId();
+
+ //this.allocateInstanceId();
+ this.partition_ = new Partition();
+ this.parseAttributes();
+
this.setupWebviewNodeEvents();
}
@@ -195,7 +262,7 @@ WebViewInternal.prototype.createBrowserPluginNode = function() {
var browserPluginNode = new WebViewInternal.BrowserPlugin();
privates(browserPluginNode).internal = this;
- var ALL_ATTRIBUTES = WEB_VIEW_ATTRIBUTES.concat(['src']);
+ var ALL_ATTRIBUTES = WEB_VIEW_ATTRIBUTES;
Fady Samuel 2014/05/27 14:19:06 No point in having this at all.
lazyboy 2014/05/27 20:43:00 Done.
$Array.forEach(ALL_ATTRIBUTES, function(attributeName) {
// Only copy attributes that have been assigned values, rather than copying
// a series of undefined attributes to BrowserPlugin.
@@ -399,6 +466,26 @@ WebViewInternal.prototype.setupWebviewNodeProperties = function() {
enumerable: true
});
+ Object.defineProperty(this.webviewNode, 'partition', {
+ get: function() {
+ window.console.log('getter.partition');
+ var ret = self.partition_.toAttribute();
+ window.console.log('returning: ' + ret);
+ return ret;
+ },
+ set: function(value) {
+ window.console.log('setter.partition, value: ' + value);
+ var result = self.partition_.fromAttribute(value, self.hasNavigated());
+ if (result.error) {
+ throw result.error;
+ }
+ self.webviewNode.setAttribute('partition', value);
+
+ // TODO(lazyboy): CanRemovePartitionAttribute() when removeAttribute().
+ },
+ enumerable: true
+ });
+
// We cannot use {writable: true} property descriptor because we want a
// dynamic getter value.
Object.defineProperty(this.webviewNode, 'contentWindow', {
@@ -429,7 +516,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 +530,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);
};
/**
@@ -453,6 +540,7 @@ WebViewInternal.prototype.setupWebViewSrcAttributeMutationObserver =
*/
WebViewInternal.prototype.handleWebviewAttributeMutation =
function(name, oldValue, newValue) {
+ window.console.log('handleWebviewAttributeMutation, name = ' + name);
// 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
@@ -478,6 +566,7 @@ WebViewInternal.prototype.handleWebviewAttributeMutation =
// one case.
oldValue = oldValue || '';
newValue = newValue || '';
+ LOG('WebViewInternal.handleWebviewAttributeMutation, old = ' + oldValue + ', new = ' + newValue);
// Once we have navigated, we don't allow clearing the src attribute.
// Once <webview> enters a navigated state, it cannot be return back to a
// placeholder state.
@@ -492,15 +581,32 @@ 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;
}
+ LOG('srcAttributeChanged');
+ var result = {};
+ this.parseSrcAttribute(result);
+
+ if (result.error) {
+ throw result.error;
+ }
+ } else if (name == 'partition') {
+ LOG('handleWebviewAttributeMutation.partition');
+ LOG('newValue: ' + newValue + ', oldValue: ' + oldValue);
+ // TODO(lazyboy): Do we do extra work here if we get here from
+ // Object.set.partition?
+ this.partition_.fromAttribute(newValue, this.hasNavigated());
}
- if (this.browserPluginNode.hasOwnProperty(name)) {
- this.browserPluginNode[name] = newValue;
- } else {
- this.browserPluginNode.setAttribute(name, newValue);
+
+ // No <webview> -> <object> mutation propagation for these attributes.
+ if (name != 'src' && name != 'partition') {
+ if (this.browserPluginNode.hasOwnProperty(name)) {
+ this.browserPluginNode[name] = newValue;
+ } else {
+ this.browserPluginNode.setAttribute(name, newValue);
+ }
}
};
@@ -509,6 +615,12 @@ WebViewInternal.prototype.handleWebviewAttributeMutation =
*/
WebViewInternal.prototype.handleBrowserPluginAttributeMutation =
function(name, newValue) {
+ if (name == 'src') {
+ // name == 'src' here implies autoNavigate = true;
+ this.autoNavigate_ = true;
+ this.partition_.fromAttribute('persist:custom_plugin', this.hasNavigated());
+ }
+
// This observer monitors mutations to attributes of the BrowserPlugin and
// updates the <webview> attributes accordingly.
// |newValue| is null if the attribute |name| has been removed.
@@ -597,23 +709,89 @@ WebViewInternal.prototype.handleSizeChangedEvent =
node.dispatchEvent(webViewEvent);
};
+WebViewInternal.prototype.hasNavigated = function() {
+ return !this.beforeFirstNavigation_;
+};
+
+/** @return {boolean} */
+WebViewInternal.prototype.parseSrcAttribute = function(result) {
+ LOG('parseSrcAttribute');
+ if (!this.partition_.validPartitionId_) {
+ LOG('ERROR_MSG_INVALID_PARTITION_ATTRIBUTE');
+ result.error = ERROR_MSG_INVALID_PARTITION_ATTRIBUTE;
+ return false;
+ }
+
+ this.src = this.webviewNode.getAttribute('src');
+ LOG('parseSrcAttribute, srcAttribute: ' + this.src);
+
+ if (!this.src) {
+ LOG('src empty');
+ return true;
+ }
+
+ LOG('hasGuestInstanceID: ' + this.hasGuestInstanceID());
+ LOG('beforeFirstNavigation_: ' + this.beforeFirstNavigation_);
+ if (!this.hasGuestInstanceID()) {
+ if (this.beforeFirstNavigation_) {
+ this.beforeFirstNavigation_ = false;
+ this.allocateInstanceId();
+ }
+ return true;
+ }
+
+ LOG('Webview.navigate, i: ' + this.instanceId + ', src = ' + this.src);
+
+ // Navigate to this.src.
+ WebView.navigate(this.instanceId, this.src);
+ return true;
+};
+
+/** @return {boolean} */
+WebViewInternal.prototype.parseAttributes = function() {
+ LOG('parseAttributes');
+ var hasNavigated = this.hasNavigated();
+
+ var attributeValue = this.webviewNode.getAttribute('partition');
+ LOG('parseAttributes, partition.ttributeValue: ' + attributeValue);
+ var result = this.partition_.fromAttribute(attributeValue, hasNavigated);
+ return this.parseSrcAttribute(result);
+};
+
+WebViewInternal.prototype.hasGuestInstanceID = function() {
+ return this.instanceId != undefined;
+};
+
+WebViewInternal.prototype.allocateInstanceId = function() {
+ LOG('allocateInstanceId');
+ //this.viewInstanceId = IdGenerator.GetNextId();
+ LOG('cur partition: ' + this.webviewNode.getAttribute('partition'));
+ LOG('cur partition prop: ' + this.webviewNode['partition']);
+
+ // Parse .src and .partition.
+
+ var self = this;
+ WebView.allocateInstanceId(
Fady Samuel 2014/05/27 14:19:06 Let's make it GuestView.allocateInstanceId
lazyboy 2014/05/27 20:43:00 Done.
+ 'webview',
+ this.viewInstanceId,
+ function(info) {
+ LOG('allocateInstanceId.callback.info: ' + info);
+ self.instanceId = info;
+ // 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);
}
@@ -848,8 +1026,21 @@ WebViewInternal.prototype.handleNewWindowEvent =
// asynchronously.
setTimeout(function() {
var webViewInternal = privates(webview).internal;
+ LOG('=== Attach w/o a src');
+
+ if (event.storagePartitionId) {
+ LOG('read partition string: ' + 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);
@@ -1062,16 +1253,33 @@ WebViewInternal.prototype.setUserAgentOverride = function(userAgentOverride) {
};
/** @private */
-WebViewInternal.prototype.attachWindowAndSetUpEvents = function(instanceId) {
+WebViewInternal.prototype.attachWindowAndSetUpEvents = function(
+ instanceId, opt_src, opt_partitionId) {
this.instanceId = instanceId;
var params = {
'api': 'webview',
'instanceId': this.viewInstanceId,
'name': this.name
};
+ if (!!opt_src) {
+ params.src = opt_src;
Fady Samuel 2014/05/27 14:19:06 For consistency, ca we simply make this and userAg
lazyboy 2014/05/27 20:43:00 There's a bit of difference between this and what
+ }
if (this.userAgentOverride) {
params['userAgentOverride'] = this.userAgentOverride;
}
+
+ // If we have a partition from the opener, use that instead.
+ if (!!opt_partitionId) {
+ LOG("******* use from opener *****");
+ params['storagePartitionId'] = opt_partitionId;
+ } else {
+ LOG('starting to get partitionAttr');
+ // TODO(lazyboy): Tidy this up.
+ var partitionAttr = this.webviewNode.getAttribute('partition') ||
+ this.webviewNode['partition'];
+ LOG('partitionAttr: ' + partitionAttr);
+ params['storagePartitionId'] = partitionAttr;
+ }
this.setupNameAttribute();
var events = this.getEvents();
for (var eventName in events) {
@@ -1125,6 +1333,8 @@ function registerWebViewElement() {
new WebViewInternal(this);
};
+ proto.customElementDetached = false;
Fady Samuel 2014/05/27 14:19:06 What is the purpose of this flag? Debugging? Can w
lazyboy 2014/05/27 20:43:00 This is for detecting an attach after detach.
+
proto.attributeChangedCallback = function(name, oldValue, newValue) {
var internal = privates(this).internal;
if (!internal) {
@@ -1133,6 +1343,27 @@ function registerWebViewElement() {
internal.handleWebviewAttributeMutation(name, oldValue, newValue);
};
+ proto.detachedCallback = function() {
+ LOG('<webview> got detached');
+ LOG('this.customElementDetached was: ' + this.customElementDetached);
Fady Samuel 2014/05/27 14:19:06 Let's remove all the listeners here.
lazyboy 2014/05/27 20:43:00 I need this to allocate new instanceId on attachin
+ this.customElementDetached = true;
+ };
+ proto.attachedCallback = function() {
+ LOG('attached, for the first time or subsequent, must init later');
+ LOG('this.customElementDetached was: ' + this.customElementDetached);
+ if (this.customElementDetached) {
+ var otherThis = privates(this).internal;
+ LOG('allocateInstanceId again');
+ otherThis.instanceId = undefined;
+ otherThis.beforeFirstNavigation_ = true;
+ otherThis.validPartitionId_ = true;
+ otherThis.partition_.validPartitionId_ = true;
+
+ otherThis.allocateInstanceId();
+ }
+ this.customElementDetached = false;
+ };
+
proto.back = function() {
this.go(-1);
};

Powered by Google App Engine
This is Rietveld 408576698