1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // This module implements the attributes of the <webview> tag.
7 var GuestViewAttributes = require('guestViewAttributes').GuestViewAttributes;
8 var WebViewConstants = require('webViewConstants').WebViewConstants;
9 var WebViewImpl = require('webView').WebViewImpl;
10 var WebViewInternal = require('webViewInternal').WebViewInternal;
12 // -----------------------------------------------------------------------------
13 // AllowScalingAttribute object.
15 // Attribute that specifies whether scaling is allowed in the webview.
16 function AllowScalingAttribute(view) {
17 GuestViewAttributes.BooleanAttribute.call(
18 this, WebViewConstants.ATTRIBUTE_ALLOWSCALING, view);
21 AllowScalingAttribute.prototype.__proto__ =
22 GuestViewAttributes.BooleanAttribute.prototype;
24 AllowScalingAttribute.prototype.handleMutation = function(oldValue, newValue) {
25 if (!this.view.guest.getId())
28 WebViewInternal.setAllowScaling(this.view.guest.getId(), this.getValue());
31 // -----------------------------------------------------------------------------
32 // AllowTransparencyAttribute object.
34 // Attribute that specifies whether transparency is allowed in the webview.
35 function AllowTransparencyAttribute(view) {
36 GuestViewAttributes.BooleanAttribute.call(
37 this, WebViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY, view);
40 AllowTransparencyAttribute.prototype.__proto__ =
41 GuestViewAttributes.BooleanAttribute.prototype;
43 AllowTransparencyAttribute.prototype.handleMutation = function(oldValue,
45 if (!this.view.guest.getId())
48 WebViewInternal.setAllowTransparency(this.view.guest.getId(),
52 // -----------------------------------------------------------------------------
53 // AutosizeDimensionAttribute object.
55 // Attribute used to define the demension limits of autosizing.
56 function AutosizeDimensionAttribute(name, view) {
57 GuestViewAttributes.IntegerAttribute.call(this, name, view);
60 AutosizeDimensionAttribute.prototype.__proto__ =
61 GuestViewAttributes.IntegerAttribute.prototype;
63 AutosizeDimensionAttribute.prototype.handleMutation = function(
65 if (!this.view.guest.getId())
68 this.view.guest.setSize({
69 'enableAutoSize': this.view.attributes[
70 WebViewConstants.ATTRIBUTE_AUTOSIZE].getValue(),
72 'width': this.view.attributes[
73 WebViewConstants.ATTRIBUTE_MINWIDTH].getValue(),
74 'height': this.view.attributes[
75 WebViewConstants.ATTRIBUTE_MINHEIGHT].getValue()
78 'width': this.view.attributes[
79 WebViewConstants.ATTRIBUTE_MAXWIDTH].getValue(),
80 'height': this.view.attributes[
81 WebViewConstants.ATTRIBUTE_MAXHEIGHT].getValue()
87 // -----------------------------------------------------------------------------
88 // AutosizeAttribute object.
90 // Attribute that specifies whether the webview should be autosized.
91 function AutosizeAttribute(view) {
92 GuestViewAttributes.BooleanAttribute.call(
93 this, WebViewConstants.ATTRIBUTE_AUTOSIZE, view);
96 AutosizeAttribute.prototype.__proto__ =
97 GuestViewAttributes.BooleanAttribute.prototype;
99 AutosizeAttribute.prototype.handleMutation =
100 AutosizeDimensionAttribute.prototype.handleMutation;
102 // -----------------------------------------------------------------------------
103 // NameAttribute object.
105 // Attribute that sets the guest content's window.name object.
106 function NameAttribute(view) {
107 GuestViewAttributes.Attribute.call(
108 this, WebViewConstants.ATTRIBUTE_NAME, view);
111 NameAttribute.prototype.__proto__ = GuestViewAttributes.Attribute.prototype
113 NameAttribute.prototype.handleMutation = function(oldValue, newValue) {
114 oldValue = oldValue || '';
115 newValue = newValue || '';
116 if (oldValue === newValue || !this.view.guest.getId())
119 WebViewInternal.setName(this.view.guest.getId(), newValue);
122 NameAttribute.prototype.setValue = function(value) {
125 this.view.element.removeAttribute(this.name);
127 this.view.element.setAttribute(this.name, value);
130 // -----------------------------------------------------------------------------
131 // PartitionAttribute object.
133 // Attribute representing the state of the storage partition.
134 function PartitionAttribute(view) {
135 GuestViewAttributes.Attribute.call(
136 this, WebViewConstants.ATTRIBUTE_PARTITION, view);
137 this.validPartitionId = true;
140 PartitionAttribute.prototype.__proto__ =
141 GuestViewAttributes.Attribute.prototype;
143 PartitionAttribute.prototype.handleMutation = function(oldValue, newValue) {
144 newValue = newValue || '';
146 // The partition cannot change if the webview has already navigated.
147 if (!this.view.attributes[
148 WebViewConstants.ATTRIBUTE_SRC].beforeFirstNavigation) {
149 window.console.error(WebViewConstants.ERROR_MSG_ALREADY_NAVIGATED);
150 this.setValueIgnoreMutation(oldValue);
153 if (newValue == 'persist:') {
154 this.validPartitionId = false;
155 window.console.error(
156 WebViewConstants.ERROR_MSG_INVALID_PARTITION_ATTRIBUTE);
160 PartitionAttribute.prototype.detach = function() {
161 this.validPartitionId = true;
164 // -----------------------------------------------------------------------------
165 // SrcAttribute object.
167 // Attribute that handles the location and navigation of the webview.
168 function SrcAttribute(view) {
169 GuestViewAttributes.Attribute.call(
170 this, WebViewConstants.ATTRIBUTE_SRC, view);
171 this.setupMutationObserver();
172 this.beforeFirstNavigation = true;
175 SrcAttribute.prototype.__proto__ = GuestViewAttributes.Attribute.prototype;
177 SrcAttribute.prototype.setValueIgnoreMutation = function(value) {
178 GuestViewAttributes.Attribute.prototype.setValueIgnoreMutation.call(
180 // takeRecords() is needed to clear queued up src mutations. Without it, it is
181 // possible for this change to get picked up asyncronously by src's mutation
182 // observer |observer|, and then get handled even though we do not want to
183 // handle this mutation.
184 this.observer.takeRecords();
187 SrcAttribute.prototype.handleMutation = function(oldValue, newValue) {
188 // Once we have navigated, we don't allow clearing the src attribute.
189 // Once <webview> enters a navigated state, it cannot return to a
190 // placeholder state.
191 if (!newValue && oldValue) {
192 // src attribute changes normally initiate a navigation. We suppress
193 // the next src attribute handler call to avoid reloading the page
194 // on every guest-initiated navigation.
195 this.setValueIgnoreMutation(oldValue);
201 SrcAttribute.prototype.attach = function() {
205 SrcAttribute.prototype.detach = function() {
206 this.beforeFirstNavigation = true;
209 // The purpose of this mutation observer is to catch assignment to the src
210 // attribute without any changes to its value. This is useful in the case
211 // where the webview guest has crashed and navigating to the same address
212 // spawns off a new process.
213 SrcAttribute.prototype.setupMutationObserver =
215 this.observer = new MutationObserver(function(mutations) {
216 $Array.forEach(mutations, function(mutation) {
217 var oldValue = mutation.oldValue;
218 var newValue = this.getValue();
219 if (oldValue != newValue) {
222 this.handleMutation(oldValue, newValue);
227 attributeOldValue: true,
228 attributeFilter: [this.name]
230 this.observer.observe(this.view.element, params);
233 SrcAttribute.prototype.parse = function() {
234 if (!this.view.elementAttached ||
235 !this.view.attributes[
236 WebViewConstants.ATTRIBUTE_PARTITION].validPartitionId ||
241 if (!this.view.guest.getId()) {
242 if (this.beforeFirstNavigation) {
243 this.beforeFirstNavigation = false;
244 this.view.createGuest();
249 WebViewInternal.navigate(this.view.guest.getId(), this.getValue());
252 // -----------------------------------------------------------------------------
254 // Sets up all of the webview attributes.
255 WebViewImpl.prototype.setupAttributes = function() {
256 this.attributes[WebViewConstants.ATTRIBUTE_ALLOWSCALING] =
257 new AllowScalingAttribute(this);
258 this.attributes[WebViewConstants.ATTRIBUTE_ALLOWTRANSPARENCY] =
259 new AllowTransparencyAttribute(this);
260 this.attributes[WebViewConstants.ATTRIBUTE_AUTOSIZE] =
261 new AutosizeAttribute(this);
262 this.attributes[WebViewConstants.ATTRIBUTE_NAME] =
263 new NameAttribute(this);
264 this.attributes[WebViewConstants.ATTRIBUTE_PARTITION] =
265 new PartitionAttribute(this);
266 this.attributes[WebViewConstants.ATTRIBUTE_SRC] =
267 new SrcAttribute(this);
269 var autosizeAttributes = [WebViewConstants.ATTRIBUTE_MAXHEIGHT,
270 WebViewConstants.ATTRIBUTE_MAXWIDTH,
271 WebViewConstants.ATTRIBUTE_MINHEIGHT,
272 WebViewConstants.ATTRIBUTE_MINWIDTH];
273 for (var i = 0; autosizeAttributes[i]; ++i) {
274 this.attributes[autosizeAttributes[i]] =
275 new AutosizeDimensionAttribute(autosizeAttributes[i], this);