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

Side by Side Diff: chrome/renderer/resources/extensions/app_view.js

Issue 618823002: GuestView: Move lifetime management out of content (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Added comment Created 6 years, 2 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 var DocumentNatives = requireNative('document_natives'); 5 var DocumentNatives = requireNative('document_natives');
6 var GuestViewInternal = 6 var GuestViewInternal =
7 require('binding').Binding.create('guestViewInternal').generate(); 7 require('binding').Binding.create('guestViewInternal').generate();
8 var IdGenerator = requireNative('id_generator'); 8 var IdGenerator = requireNative('id_generator');
9 var guestViewInternalNatives = requireNative('guest_view_internal'); 9 var guestViewInternalNatives = requireNative('guest_view_internal');
10 10
11 function AppViewInternal(appviewNode) { 11 function AppViewInternal(appviewNode) {
12 privates(appviewNode).internal = this; 12 privates(appviewNode).internal = this;
13 this.appviewNode = appviewNode; 13 this.appviewNode = appviewNode;
14 this.elementAttached = false;
15 this.pendingGuestCreation = false;
14 16
15 this.browserPluginNode = this.createBrowserPluginNode(); 17 this.browserPluginNode = this.createBrowserPluginNode();
16 var shadowRoot = this.appviewNode.createShadowRoot(); 18 var shadowRoot = this.appviewNode.createShadowRoot();
17 shadowRoot.appendChild(this.browserPluginNode); 19 shadowRoot.appendChild(this.browserPluginNode);
18 this.viewInstanceId = IdGenerator.GetNextId(); 20 this.viewInstanceId = IdGenerator.GetNextId();
19 } 21 }
20 22
21 AppViewInternal.prototype.getErrorNode = function() { 23 AppViewInternal.prototype.getErrorNode = function() {
22 if (!this.errorNode) { 24 if (!this.errorNode) {
23 this.errorNode = document.createElement('div'); 25 this.errorNode = document.createElement('div');
(...skipping 10 matching lines...) Expand all
34 36
35 AppViewInternal.prototype.createBrowserPluginNode = function() { 37 AppViewInternal.prototype.createBrowserPluginNode = function() {
36 // We create BrowserPlugin as a custom element in order to observe changes 38 // We create BrowserPlugin as a custom element in order to observe changes
37 // to attributes synchronously. 39 // to attributes synchronously.
38 var browserPluginNode = new AppViewInternal.BrowserPlugin(); 40 var browserPluginNode = new AppViewInternal.BrowserPlugin();
39 privates(browserPluginNode).internal = this; 41 privates(browserPluginNode).internal = this;
40 return browserPluginNode; 42 return browserPluginNode;
41 }; 43 };
42 44
43 AppViewInternal.prototype.connect = function(app, data, callback) { 45 AppViewInternal.prototype.connect = function(app, data, callback) {
46 if (!this.elementAttached || this.pendingGuestCreation) {
47 if (callback) {
48 callback(false);
49 }
50 return;
51 }
44 var createParams = { 52 var createParams = {
45 'appId': app, 53 'appId': app,
46 'data': data || {} 54 'data': data || {}
47 }; 55 };
48 var self = this;
49 GuestViewInternal.createGuest( 56 GuestViewInternal.createGuest(
50 'appview', 57 'appview',
51 createParams, 58 createParams,
52 function(guestInstanceId) { 59 function(guestInstanceId) {
60 this.pendingGuestCreation = false;
61 if (guestInstanceId && !this.elementAttached) {
62 GuestViewInternal.destroyGuest(guestInstanceId);
63 guestInstanceId = 0;
64 }
53 if (!guestInstanceId) { 65 if (!guestInstanceId) {
54 this.browserPluginNode.style.visibility = 'hidden'; 66 this.browserPluginNode.style.visibility = 'hidden';
55 var errorMsg = 'Unable to connect to app "' + app + '".'; 67 var errorMsg = 'Unable to connect to app "' + app + '".';
56 window.console.warn(errorMsg); 68 window.console.warn(errorMsg);
57 this.getErrorNode().innerText = errorMsg; 69 this.getErrorNode().innerText = errorMsg;
58 if (callback) { 70 if (callback) {
59 callback(false); 71 callback(false);
60 } 72 }
61 return; 73 return;
62 } 74 }
63 this.attachWindow(guestInstanceId); 75 this.attachWindow(guestInstanceId);
64 if (callback) { 76 if (callback) {
65 callback(true); 77 callback(true);
66 } 78 }
67 }.bind(this) 79 }.bind(this)
68 ); 80 );
81 this.pendingGuestCreation = true;
69 }; 82 };
70 83
71 AppViewInternal.prototype.attachWindow = function(guestInstanceId) { 84 AppViewInternal.prototype.attachWindow = function(guestInstanceId) {
72 this.guestInstanceId = guestInstanceId; 85 this.guestInstanceId = guestInstanceId;
86 if (!this.internalInstanceId) {
87 return;
88 }
73 var params = { 89 var params = {
74 'instanceId': this.viewInstanceId, 90 'instanceId': this.viewInstanceId
75 }; 91 };
76 this.browserPluginNode.style.visibility = 'visible'; 92 this.browserPluginNode.style.visibility = 'visible';
77 return guestViewInternalNatives.AttachGuest( 93 return guestViewInternalNatives.AttachGuest(
78 parseInt(this.browserPluginNode.getAttribute('internalinstanceid')), 94 this.internalInstanceId,
79 guestInstanceId, 95 guestInstanceId,
80 params); 96 params);
81 }; 97 };
82 98
99 AppViewInternal.prototype.handleBrowserPluginAttributeMutation =
100 function(name, oldValue, newValue) {
101 if (name == 'internalinstanceid' && !oldValue && !!newValue) {
102 this.browserPluginNode.removeAttribute('internalinstanceid');
103 this.internalInstanceId = parseInt(newValue);
104
105 if (!!this.guestInstanceId && this.guestInstanceId != 0) {
106 var params = {
107 'instanceId': this.viewInstanceId
108 };
109 guestViewInternalNatives.AttachGuest(
110 this.internalInstanceId,
111 this.guestInstanceId,
112 params);
113 }
114 return;
115 }
116 };
117
118 AppViewInternal.prototype.reset = function() {
119 if (this.guestInstanceId) {
120 GuestViewInternal.destroyGuest(this.guestInstanceId);
121 this.guestInstanceId = undefined;
122 }
123 };
124
83 function registerBrowserPluginElement() { 125 function registerBrowserPluginElement() {
84 var proto = Object.create(HTMLObjectElement.prototype); 126 var proto = Object.create(HTMLObjectElement.prototype);
85 127
86 proto.createdCallback = function() { 128 proto.createdCallback = function() {
87 this.setAttribute('type', 'application/browser-plugin'); 129 this.setAttribute('type', 'application/browser-plugin');
88 this.style.width = '100%'; 130 this.style.width = '100%';
89 this.style.height = '100%'; 131 this.style.height = '100%';
90 }; 132 };
91 133
92 proto.attachedCallback = function() { 134 proto.attachedCallback = function() {
93 // Load the plugin immediately. 135 // Load the plugin immediately.
94 var unused = this.nonExistentAttribute; 136 var unused = this.nonExistentAttribute;
95 }; 137 };
96 138
139 proto.attributeChangedCallback = function(name, oldValue, newValue) {
140 var internal = privates(this).internal;
141 if (!internal) {
142 return;
143 }
144 internal.handleBrowserPluginAttributeMutation(name, oldValue, newValue);
145 };
146
97 AppViewInternal.BrowserPlugin = 147 AppViewInternal.BrowserPlugin =
98 DocumentNatives.RegisterElement('appplugin', {extends: 'object', 148 DocumentNatives.RegisterElement('appplugin', {extends: 'object',
99 prototype: proto}); 149 prototype: proto});
100 150
101 delete proto.createdCallback; 151 delete proto.createdCallback;
102 delete proto.attachedCallback; 152 delete proto.attachedCallback;
103 delete proto.detachedCallback; 153 delete proto.detachedCallback;
104 delete proto.attributeChangedCallback; 154 delete proto.attributeChangedCallback;
105 } 155 }
106 156
107 function registerAppViewElement() { 157 function registerAppViewElement() {
108 var proto = Object.create(HTMLElement.prototype); 158 var proto = Object.create(HTMLElement.prototype);
109 159
110 proto.createdCallback = function() { 160 proto.createdCallback = function() {
111 new AppViewInternal(this); 161 new AppViewInternal(this);
112 }; 162 };
113 163
164 proto.attachedCallback = function() {
165 var internal = privates(this).internal;
166 if (!internal) {
167 return;
168 }
169 internal.elementAttached = true;
170 };
171
172 proto.detachedCallback = function() {
173 var internal = privates(this).internal;
174 if (!internal) {
175 return;
176 }
177 internal.elementAttached = false;
178 internal.reset();
179 };
180
114 proto.connect = function() { 181 proto.connect = function() {
115 var internal = privates(this).internal; 182 var internal = privates(this).internal;
116 $Function.apply(internal.connect, internal, arguments); 183 $Function.apply(internal.connect, internal, arguments);
117 } 184 }
185
118 window.AppView = 186 window.AppView =
119 DocumentNatives.RegisterElement('appview', {prototype: proto}); 187 DocumentNatives.RegisterElement('appview', {prototype: proto});
120 188
121 // Delete the callbacks so developers cannot call them and produce unexpected 189 // Delete the callbacks so developers cannot call them and produce unexpected
122 // behavior. 190 // behavior.
123 delete proto.createdCallback; 191 delete proto.createdCallback;
124 delete proto.attachedCallback; 192 delete proto.attachedCallback;
125 delete proto.detachedCallback; 193 delete proto.detachedCallback;
126 delete proto.attributeChangedCallback; 194 delete proto.attributeChangedCallback;
127 } 195 }
128 196
129 var useCapture = true; 197 var useCapture = true;
130 window.addEventListener('readystatechange', function listener(event) { 198 window.addEventListener('readystatechange', function listener(event) {
131 if (document.readyState == 'loading') 199 if (document.readyState == 'loading')
132 return; 200 return;
133 201
134 registerBrowserPluginElement(); 202 registerBrowserPluginElement();
135 registerAppViewElement(); 203 registerAppViewElement();
136 window.removeEventListener(event.type, listener, useCapture); 204 window.removeEventListener(event.type, listener, useCapture);
137 }, useCapture); 205 }, useCapture);
OLDNEW
« no previous file with comments | « chrome/browser/apps/web_view_browsertest.cc ('k') | chrome/renderer/resources/extensions/extension_options.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698