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

Side by Side Diff: extensions/renderer/resources/guest_view/guest_view_container.js

Issue 1165773004: Extract the element implementation logic to function mods in <webview>. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@qui
Patch Set: Address comments Created 5 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 unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // This module implements the shared functionality for different guestview 5 // This module implements the shared functionality for different guestview
6 // containers, such as web_view, app_view, etc. 6 // containers, such as web_view, app_view, etc.
7 7
8 var DocumentNatives = requireNative('document_natives'); 8 var DocumentNatives = requireNative('document_natives');
9 var GuestView = require('guestView').GuestView; 9 var GuestView = require('guestView').GuestView;
10 var GuestViewInternalNatives = requireNative('guest_view_internal'); 10 var GuestViewInternalNatives = requireNative('guest_view_internal');
11 var IdGenerator = requireNative('id_generator'); 11 var IdGenerator = requireNative('id_generator');
12 12
13 function GuestViewContainer(element, viewType) { 13 function GuestViewContainer(element, viewType) {
14 privates(element).internal = this; 14 privates(element).internal = this;
15 this.attributes = {}; 15 this.attributes = {};
16 this.element = element; 16 this.element = element;
17 this.elementAttached = false; 17 this.elementAttached = false;
18 this.viewInstanceId = IdGenerator.GetNextId(); 18 this.viewInstanceId = IdGenerator.GetNextId();
19 this.viewType = viewType; 19 this.viewType = viewType;
20 20
21 this.setupGuestProperty(); 21 this.setupGuestProperty();
22 this.guest = new GuestView(viewType); 22 this.guest = new GuestView(viewType);
23 this.setupAttributes(); 23 this.setupAttributes();
24 24
25 privates(this).browserPluginElement = this.createBrowserPluginElement(); 25 privates(this).internalElement = this.createInternalElement$();
26 this.setupFocusPropagation(); 26 this.setupFocusPropagation();
27 var shadowRoot = this.element.createShadowRoot(); 27 var shadowRoot = this.element.createShadowRoot();
28 shadowRoot.appendChild(privates(this).browserPluginElement); 28 shadowRoot.appendChild(privates(this).internalElement);
29 29
30 GuestViewInternalNatives.RegisterView(this.viewInstanceId, this); 30 GuestViewInternalNatives.RegisterView(this.viewInstanceId, this);
31 } 31 }
32 32
33 // Forward public API methods from |proto| to their internal implementations. 33 // Forward public API methods from |proto| to their internal implementations.
34 GuestViewContainer.forwardApiMethods = function(proto, apiMethods) { 34 GuestViewContainer.forwardApiMethods = function(proto, apiMethods) {
35 var createProtoHandler = function(m) { 35 var createProtoHandler = function(m) {
36 return function(var_args) { 36 return function(var_args) {
37 var internal = privates(this).internal; 37 var internal = privates(this).internal;
38 return $Function.apply(internal[m], internal, arguments); 38 return $Function.apply(internal[m], internal, arguments);
39 }; 39 };
40 }; 40 };
41 for (var i = 0; apiMethods[i]; ++i) { 41 for (var i = 0; apiMethods[i]; ++i) {
42 proto[apiMethods[i]] = createProtoHandler(apiMethods[i]); 42 proto[apiMethods[i]] = createProtoHandler(apiMethods[i]);
43 } 43 }
44 }; 44 };
45 45
46 // Registers the browserplugin and guestview as custom elements once the 46 // Registers the browserplugin and guestview as custom elements once the
47 // document has loaded. 47 // document has loaded.
48 GuestViewContainer.registerElement = function(guestViewContainerType) { 48 GuestViewContainer.registerElement = function(guestViewContainerType) {
49 var useCapture = true; 49 var useCapture = true;
50 window.addEventListener('readystatechange', function listener(event) { 50 window.addEventListener('readystatechange', function listener(event) {
51 if (document.readyState == 'loading') 51 if (document.readyState == 'loading')
52 return; 52 return;
53 53
54 registerBrowserPluginElement( 54 registerInternalElement(guestViewContainerType.VIEW_TYPE.toLowerCase());
55 guestViewContainerType.VIEW_TYPE.toLowerCase());
56 registerGuestViewElement(guestViewContainerType); 55 registerGuestViewElement(guestViewContainerType);
57 window.removeEventListener(event.type, listener, useCapture); 56 window.removeEventListener(event.type, listener, useCapture);
58 }, useCapture); 57 }, useCapture);
59 }; 58 };
60 59
61 // Create the 'guest' property to track new GuestViews and always listen for 60 // Create the 'guest' property to track new GuestViews and always listen for
62 // their resizes. 61 // their resizes.
63 GuestViewContainer.prototype.setupGuestProperty = function() { 62 GuestViewContainer.prototype.setupGuestProperty = function() {
64 $Object.defineProperty(this, 'guest', { 63 $Object.defineProperty(this, 'guest', {
65 get: function() { 64 get: function() {
(...skipping 11 matching lines...) Expand all
77 contentResizeEvent.oldHeight = e.oldHeight; 76 contentResizeEvent.oldHeight = e.oldHeight;
78 contentResizeEvent.newWidth = e.newWidth; 77 contentResizeEvent.newWidth = e.newWidth;
79 contentResizeEvent.newHeight = e.newHeight; 78 contentResizeEvent.newHeight = e.newHeight;
80 this.dispatchEvent(contentResizeEvent); 79 this.dispatchEvent(contentResizeEvent);
81 }.bind(this); 80 }.bind(this);
82 }.bind(this), 81 }.bind(this),
83 enumerable: true 82 enumerable: true
84 }); 83 });
85 }; 84 };
86 85
87 GuestViewContainer.prototype.createBrowserPluginElement = function() { 86 GuestViewContainer.prototype.createInternalElement$ = function() {
88 // We create BrowserPlugin as a custom element in order to observe changes 87 // We create BrowserPlugin as a custom element in order to observe changes
89 // to attributes synchronously. 88 // to attributes synchronously.
90 var browserPluginElement = 89 var browserPluginElement =
91 new GuestViewContainer[this.viewType + 'BrowserPlugin'](); 90 new GuestViewContainer[this.viewType + 'BrowserPlugin']();
92 privates(browserPluginElement).internal = this; 91 privates(browserPluginElement).internal = this;
93 return browserPluginElement; 92 return browserPluginElement;
94 }; 93 };
95 94
96 GuestViewContainer.prototype.setupFocusPropagation = function() { 95 GuestViewContainer.prototype.setupFocusPropagation = function() {
97 if (!this.element.hasAttribute('tabIndex')) { 96 if (!this.element.hasAttribute('tabIndex')) {
98 // GuestViewContainer needs a tabIndex in order to be focusable. 97 // GuestViewContainer needs a tabIndex in order to be focusable.
99 // TODO(fsamuel): It would be nice to avoid exposing a tabIndex attribute 98 // TODO(fsamuel): It would be nice to avoid exposing a tabIndex attribute
100 // to allow GuestViewContainer to be focusable. 99 // to allow GuestViewContainer to be focusable.
101 // See http://crbug.com/231664. 100 // See http://crbug.com/231664.
102 this.element.setAttribute('tabIndex', -1); 101 this.element.setAttribute('tabIndex', -1);
103 } 102 }
104 this.element.addEventListener('focus', this.weakWrapper(function(e) { 103 this.element.addEventListener('focus', this.weakWrapper(function(e) {
105 // Focus the BrowserPlugin when the GuestViewContainer takes focus. 104 // Focus the BrowserPlugin when the GuestViewContainer takes focus.
106 privates(this).browserPluginElement.focus(); 105 privates(this).internalElement.focus();
107 })); 106 }));
108 this.element.addEventListener('blur', this.weakWrapper(function(e) { 107 this.element.addEventListener('blur', this.weakWrapper(function(e) {
109 // Blur the BrowserPlugin when the GuestViewContainer loses focus. 108 // Blur the BrowserPlugin when the GuestViewContainer loses focus.
110 privates(this).browserPluginElement.blur(); 109 privates(this).internalElement.blur();
111 })); 110 }));
112 }; 111 };
113 112
114 GuestViewContainer.prototype.attachWindow = function() { 113 GuestViewContainer.prototype.attachWindow$ = function() {
115 if (!this.internalInstanceId) { 114 if (!this.internalInstanceId) {
116 return true; 115 return true;
117 } 116 }
118 117
119 this.guest.attach(this.internalInstanceId, 118 this.guest.attach(this.internalInstanceId,
120 this.viewInstanceId, 119 this.viewInstanceId,
121 this.buildParams()); 120 this.buildParams());
122 return true; 121 return true;
123 }; 122 };
124 123
125 GuestViewContainer.prototype.handleBrowserPluginAttributeMutation = 124 GuestViewContainer.prototype.onInternalInstanceId = function(
125 internalInstanceId) {
126 this.internalInstanceId = internalInstanceId;
127
128 // Track when the element resizes using the element resize callback.
129 GuestViewInternalNatives.RegisterElementResizeCallback(
130 this.internalInstanceId, this.weakWrapper(this.onElementResize));
131
132 if (!this.guest.getId()) {
133 return;
134 }
135 this.guest.attach(this.internalInstanceId,
136 this.viewInstanceId,
137 this.buildParams());
138 };
139
140 GuestViewContainer.prototype.handleInternalElementAttributeMutation =
126 function(name, oldValue, newValue) { 141 function(name, oldValue, newValue) {
127 if (name == 'internalinstanceid' && !oldValue && !!newValue) { 142 if (name == 'internalinstanceid' && !oldValue && !!newValue) {
128 privates(this).browserPluginElement.removeAttribute('internalinstanceid'); 143 privates(this).internalElement.removeAttribute('internalinstanceid');
129 this.internalInstanceId = parseInt(newValue); 144 this.onInternalInstanceId(parseInt(newValue));
130
131 // Track when the element resizes using the element resize callback.
132 GuestViewInternalNatives.RegisterElementResizeCallback(
133 this.internalInstanceId, this.weakWrapper(this.onElementResize));
134
135 if (!this.guest.getId()) {
136 return;
137 }
138 this.guest.attach(this.internalInstanceId,
139 this.viewInstanceId,
140 this.buildParams());
141 } 145 }
142 }; 146 };
143 147
144 GuestViewContainer.prototype.onElementResize = function(newWidth, newHeight) { 148 GuestViewContainer.prototype.onElementResize = function(newWidth, newHeight) {
145 if (!this.guest.getId()) 149 if (!this.guest.getId())
146 return; 150 return;
147 this.guest.setSize({normal: {width: newWidth, height: newHeight}}); 151 this.guest.setSize({normal: {width: newWidth, height: newHeight}});
148 }; 152 };
149 153
150 GuestViewContainer.prototype.buildParams = function() { 154 GuestViewContainer.prototype.buildParams = function() {
(...skipping 29 matching lines...) Expand all
180 }; 184 };
181 185
182 // Implemented by the specific view type, if needed. 186 // Implemented by the specific view type, if needed.
183 GuestViewContainer.prototype.buildContainerParams = function() { return {}; }; 187 GuestViewContainer.prototype.buildContainerParams = function() { return {}; };
184 GuestViewContainer.prototype.onElementAttached = function() {}; 188 GuestViewContainer.prototype.onElementAttached = function() {};
185 GuestViewContainer.prototype.onElementDetached = function() {}; 189 GuestViewContainer.prototype.onElementDetached = function() {};
186 GuestViewContainer.prototype.setupAttributes = function() {}; 190 GuestViewContainer.prototype.setupAttributes = function() {};
187 191
188 // Registers the browser plugin <object> custom element. |viewType| is the 192 // Registers the browser plugin <object> custom element. |viewType| is the
189 // name of the specific guestview container (e.g. 'webview'). 193 // name of the specific guestview container (e.g. 'webview').
190 function registerBrowserPluginElement(viewType) { 194 function registerInternalElement(viewType) {
191 var proto = $Object.create(HTMLElement.prototype); 195 var proto = $Object.create(HTMLElement.prototype);
192 196
193 proto.createdCallback = function() { 197 proto.createdCallback = function() {
194 this.setAttribute('type', 'application/browser-plugin'); 198 this.setAttribute('type', 'application/browser-plugin');
195 this.setAttribute('id', 'browser-plugin-' + IdGenerator.GetNextId()); 199 this.setAttribute('id', 'browser-plugin-' + IdGenerator.GetNextId());
196 this.style.width = '100%'; 200 this.style.width = '100%';
197 this.style.height = '100%'; 201 this.style.height = '100%';
198 }; 202 };
199 203
200 proto.attachedCallback = function() { 204 proto.attachedCallback = function() {
201 // Load the plugin immediately. 205 // Load the plugin immediately.
202 var unused = this.nonExistentAttribute; 206 var unused = this.nonExistentAttribute;
203 }; 207 };
204 208
205 proto.attributeChangedCallback = function(name, oldValue, newValue) { 209 proto.attributeChangedCallback = function(name, oldValue, newValue) {
206 var internal = privates(this).internal; 210 var internal = privates(this).internal;
207 if (!internal) { 211 if (!internal) {
208 return; 212 return;
209 } 213 }
210 internal.handleBrowserPluginAttributeMutation(name, oldValue, newValue); 214 internal.handleInternalElementAttributeMutation(name, oldValue, newValue);
211 }; 215 };
212 216
213 GuestViewContainer[viewType + 'BrowserPlugin'] = 217 GuestViewContainer[viewType + 'BrowserPlugin'] =
214 DocumentNatives.RegisterElement(viewType + 'browserplugin', 218 DocumentNatives.RegisterElement(viewType + 'browserplugin',
215 {extends: 'object', prototype: proto}); 219 {extends: 'object', prototype: proto});
216 220
217 delete proto.createdCallback; 221 delete proto.createdCallback;
218 delete proto.attachedCallback; 222 delete proto.attachedCallback;
219 delete proto.detachedCallback; 223 delete proto.detachedCallback;
220 delete proto.attributeChangedCallback; 224 delete proto.attributeChangedCallback;
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 // Delete the callbacks so developers cannot call them and produce unexpected 278 // Delete the callbacks so developers cannot call them and produce unexpected
275 // behavior. 279 // behavior.
276 delete proto.createdCallback; 280 delete proto.createdCallback;
277 delete proto.attachedCallback; 281 delete proto.attachedCallback;
278 delete proto.detachedCallback; 282 delete proto.detachedCallback;
279 delete proto.attributeChangedCallback; 283 delete proto.attributeChangedCallback;
280 } 284 }
281 285
282 // Exports. 286 // Exports.
283 exports.GuestViewContainer = GuestViewContainer; 287 exports.GuestViewContainer = GuestViewContainer;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698