Commit abb035a0 authored by paulmeyer's avatar paulmeyer Committed by Commit bot

Got rid of the internal copies of webview attributes.

Webview attributes are now only stored in one location (in the webview node), so that all the code needed to sync up the copies could be removed (and was).

Also reworked the behavior of the |allowtransparency| and |autosize| to be both consistent with each other and more intuitive in general (they are both treated like booleans now). I updated the tests to reflect this new behavior.

Review URL: https://codereview.chromium.org/698973003

Cr-Commit-Position: refs/heads/master@{#302661}
parent 71ffa214
...@@ -950,8 +950,10 @@ IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestCannotMutateEventName) { ...@@ -950,8 +950,10 @@ IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestCannotMutateEventName) {
TestHelper("testCannotMutateEventName", "web_view/shim", NO_TEST_SERVER); TestHelper("testCannotMutateEventName", "web_view/shim", NO_TEST_SERVER);
} }
IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestPartitionRaisesException) { IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestPartitionChangeAfterNavigation) {
TestHelper("testPartitionRaisesException", "web_view/shim", NO_TEST_SERVER); TestHelper("testPartitionChangeAfterNavigation",
"web_view/shim",
NO_TEST_SERVER);
} }
IN_PROC_BROWSER_TEST_F(WebViewTest, IN_PROC_BROWSER_TEST_F(WebViewTest,
......
...@@ -97,20 +97,28 @@ embedder.test.assertFalse = function(condition) { ...@@ -97,20 +97,28 @@ embedder.test.assertFalse = function(condition) {
// Tests begin. // Tests begin.
// This test verifies that the allowtransparency property cannot be changed // This test verifies that the allowtransparency property is interpreted as true
// once set. The attribute can only be deleted. // if it exists (regardless of its value), and can be removed by setting it to
// to anything false.
function testAllowTransparencyAttribute() { function testAllowTransparencyAttribute() {
var webview = document.createElement('webview'); var webview = document.createElement('webview');
webview.src = 'data:text/html,webview test'; webview.src = 'data:text/html,webview test';
embedder.test.assertFalse(webview.hasAttribute('allowtransparency'));
embedder.test.assertFalse(webview.allowtransparency);
webview.allowtransparency = true; webview.allowtransparency = true;
webview.addEventListener('loadstop', function(e) { webview.addEventListener('loadstop', function(e) {
embedder.test.assertTrue(webview.hasAttribute('allowtransparency')); embedder.test.assertTrue(webview.hasAttribute('allowtransparency'));
webview.allowtransparency = false;
embedder.test.assertTrue(webview.allowtransparency); embedder.test.assertTrue(webview.allowtransparency);
embedder.test.assertTrue(webview.hasAttribute('allowtransparency')); webview.allowtransparency = false;
webview.removeAttribute('allowtransparency'); embedder.test.assertFalse(webview.hasAttribute('allowtransparency'));
embedder.test.assertFalse(webview.allowtransparency); embedder.test.assertFalse(webview.allowtransparency);
webview.allowtransparency = '';
embedder.test.assertFalse(webview.hasAttribute('allowtransparency'));
embedder.test.assertFalse(webview.allowtransparency);
webview.allowtransparency = 'some string';
embedder.test.assertTrue(webview.hasAttribute('allowtransparency'));
embedder.test.assertTrue(webview.allowtransparency);
embedder.test.succeed(); embedder.test.succeed();
}); });
...@@ -616,7 +624,7 @@ function testLoadProgressEvent() { ...@@ -616,7 +624,7 @@ function testLoadProgressEvent() {
// Current expected behavior is that the second event listener will still // Current expected behavior is that the second event listener will still
// fire without crashing. // fire without crashing.
function testDestroyOnEventListener() { function testDestroyOnEventListener() {
var webview = util.createWebViewTagInDOM(arguments.callee.name); var webview = document.createElement('webview');
var url = 'data:text/html,<body>Destroy test</body>'; var url = 'data:text/html,<body>Destroy test</body>';
var loadCommitCount = 0; var loadCommitCount = 0;
...@@ -647,13 +655,14 @@ function testDestroyOnEventListener() { ...@@ -647,13 +655,14 @@ function testDestroyOnEventListener() {
loadCommitCommon(e); loadCommitCommon(e);
}); });
webview.setAttribute('src', url); webview.setAttribute('src', url);
document.body.appendChild(webview);
} }
// This test registers two event listeners on a same event (loadcommit). // This test registers two event listeners on a same event (loadcommit).
// Each of the listener tries to change some properties on the event param, // Each of the listener tries to change some properties on the event param,
// which should not be possible. // which should not be possible.
function testCannotMutateEventName() { function testCannotMutateEventName() {
var webview = util.createWebViewTagInDOM(arguments.callee.name); var webview = document.createElement('webview');
var url = 'data:text/html,<body>Two</body>'; var url = 'data:text/html,<body>Two</body>';
var loadCommitACalled = false; var loadCommitACalled = false;
...@@ -695,23 +704,20 @@ function testCannotMutateEventName() { ...@@ -695,23 +704,20 @@ function testCannotMutateEventName() {
webview.addEventListener('loadcommit', onLoadCommitA); webview.addEventListener('loadcommit', onLoadCommitA);
webview.addEventListener('loadcommit', onLoadCommitB); webview.addEventListener('loadcommit', onLoadCommitB);
webview.setAttribute('src', url); webview.setAttribute('src', url);
document.body.appendChild(webview);
} }
// This test verifies that setting the partition attribute after the src has // This test verifies that the partion attribute cannot be changed after the src
// been set raises an exception. // has been set.
function testPartitionRaisesException() { function testPartitionChangeAfterNavigation() {
var webview = document.createElement('webview'); var webview = document.createElement('webview');
var partitionAttribute = arguments.callee.name; var partitionAttribute = arguments.callee.name;
webview.setAttribute('partition', partitionAttribute); webview.setAttribute('partition', partitionAttribute);
var loadstopHandler = function(e) { var loadstopHandler = function(e) {
try {
webview.partition = 'illegal'; webview.partition = 'illegal';
embedder.test.fail();
} catch (e) {
embedder.test.assertEq(partitionAttribute, webview.partition); embedder.test.assertEq(partitionAttribute, webview.partition);
embedder.test.succeed(); embedder.test.succeed();
}
}; };
webview.addEventListener('loadstop', loadstopHandler); webview.addEventListener('loadstop', loadstopHandler);
...@@ -1999,7 +2005,7 @@ embedder.test.testList = { ...@@ -1999,7 +2005,7 @@ embedder.test.testList = {
'testLoadProgressEvent': testLoadProgressEvent, 'testLoadProgressEvent': testLoadProgressEvent,
'testDestroyOnEventListener': testDestroyOnEventListener, 'testDestroyOnEventListener': testDestroyOnEventListener,
'testCannotMutateEventName': testCannotMutateEventName, 'testCannotMutateEventName': testCannotMutateEventName,
'testPartitionRaisesException': testPartitionRaisesException, 'testPartitionChangeAfterNavigation': testPartitionChangeAfterNavigation,
'testPartitionRemovalAfterNavigationFails': 'testPartitionRemovalAfterNavigationFails':
testPartitionRemovalAfterNavigationFails, testPartitionRemovalAfterNavigationFails,
'testExecuteScriptFail': testExecuteScriptFail, 'testExecuteScriptFail': testExecuteScriptFail,
......
...@@ -615,8 +615,8 @@ IN_PROC_BROWSER_TEST_F(WebViewAPITest, TestOnEventProperty) { ...@@ -615,8 +615,8 @@ IN_PROC_BROWSER_TEST_F(WebViewAPITest, TestOnEventProperty) {
RunTest("testOnEventProperties", "web_view/apitest"); RunTest("testOnEventProperties", "web_view/apitest");
} }
IN_PROC_BROWSER_TEST_F(WebViewAPITest, TestPartitionRaisesException) { IN_PROC_BROWSER_TEST_F(WebViewAPITest, TestPartitionChangeAfterNavigation) {
RunTest("testPartitionRaisesException", "web_view/apitest"); RunTest("testPartitionChangeAfterNavigation", "web_view/apitest");
} }
IN_PROC_BROWSER_TEST_F(WebViewAPITest, IN_PROC_BROWSER_TEST_F(WebViewAPITest,
......
...@@ -34,7 +34,6 @@ function WebView(webviewNode) { ...@@ -34,7 +34,6 @@ function WebView(webviewNode) {
this.beforeFirstNavigation = true; this.beforeFirstNavigation = true;
this.contentWindow = null; this.contentWindow = null;
this.validPartitionId = true;
// Used to save some state upon deferred attachment. // Used to save some state upon deferred attachment.
// If <object> bindings is not available, we defer attachment. // If <object> bindings is not available, we defer attachment.
// This state contains whether or not the attachment request was for // This state contains whether or not the attachment request was for
...@@ -82,7 +81,6 @@ WebView.prototype.reset = function() { ...@@ -82,7 +81,6 @@ WebView.prototype.reset = function() {
GuestViewInternal.destroyGuest(this.guestInstanceId); GuestViewInternal.destroyGuest(this.guestInstanceId);
this.guestInstanceId = undefined; this.guestInstanceId = undefined;
this.beforeFirstNavigation = true; this.beforeFirstNavigation = true;
this.validPartitionId = true;
this.attributes[WebViewConstants.ATTRIBUTE_PARTITION].validPartitionId = this.attributes[WebViewConstants.ATTRIBUTE_PARTITION].validPartitionId =
true; true;
this.contentWindow = null; this.contentWindow = null;
...@@ -129,14 +127,12 @@ WebView.prototype.validateExecuteCodeCall = function() { ...@@ -129,14 +127,12 @@ WebView.prototype.validateExecuteCodeCall = function() {
WebView.prototype.setupAutoSizeProperties = function() { WebView.prototype.setupAutoSizeProperties = function() {
$Array.forEach(AUTO_SIZE_ATTRIBUTES, function(attributeName) { $Array.forEach(AUTO_SIZE_ATTRIBUTES, function(attributeName) {
this.attributes[attributeName].setValue(
this.webviewNode.getAttribute(attributeName));
Object.defineProperty(this.webviewNode, attributeName, { Object.defineProperty(this.webviewNode, attributeName, {
get: function() { get: function() {
return this.attributes[attributeName].getValue(); return this.attributes[attributeName].getValue();
}.bind(this), }.bind(this),
set: function(value) { set: function(value) {
this.webviewNode.setAttribute(attributeName, value); this.attributes[attributeName].setValue(value);
}.bind(this), }.bind(this),
enumerable: true enumerable: true
}); });
...@@ -153,9 +149,8 @@ WebView.prototype.setupWebviewNodeProperties = function() { ...@@ -153,9 +149,8 @@ WebView.prototype.setupWebviewNodeProperties = function() {
getValue(); getValue();
}.bind(this), }.bind(this),
set: function(value) { set: function(value) {
this.webviewNode.setAttribute( this.attributes[WebViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY].
WebViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY, setValue(value);
value);
}.bind(this), }.bind(this),
enumerable: true enumerable: true
}); });
...@@ -179,7 +174,7 @@ WebView.prototype.setupWebviewNodeProperties = function() { ...@@ -179,7 +174,7 @@ WebView.prototype.setupWebviewNodeProperties = function() {
return this.attributes[WebViewConstants.ATTRIBUTE_NAME].getValue(); return this.attributes[WebViewConstants.ATTRIBUTE_NAME].getValue();
}.bind(this), }.bind(this),
set: function(value) { set: function(value) {
this.webviewNode.setAttribute(WebViewConstants.ATTRIBUTE_NAME, value); this.attributes[WebViewConstants.ATTRIBUTE_NAME].setValue(value);
}.bind(this), }.bind(this),
enumerable: true enumerable: true
}); });
...@@ -190,25 +185,17 @@ WebView.prototype.setupWebviewNodeProperties = function() { ...@@ -190,25 +185,17 @@ WebView.prototype.setupWebviewNodeProperties = function() {
return this.attributes[WebViewConstants.ATTRIBUTE_PARTITION].getValue(); return this.attributes[WebViewConstants.ATTRIBUTE_PARTITION].getValue();
}.bind(this), }.bind(this),
set: function(value) { set: function(value) {
var result = this.attributes[WebViewConstants.ATTRIBUTE_PARTITION]. this.attributes[WebViewConstants.ATTRIBUTE_PARTITION].setValue(value);
setValue(value);
if (result.error) {
throw result.error;
}
this.webviewNode.setAttribute(WebViewConstants.ATTRIBUTE_PARTITION,
value);
}.bind(this), }.bind(this),
enumerable: true enumerable: true
}); });
this.attributes[WebViewConstants.ATTRIBUTE_SRC].setValue(
this.webviewNode.getAttribute(WebViewConstants.ATTRIBUTE_SRC));
Object.defineProperty(this.webviewNode, WebViewConstants.ATTRIBUTE_SRC, { Object.defineProperty(this.webviewNode, WebViewConstants.ATTRIBUTE_SRC, {
get: function() { get: function() {
return this.attributes[WebViewConstants.ATTRIBUTE_SRC].getValue(); return this.attributes[WebViewConstants.ATTRIBUTE_SRC].getValue();
}.bind(this), }.bind(this),
set: function(value) { set: function(value) {
this.webviewNode.setAttribute(WebViewConstants.ATTRIBUTE_SRC, value); this.attributes[WebViewConstants.ATTRIBUTE_SRC].setValue(value);
}.bind(this), }.bind(this),
enumerable: true enumerable: true
}); });
...@@ -223,7 +210,7 @@ WebView.prototype.setupWebViewSrcAttributeMutationObserver = ...@@ -223,7 +210,7 @@ WebView.prototype.setupWebViewSrcAttributeMutationObserver =
this.srcAndPartitionObserver = new MutationObserver(function(mutations) { this.srcAndPartitionObserver = new MutationObserver(function(mutations) {
$Array.forEach(mutations, function(mutation) { $Array.forEach(mutations, function(mutation) {
var oldValue = mutation.oldValue; var oldValue = mutation.oldValue;
var newValue = this.webviewNode.getAttribute(mutation.attributeName); var newValue = this.attributes[mutation.attributeName].getValue();
if (oldValue != newValue) { if (oldValue != newValue) {
return; return;
} }
...@@ -246,17 +233,22 @@ WebView.prototype.setupWebViewSrcAttributeMutationObserver = ...@@ -246,17 +233,22 @@ WebView.prototype.setupWebViewSrcAttributeMutationObserver =
// attribute, if necessary. See BrowserPlugin::UpdateDOMAttribute for more // attribute, if necessary. See BrowserPlugin::UpdateDOMAttribute for more
// details. // details.
WebView.prototype.handleWebviewAttributeMutation = WebView.prototype.handleWebviewAttributeMutation =
function(name, oldValue, newValue) { function(attributeName, oldValue, newValue) {
if (AUTO_SIZE_ATTRIBUTES.indexOf(name) > -1) { // Certain changes (such as internally-initiated changes) to attributes should
this.attributes[name].setValue(newValue); // not be handled normally.
if (this.attributes[attributeName] &&
this.attributes[attributeName].ignoreNextMutation) {
this.attributes[attributeName].ignoreNextMutation = false;
return;
}
if (AUTO_SIZE_ATTRIBUTES.indexOf(attributeName) > -1) {
if (!this.guestInstanceId) { if (!this.guestInstanceId) {
return; return;
} }
// Convert autosize attribute to boolean.
var autosize = this.webviewNode.hasAttribute(
WebViewConstants.ATTRIBUTE_AUTOSIZE);
GuestViewInternal.setAutoSize(this.guestInstanceId, { GuestViewInternal.setAutoSize(this.guestInstanceId, {
'enableAutoSize': autosize, 'enableAutoSize': this.attributes[WebViewConstants.ATTRIBUTE_AUTOSIZE].
getValue(),
'min': { 'min': {
'width': parseInt(this. 'width': parseInt(this.
attributes[WebViewConstants.ATTRIBUTE_MINWIDTH].getValue() || 0), attributes[WebViewConstants.ATTRIBUTE_MINWIDTH].getValue() || 0),
...@@ -271,19 +263,13 @@ WebView.prototype.handleWebviewAttributeMutation = ...@@ -271,19 +263,13 @@ WebView.prototype.handleWebviewAttributeMutation =
} }
}); });
return; return;
} else if (name == WebViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY) { } else if (attributeName == WebViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY) {
// We treat null attribute (attribute removed) and the empty string as // We treat null attribute (attribute removed) and the empty string as
// one case. // one case.
oldValue = oldValue || ''; oldValue = oldValue || '';
newValue = newValue || ''; newValue = newValue || '';
if (oldValue === newValue) { if (oldValue === newValue || !this.guestInstanceId) {
return;
}
this.attributes[WebViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY].
setValue(newValue != '');
if (!this.guestInstanceId) {
return; return;
} }
...@@ -292,7 +278,7 @@ WebView.prototype.handleWebviewAttributeMutation = ...@@ -292,7 +278,7 @@ WebView.prototype.handleWebviewAttributeMutation =
this.attributes[WebViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY]. this.attributes[WebViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY].
getValue()); getValue());
return; return;
} else if (name == WebViewConstants.ATTRIBUTE_NAME) { } else if (attributeName == WebViewConstants.ATTRIBUTE_NAME) {
// We treat null attribute (attribute removed) and the empty string as // We treat null attribute (attribute removed) and the empty string as
// one case. // one case.
oldValue = oldValue || ''; oldValue = oldValue || '';
...@@ -301,19 +287,19 @@ WebView.prototype.handleWebviewAttributeMutation = ...@@ -301,19 +287,19 @@ WebView.prototype.handleWebviewAttributeMutation =
if (oldValue === newValue) { if (oldValue === newValue) {
return; return;
} }
this.attributes[WebViewConstants.ATTRIBUTE_NAME].setValue(newValue);
if (!this.guestInstanceId) { if (!this.guestInstanceId) {
return; return;
} }
WebViewInternal.setName(this.guestInstanceId, newValue); WebViewInternal.setName(this.guestInstanceId, newValue);
return; return;
} else if (name == WebViewConstants.ATTRIBUTE_SRC) { } else if (attributeName == WebViewConstants.ATTRIBUTE_SRC) {
// We treat null attribute (attribute removed) and the empty string as // We treat null attribute (attribute removed) and the empty string as
// one case. // one case.
oldValue = oldValue || ''; oldValue = oldValue || '';
newValue = newValue || ''; newValue = newValue || '';
// Once we have navigated, we don't allow clearing the src attribute. // 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 // Once <webview> enters a navigated state, it cannot return to a
// placeholder state. // placeholder state.
if (newValue == '' && oldValue != '') { if (newValue == '' && oldValue != '') {
// src attribute changes normally initiate a navigation. We suppress // src attribute changes normally initiate a navigation. We suppress
...@@ -323,28 +309,23 @@ WebView.prototype.handleWebviewAttributeMutation = ...@@ -323,28 +309,23 @@ WebView.prototype.handleWebviewAttributeMutation =
this.webviewNode.setAttribute(WebViewConstants.ATTRIBUTE_SRC, oldValue); this.webviewNode.setAttribute(WebViewConstants.ATTRIBUTE_SRC, oldValue);
return; return;
} }
this.attributes[WebViewConstants.ATTRIBUTE_SRC].setValue(newValue);
if (this.ignoreNextSrcAttributeChange) { if (this.ignoreNextSrcAttributeChange) {
// Don't allow the src mutation observer to see this change. // Don't allow the src mutation observer to see this change.
this.srcAndPartitionObserver.takeRecords(); this.srcAndPartitionObserver.takeRecords();
this.ignoreNextSrcAttributeChange = false; this.ignoreNextSrcAttributeChange = false;
return; return;
} }
var result = {}; this.parseSrcAttribute();
this.parseSrcAttribute(result); } else if (attributeName == WebViewConstants.ATTRIBUTE_PARTITION) {
this.attributes[WebViewConstants.ATTRIBUTE_PARTITION].handleMutation(
if (result.error) { oldValue, newValue);
throw result.error;
}
} else if (name == WebViewConstants.ATTRIBUTE_PARTITION) {
// Note that throwing error here won't synchronously propagate.
this.attributes[WebViewConstants.ATTRIBUTE_PARTITION].setValue(newValue);
} }
}; };
WebView.prototype.handleBrowserPluginAttributeMutation = WebView.prototype.handleBrowserPluginAttributeMutation =
function(name, oldValue, newValue) { function(attributeName, oldValue, newValue) {
if (name == WebViewConstants.ATTRIBUTE_INTERNALINSTANCEID && if (attributeName == WebViewConstants.ATTRIBUTE_INTERNALINSTANCEID &&
!oldValue && !!newValue) { !oldValue && !!newValue) {
this.browserPluginNode.removeAttribute( this.browserPluginNode.removeAttribute(
WebViewConstants.ATTRIBUTE_INTERNALINSTANCEID); WebViewConstants.ATTRIBUTE_INTERNALINSTANCEID);
...@@ -417,7 +398,7 @@ WebView.prototype.onSizeChanged = function(webViewEvent) { ...@@ -417,7 +398,7 @@ WebView.prototype.onSizeChanged = function(webViewEvent) {
minHeight = maxHeight; minHeight = maxHeight;
} }
if (!this.webviewNode.hasAttribute(WebViewConstants.ATTRIBUTE_AUTOSIZE) || if (!this.attributes[WebViewConstants.ATTRIBUTE_AUTOSIZE].getValue() ||
(newWidth >= minWidth && (newWidth >= minWidth &&
newWidth <= maxWidth && newWidth <= maxWidth &&
newHeight >= minHeight && newHeight >= minHeight &&
...@@ -439,15 +420,9 @@ WebView.prototype.hasNavigated = function() { ...@@ -439,15 +420,9 @@ WebView.prototype.hasNavigated = function() {
return !this.beforeFirstNavigation; return !this.beforeFirstNavigation;
}; };
WebView.prototype.parseSrcAttribute = function(result) { WebView.prototype.parseSrcAttribute = function() {
if (!this.attributes[WebViewConstants.ATTRIBUTE_PARTITION].validPartitionId) { if (!this.attributes[WebViewConstants.ATTRIBUTE_PARTITION].validPartitionId ||
result.error = WebViewConstants.ERROR_MSG_INVALID_PARTITION_ATTRIBUTE; !this.attributes[WebViewConstants.ATTRIBUTE_SRC].getValue()) {
return;
}
this.attributes[WebViewConstants.ATTRIBUTE_SRC].setValue(
this.webviewNode.getAttribute(WebViewConstants.ATTRIBUTE_SRC));
if (!this.attributes[WebViewConstants.ATTRIBUTE_SRC].getValue()) {
return; return;
} }
...@@ -469,22 +444,16 @@ WebView.prototype.parseAttributes = function() { ...@@ -469,22 +444,16 @@ WebView.prototype.parseAttributes = function() {
if (!this.elementAttached) { if (!this.elementAttached) {
return; return;
} }
var attributeValue = this.webviewNode.getAttribute( this.parseSrcAttribute();
WebViewConstants.ATTRIBUTE_PARTITION);
var result = this.attributes[WebViewConstants.ATTRIBUTE_PARTITION].setValue(
attributeValue);
this.parseSrcAttribute(result);
}; };
WebView.prototype.createGuest = function() { WebView.prototype.createGuest = function() {
if (this.pendingGuestCreation) { if (this.pendingGuestCreation) {
return; return;
} }
var storagePartitionId =
this.webviewNode.getAttribute(WebViewConstants.ATTRIBUTE_PARTITION) ||
this.webviewNode[WebViewConstants.ATTRIBUTE_PARTITION];
var params = { var params = {
'storagePartitionId': storagePartitionId 'storagePartitionId': this.attributes[
WebViewConstants.ATTRIBUTE_PARTITION].getValue()
}; };
GuestViewInternal.createGuest( GuestViewInternal.createGuest(
'webview', 'webview',
...@@ -502,13 +471,11 @@ WebView.prototype.createGuest = function() { ...@@ -502,13 +471,11 @@ WebView.prototype.createGuest = function() {
}; };
WebView.prototype.onFrameNameChanged = function(name) { WebView.prototype.onFrameNameChanged = function(name) {
this.attributes[WebViewConstants.ATTRIBUTE_NAME].setValue(name || ''); name = name || '';
if (this.attributes[WebViewConstants.ATTRIBUTE_NAME].getValue() === '') { if (name === '') {
this.webviewNode.removeAttribute(WebViewConstants.ATTRIBUTE_NAME); this.webviewNode.removeAttribute(WebViewConstants.ATTRIBUTE_NAME);
} else { } else {
this.webviewNode.setAttribute( this.attributes[WebViewConstants.ATTRIBUTE_NAME].setValue(name);
WebViewConstants.ATTRIBUTE_NAME,
this.attributes[WebViewConstants.ATTRIBUTE_NAME].getValue());
} }
}; };
...@@ -543,7 +510,7 @@ WebView.prototype.onLoadCommit = function( ...@@ -543,7 +510,7 @@ WebView.prototype.onLoadCommit = function(
this.currentEntryIndex = currentEntryIndex; this.currentEntryIndex = currentEntryIndex;
this.entryCount = entryCount; this.entryCount = entryCount;
this.processId = processId; this.processId = processId;
var oldValue = this.webviewNode.getAttribute(WebViewConstants.ATTRIBUTE_SRC); var oldValue = this.attributes[WebViewConstants.ATTRIBUTE_SRC].getValue();
var newValue = url; var newValue = url;
if (isTopLevel && (oldValue != newValue)) { if (isTopLevel && (oldValue != newValue)) {
// Touching the src attribute triggers a navigation. To avoid // Touching the src attribute triggers a navigation. To avoid
...@@ -555,8 +522,6 @@ WebView.prototype.onLoadCommit = function( ...@@ -555,8 +522,6 @@ WebView.prototype.onLoadCommit = function(
}; };
WebView.prototype.onAttach = function(storagePartitionId) { WebView.prototype.onAttach = function(storagePartitionId) {
this.webviewNode.setAttribute(WebViewConstants.ATTRIBUTE_PARTITION,
storagePartitionId);
this.attributes[WebViewConstants.ATTRIBUTE_PARTITION].setValue( this.attributes[WebViewConstants.ATTRIBUTE_PARTITION].setValue(
storagePartitionId); storagePartitionId);
}; };
...@@ -564,9 +529,8 @@ WebView.prototype.onAttach = function(storagePartitionId) { ...@@ -564,9 +529,8 @@ WebView.prototype.onAttach = function(storagePartitionId) {
WebView.prototype.buildAttachParams = function(isNewWindow) { WebView.prototype.buildAttachParams = function(isNewWindow) {
var params = { var params = {
'allowtransparency': this.attributes[ 'allowtransparency': this.attributes[
WebViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY].getValue() || false, WebViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY].getValue(),
'autosize': this.webviewNode.hasAttribute( 'autosize': this.attributes[WebViewConstants.ATTRIBUTE_AUTOSIZE].getValue(),
WebViewConstants.ATTRIBUTE_AUTOSIZE),
'instanceId': this.viewInstanceId, 'instanceId': this.viewInstanceId,
'maxheight': parseInt(this.attributes[WebViewConstants.ATTRIBUTE_MAXHEIGHT]. 'maxheight': parseInt(this.attributes[WebViewConstants.ATTRIBUTE_MAXHEIGHT].
getValue() || 0), getValue() || 0),
......
...@@ -13,63 +13,69 @@ var WebViewConstants = require('webViewConstants').WebViewConstants; ...@@ -13,63 +13,69 @@ var WebViewConstants = require('webViewConstants').WebViewConstants;
// Default implementation of a WebView attribute. // Default implementation of a WebView attribute.
function WebViewAttribute(name, webViewImpl) { function WebViewAttribute(name, webViewImpl) {
this.name = name; this.name = name;
this.value = '';
this.webViewImpl = webViewImpl; this.webViewImpl = webViewImpl;
this.ignoreNextMutation = false;
} }
// Retrieves and returns the attribute's value.
WebViewAttribute.prototype.getValue = function() { WebViewAttribute.prototype.getValue = function() {
return this.value || ''; return this.webViewImpl.webviewNode.getAttribute(this.name) || '';
}; };
// Sets the attribute's value.
WebViewAttribute.prototype.setValue = function(value) { WebViewAttribute.prototype.setValue = function(value) {
this.value = value; this.webViewImpl.webviewNode.setAttribute(this.name, value || '');
}; };
// Called when the attribute's value changes.
WebViewAttribute.prototype.handleMutation = function() {}
// Attribute specifying whether transparency is allowed in the webview.
function BooleanAttribute(name, webViewImpl) {
WebViewAttribute.call(this, name, webViewImpl);
}
BooleanAttribute.prototype = new WebViewAttribute();
BooleanAttribute.prototype.getValue = function() {
// This attribute is treated as a boolean, and is retrieved as such.
return this.webViewImpl.webviewNode.hasAttribute(this.name);
}
BooleanAttribute.prototype.setValue = function(value) {
if (!value) {
this.webViewImpl.webviewNode.removeAttribute(this.name);
} else {
this.webViewImpl.webviewNode.setAttribute(this.name, '');
}
}
// Attribute representing the state of the storage partition. // Attribute representing the state of the storage partition.
function Partition(webViewImpl) { function Partition(webViewImpl) {
WebViewAttribute.call(this,
WebViewConstants.ATTRIBUTE_PARTITION,
webViewImpl);
this.validPartitionId = true; this.validPartitionId = true;
this.persistStorage = false;
this.storagePartitionId = '';
this.webViewImpl = webViewImpl;
} }
Partition.prototype = new WebViewAttribute( Partition.prototype = new WebViewAttribute();
WebViewConstants.ATTRIBUTE_PARTITION);
Partition.prototype.getValue = function() { Partition.prototype.handleMutation = function(oldValue, newValue) {
if (!this.validPartitionId) { newValue = newValue || '';
return '';
}
return (this.persistStorage ? 'persist:' : '') + this.storagePartitionId;
};
Partition.prototype.setValue = function(value) { // The partition cannot change if the webview has already navigated.
var result = {}; if (!this.webViewImpl.beforeFirstNavigation) {
var hasNavigated = !this.webViewImpl.beforeFirstNavigation; window.console.error(WebViewConstants.ERROR_MSG_ALREADY_NAVIGATED);
if (hasNavigated) { this.ignoreNextMutation = true;
result.error = WebViewConstants.ERROR_MSG_ALREADY_NAVIGATED; this.webViewImpl.webviewNode.setAttribute(this.name, oldValue);
return result; return;
}
if (!value) {
value = '';
} }
if (newValue == 'persist:') {
var LEN = 'persist:'.length;
if (value.substr(0, LEN) == 'persist:') {
value = value.substr(LEN);
if (!value) {
this.validPartitionId = false; this.validPartitionId = false;
result.error = WebViewConstants.ERROR_MSG_INVALID_PARTITION_ATTRIBUTE; window.console.error(
return result; WebViewConstants.ERROR_MSG_INVALID_PARTITION_ATTRIBUTE);
} }
this.persistStorage = true; }
} else {
this.persistStorage = false;
}
this.storagePartitionId = value;
return result;
};
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
...@@ -79,12 +85,14 @@ WebView.prototype.setupWebViewAttributes = function() { ...@@ -79,12 +85,14 @@ WebView.prototype.setupWebViewAttributes = function() {
// Initialize the attributes with special behavior (and custom attribute // Initialize the attributes with special behavior (and custom attribute
// objects). // objects).
this.attributes[WebViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY] =
new BooleanAttribute(WebViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY, this);
this.attributes[WebViewConstants.ATTRIBUTE_AUTOSIZE] =
new BooleanAttribute(WebViewConstants.ATTRIBUTE_AUTOSIZE, this);
this.attributes[WebViewConstants.ATTRIBUTE_PARTITION] = new Partition(this); this.attributes[WebViewConstants.ATTRIBUTE_PARTITION] = new Partition(this);
// Initialize the remaining attributes, which have default behavior. // Initialize the remaining attributes, which have default behavior.
var defaultAttributes = [WebViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY, var defaultAttributes = [WebViewConstants.ATTRIBUTE_MAXHEIGHT,
WebViewConstants.ATTRIBUTE_AUTOSIZE,
WebViewConstants.ATTRIBUTE_MAXHEIGHT,
WebViewConstants.ATTRIBUTE_MAXWIDTH, WebViewConstants.ATTRIBUTE_MAXWIDTH,
WebViewConstants.ATTRIBUTE_MINHEIGHT, WebViewConstants.ATTRIBUTE_MINHEIGHT,
WebViewConstants.ATTRIBUTE_MINWIDTH, WebViewConstants.ATTRIBUTE_MINWIDTH,
......
...@@ -71,15 +71,22 @@ embedder.test.succeed = function() { ...@@ -71,15 +71,22 @@ embedder.test.succeed = function() {
function testAllowTransparencyAttribute() { function testAllowTransparencyAttribute() {
var webview = document.createElement('webview'); var webview = document.createElement('webview');
webview.src = 'data:text/html,webview test'; webview.src = 'data:text/html,webview test';
embedder.test.assertFalse(webview.hasAttribute('allowtransparency'));
embedder.test.assertFalse(webview.allowtransparency);
webview.allowtransparency = true; webview.allowtransparency = true;
webview.addEventListener('loadstop', function(e) { webview.addEventListener('loadstop', function(e) {
embedder.test.assertTrue(webview.hasAttribute('allowtransparency')); embedder.test.assertTrue(webview.hasAttribute('allowtransparency'));
webview.allowtransparency = false;
embedder.test.assertTrue(webview.allowtransparency); embedder.test.assertTrue(webview.allowtransparency);
embedder.test.assertTrue(webview.hasAttribute('allowtransparency')); webview.allowtransparency = false;
webview.removeAttribute('allowtransparency'); embedder.test.assertFalse(webview.hasAttribute('allowtransparency'));
embedder.test.assertFalse(webview.allowtransparency);
webview.allowtransparency = '';
embedder.test.assertFalse(webview.hasAttribute('allowtransparency'));
embedder.test.assertFalse(webview.allowtransparency); embedder.test.assertFalse(webview.allowtransparency);
webview.allowtransparency = 'some string';
embedder.test.assertTrue(webview.hasAttribute('allowtransparency'));
embedder.test.assertTrue(webview.allowtransparency);
embedder.test.succeed(); embedder.test.succeed();
}); });
...@@ -1282,21 +1289,17 @@ function testOnEventProperties() { ...@@ -1282,21 +1289,17 @@ function testOnEventProperties() {
document.body.appendChild(webview); document.body.appendChild(webview);
} }
// This test verifies that setting the partition attribute after the src has // This test verifies that the partion attribute cannot be changed after the src
// been set raises an exception. // has been set.
function testPartitionRaisesException() { function testPartitionChangeAfterNavigation() {
var webview = document.createElement('webview'); var webview = document.createElement('webview');
var partitionAttribute = arguments.callee.name; var partitionAttribute = arguments.callee.name;
webview.setAttribute('partition', partitionAttribute); webview.setAttribute('partition', partitionAttribute);
var loadstopHandler = function(e) { var loadstopHandler = function(e) {
try {
webview.partition = 'illegal'; webview.partition = 'illegal';
embedder.test.fail();
} catch (e) {
embedder.test.assertEq(partitionAttribute, webview.partition); embedder.test.assertEq(partitionAttribute, webview.partition);
embedder.test.succeed(); embedder.test.succeed();
}
}; };
webview.addEventListener('loadstop', loadstopHandler); webview.addEventListener('loadstop', loadstopHandler);
...@@ -1707,7 +1710,7 @@ embedder.test.testList = { ...@@ -1707,7 +1710,7 @@ embedder.test.testList = {
'testNewWindowNoReferrerLink': testNewWindowNoReferrerLink, 'testNewWindowNoReferrerLink': testNewWindowNoReferrerLink,
'testNewWindowTwoListeners': testNewWindowTwoListeners, 'testNewWindowTwoListeners': testNewWindowTwoListeners,
'testOnEventProperties': testOnEventProperties, 'testOnEventProperties': testOnEventProperties,
'testPartitionRaisesException': testPartitionRaisesException, 'testPartitionChangeAfterNavigation': testPartitionChangeAfterNavigation,
'testPartitionRemovalAfterNavigationFails': 'testPartitionRemovalAfterNavigationFails':
testPartitionRemovalAfterNavigationFails, testPartitionRemovalAfterNavigationFails,
'testReassignSrcAttribute': testReassignSrcAttribute, 'testReassignSrcAttribute': testReassignSrcAttribute,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment