| OLD | NEW |
| 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).browserPluginElement = this.createBrowserPluginElement(); |
| 26 this.guest.setBrowserPluginElement(privates(this).browserPluginElement); |
| 26 this.setupFocusPropagation(); | 27 this.setupFocusPropagation(); |
| 27 var shadowRoot = this.element.createShadowRoot(); | 28 var shadowRoot = this.element.createShadowRoot(); |
| 28 shadowRoot.appendChild(privates(this).browserPluginElement); | 29 shadowRoot.appendChild(privates(this).browserPluginElement); |
| 29 | 30 |
| 30 GuestViewInternalNatives.RegisterView(this.viewInstanceId, this); | 31 GuestViewInternalNatives.RegisterView(this.viewInstanceId, this); |
| 31 } | 32 } |
| 32 | 33 |
| 33 // Forward public API methods from |proto| to their internal implementations. | 34 // Forward public API methods from |proto| to their internal implementations. |
| 34 GuestViewContainer.forwardApiMethods = function(proto, apiMethods) { | 35 GuestViewContainer.forwardApiMethods = function(proto, apiMethods) { |
| 35 var createProtoHandler = function(m) { | 36 var createProtoHandler = function(m) { |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 86 | 87 |
| 87 GuestViewContainer.prototype.createBrowserPluginElement = function() { | 88 GuestViewContainer.prototype.createBrowserPluginElement = function() { |
| 88 // We create BrowserPlugin as a custom element in order to observe changes | 89 // We create BrowserPlugin as a custom element in order to observe changes |
| 89 // to attributes synchronously. | 90 // to attributes synchronously. |
| 90 var browserPluginElement = | 91 var browserPluginElement = |
| 91 new GuestViewContainer[this.viewType + 'BrowserPlugin'](); | 92 new GuestViewContainer[this.viewType + 'BrowserPlugin'](); |
| 92 privates(browserPluginElement).internal = this; | 93 privates(browserPluginElement).internal = this; |
| 93 return browserPluginElement; | 94 return browserPluginElement; |
| 94 }; | 95 }; |
| 95 | 96 |
| 97 GuestViewContainer.prototype.getBrowserPluginElement = function() { |
| 98 return privates(this).browserPluginElement; |
| 99 }; |
| 100 |
| 96 GuestViewContainer.prototype.setupFocusPropagation = function() { | 101 GuestViewContainer.prototype.setupFocusPropagation = function() { |
| 97 if (!this.element.hasAttribute('tabIndex')) { | 102 if (!this.element.hasAttribute('tabIndex')) { |
| 98 // GuestViewContainer needs a tabIndex in order to be focusable. | 103 // GuestViewContainer needs a tabIndex in order to be focusable. |
| 99 // TODO(fsamuel): It would be nice to avoid exposing a tabIndex attribute | 104 // TODO(fsamuel): It would be nice to avoid exposing a tabIndex attribute |
| 100 // to allow GuestViewContainer to be focusable. | 105 // to allow GuestViewContainer to be focusable. |
| 101 // See http://crbug.com/231664. | 106 // See http://crbug.com/231664. |
| 102 this.element.setAttribute('tabIndex', -1); | 107 this.element.setAttribute('tabIndex', -1); |
| 103 } | 108 } |
| 104 this.element.addEventListener('focus', this.weakWrapper(function(e) { | 109 this.element.addEventListener('focus', this.weakWrapper(function(e) { |
| 105 // Focus the BrowserPlugin when the GuestViewContainer takes focus. | 110 // Focus the BrowserPlugin when the GuestViewContainer takes focus. |
| 106 privates(this).browserPluginElement.focus(); | 111 privates(this).browserPluginElement.focus(); |
| 107 })); | 112 })); |
| 108 this.element.addEventListener('blur', this.weakWrapper(function(e) { | 113 this.element.addEventListener('blur', this.weakWrapper(function(e) { |
| 109 // Blur the BrowserPlugin when the GuestViewContainer loses focus. | 114 // Blur the BrowserPlugin when the GuestViewContainer loses focus. |
| 110 privates(this).browserPluginElement.blur(); | 115 privates(this).browserPluginElement.blur(); |
| 111 })); | 116 })); |
| 112 }; | 117 }; |
| 113 | 118 |
| 114 GuestViewContainer.prototype.attachWindow = function() { | 119 GuestViewContainer.prototype.attachWindow = function() { |
| 115 if (!this.internalInstanceId) { | 120 if (!this.internalInstanceId) { |
| 116 return true; | 121 return true; |
| 117 } | 122 } |
| 118 | 123 |
| 119 this.guest.attach(this.internalInstanceId, | 124 this.guest.attach(this.internalInstanceId, |
| 120 this.viewInstanceId, | 125 this.viewInstanceId, |
| 121 this.buildParams()); | 126 this.buildParams()); |
| 122 return true; | 127 return true; |
| 123 }; | 128 }; |
| 124 | 129 |
| 130 GuestViewContainer.prototype.onInternalInstanceID = function( |
| 131 internalInstanceId) { |
| 132 window.console.log('onInternalInstanceID: ' + internalInstanceId); |
| 133 this.internalInstanceId = internalInstanceId; |
| 134 |
| 135 // Track when the element resizes using the element resize callback. |
| 136 GuestViewInternalNatives.RegisterElementResizeCallback( |
| 137 this.internalInstanceId, this.onElementResize.bind(this)); |
| 138 |
| 139 window.console.log('this.guest.getId() = ' + |
| 140 this.guest.getId()); |
| 141 if (!this.guest.getId()) { |
| 142 return; |
| 143 } |
| 144 this.guest.attach(this.internalInstanceId, |
| 145 this.viewInstanceId, |
| 146 this.buildParams()); |
| 147 }; |
| 148 |
| 125 GuestViewContainer.prototype.handleBrowserPluginAttributeMutation = | 149 GuestViewContainer.prototype.handleBrowserPluginAttributeMutation = |
| 126 function(name, oldValue, newValue) { | 150 function(name, oldValue, newValue) { |
| 127 if (name == 'internalinstanceid' && !oldValue && !!newValue) { | 151 if (name == 'internalinstanceid' && !oldValue && !!newValue) { |
| 128 privates(this).browserPluginElement.removeAttribute('internalinstanceid'); | 152 privates(this).browserPluginElement.removeAttribute('internalinstanceid'); |
| 129 this.internalInstanceId = parseInt(newValue); | 153 this.onInternalInstanceID(parseInt(newValue)); |
| 130 | |
| 131 // Track when the element resizes using the element resize callback. | |
| 132 GuestViewInternalNatives.RegisterElementResizeCallback( | |
| 133 this.internalInstanceId, this.onElementResize.bind(this)); | |
| 134 | |
| 135 if (!this.guest.getId()) { | |
| 136 return; | |
| 137 } | |
| 138 this.guest.attach(this.internalInstanceId, | |
| 139 this.viewInstanceId, | |
| 140 this.buildParams()); | |
| 141 } | 154 } |
| 142 }; | 155 }; |
| 143 | 156 |
| 144 GuestViewContainer.prototype.onElementResize = function(newWidth, newHeight) { | 157 GuestViewContainer.prototype.onElementResize = function(newWidth, newHeight) { |
| 145 if (!this.guest.getId()) | 158 if (!this.guest.getId()) |
| 146 return; | 159 return; |
| 147 this.guest.setSize({normal: {width: newWidth, height: newHeight}}); | 160 this.guest.setSize({normal: {width: newWidth, height: newHeight}}); |
| 148 }; | 161 }; |
| 149 | 162 |
| 150 GuestViewContainer.prototype.buildParams = function() { | 163 GuestViewContainer.prototype.buildParams = function() { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 181 | 194 |
| 182 // Implemented by the specific view type, if needed. | 195 // Implemented by the specific view type, if needed. |
| 183 GuestViewContainer.prototype.buildContainerParams = function() { return {}; }; | 196 GuestViewContainer.prototype.buildContainerParams = function() { return {}; }; |
| 184 GuestViewContainer.prototype.onElementAttached = function() {}; | 197 GuestViewContainer.prototype.onElementAttached = function() {}; |
| 185 GuestViewContainer.prototype.onElementDetached = function() {}; | 198 GuestViewContainer.prototype.onElementDetached = function() {}; |
| 186 GuestViewContainer.prototype.setupAttributes = function() {}; | 199 GuestViewContainer.prototype.setupAttributes = function() {}; |
| 187 | 200 |
| 188 // Registers the browser plugin <object> custom element. |viewType| is the | 201 // Registers the browser plugin <object> custom element. |viewType| is the |
| 189 // name of the specific guestview container (e.g. 'webview'). | 202 // name of the specific guestview container (e.g. 'webview'). |
| 190 function registerBrowserPluginElement(viewType) { | 203 function registerBrowserPluginElement(viewType) { |
| 191 var proto = $Object.create(HTMLElement.prototype); | 204 var isSitePerProcess = GuestViewInternalNatives.IsSitePerProcess(); |
| 205 var proto = $Object.create(isSitePerProcess ? HTMLIFrameElement.prototype |
| 206 : HTMLElement.prototype); |
| 207 |
| 208 window.console.log('isSitePerProcess: ' + isSitePerProcess); |
| 192 | 209 |
| 193 proto.createdCallback = function() { | 210 proto.createdCallback = function() { |
| 194 this.setAttribute('type', 'application/browser-plugin'); | 211 if (!isSitePerProcess) { |
| 195 this.setAttribute('id', 'browser-plugin-' + IdGenerator.GetNextId()); | 212 this.setAttribute('type', 'application/browser-plugin'); |
| 213 this.setAttribute('id', 'browser-plugin-' + IdGenerator.GetNextId()); |
| 214 } |
| 196 this.style.width = '100%'; | 215 this.style.width = '100%'; |
| 197 this.style.height = '100%'; | 216 this.style.height = '100%'; |
| 198 }; | 217 }; |
| 199 | 218 |
| 200 proto.attachedCallback = function() { | 219 proto.attachedCallback = function() { |
| 201 // Load the plugin immediately. | 220 // Load the plugin immediately. |
| 202 var unused = this.nonExistentAttribute; | 221 var unused = this.nonExistentAttribute; |
| 203 }; | 222 }; |
| 204 | 223 |
| 205 proto.attributeChangedCallback = function(name, oldValue, newValue) { | 224 if (!isSitePerProcess) { |
| 206 var internal = privates(this).internal; | 225 proto.attributeChangedCallback = function(name, oldValue, newValue) { |
| 207 if (!internal) { | 226 var internal = privates(this).internal; |
| 208 return; | 227 if (!internal) { |
| 209 } | 228 return; |
| 210 internal.handleBrowserPluginAttributeMutation(name, oldValue, newValue); | 229 } |
| 211 }; | 230 internal.handleBrowserPluginAttributeMutation(name, oldValue, newValue); |
| 231 }; |
| 232 } |
| 212 | 233 |
| 234 var options = {prototype: proto}; |
| 235 options.extends = isSitePerProcess ? 'iframe' : 'object'; |
| 213 GuestViewContainer[viewType + 'BrowserPlugin'] = | 236 GuestViewContainer[viewType + 'BrowserPlugin'] = |
| 214 DocumentNatives.RegisterElement(viewType + 'browserplugin', | 237 DocumentNatives.RegisterElement(viewType + 'browserplugin', options); |
| 215 {extends: 'object', prototype: proto}); | |
| 216 | 238 |
| 217 delete proto.createdCallback; | 239 delete proto.createdCallback; |
| 218 delete proto.attachedCallback; | 240 delete proto.attachedCallback; |
| 219 delete proto.detachedCallback; | 241 delete proto.detachedCallback; |
| 220 delete proto.attributeChangedCallback; | 242 delete proto.attributeChangedCallback; |
| 221 }; | 243 }; |
| 222 | 244 |
| 223 // Registers the guestview container as a custom element. | 245 // Registers the guestview container as a custom element. |
| 224 // |guestViewContainerType| is the type of guestview container | 246 // |guestViewContainerType| is the type of guestview container |
| 225 // (e.g.WebViewImpl). | 247 // (e.g.WebViewImpl). |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 274 // Delete the callbacks so developers cannot call them and produce unexpected | 296 // Delete the callbacks so developers cannot call them and produce unexpected |
| 275 // behavior. | 297 // behavior. |
| 276 delete proto.createdCallback; | 298 delete proto.createdCallback; |
| 277 delete proto.attachedCallback; | 299 delete proto.attachedCallback; |
| 278 delete proto.detachedCallback; | 300 delete proto.detachedCallback; |
| 279 delete proto.attributeChangedCallback; | 301 delete proto.attributeChangedCallback; |
| 280 } | 302 } |
| 281 | 303 |
| 282 // Exports. | 304 // Exports. |
| 283 exports.GuestViewContainer = GuestViewContainer; | 305 exports.GuestViewContainer = GuestViewContainer; |
| OLD | NEW |