OLD | NEW |
---|---|
(Empty) | |
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. | |
4 | |
5 var DocumentNatives = requireNative('document_natives'); | |
6 var GuestViewInternal = | |
7 require('binding').Binding.create('guestViewInternal').generate(); | |
8 var IdGenerator = requireNative('id_generator'); | |
9 | |
10 function ExtensionOptionsInternal(extensionoptionsNode) { | |
11 privates(extensionoptionsNode).internal = this; | |
12 this.extensionoptionsNode = extensionoptionsNode; | |
13 | |
14 if (this.parseExtensionAttribute()) { | |
Devlin
2014/07/16 20:55:07
no brackets.
ericzeng
2014/07/16 22:27:38
Done.
| |
15 this.init(); | |
16 } | |
17 }; | |
18 | |
19 ExtensionOptionsInternal.prototype.attachWindow = function(instanceId) { | |
20 this.instanceId = instanceId; | |
21 var params = { | |
22 'instanceId': this.viewInstanceId, | |
23 } | |
24 return this.browserPluginNode['-internal-attach'](instanceId, params); | |
25 }; | |
26 | |
27 ExtensionOptionsInternal.prototype.createBrowserPluginNode = function() { | |
28 var browserPluginNode = new ExtensionOptionsInternal.BrowserPlugin(); | |
29 privates(browserPluginNode).internal = this; | |
30 return browserPluginNode; | |
31 }; | |
32 | |
33 ExtensionOptionsInternal.prototype.createGuest = function() { | |
34 var params = { | |
35 'extensionId': this.extensionId, | |
36 }; | |
37 var self = this; | |
38 GuestViewInternal.createGuest( | |
39 'extensionoptions', | |
40 params, | |
41 function(instanceId) { | |
42 self.instanceId = instanceId; | |
43 self.attachWindow(instanceId); | |
44 }); | |
45 }; | |
46 | |
47 ExtensionOptionsInternal.prototype.handleExtensionOptionsAttributeMutation = | |
48 function(name, oldValue, newValue) { | |
49 if (name != 'extension') | |
50 return; | |
51 // We treat null attribute (attribute removed) and the empty string as | |
52 // one case. | |
53 oldValue = oldValue || ''; | |
54 newValue = newValue || ''; | |
55 | |
56 if (oldValue === newValue) | |
57 return; | |
58 this.extensionId = newValue; | |
59 | |
60 // Create new guest view if one hasn't been created for this element. | |
61 if (!this.instanceId && this.parseExtensionAttribute()) { | |
62 this.init(); | |
63 } | |
64 // TODO(ericzeng): Implement navigation to another guest view if we want | |
65 // that functionality. | |
66 }; | |
67 | |
68 ExtensionOptionsInternal.prototype.init = function() { | |
69 this.browserPluginNode = this.createBrowserPluginNode(); | |
70 var shadowRoot = this.extensionoptionsNode.createShadowRoot(); | |
71 shadowRoot.appendChild(this.browserPluginNode); | |
72 this.viewInstanceId = IdGenerator.GetNextId(); | |
73 this.createGuest(); | |
74 }; | |
75 | |
76 ExtensionOptionsInternal.prototype.parseExtensionAttribute = function() { | |
77 if (this.extensionoptionsNode.hasAttribute('extension')) { | |
78 var extensionId = this.extensionoptionsNode.getAttribute('extension'); | |
79 // Only allow extensions to embed their own options page. | |
80 if (chrome.runtime.id == extensionId) { | |
81 this.extensionId = extensionId; | |
82 return true; | |
83 } | |
84 } | |
85 return false; | |
86 }; | |
87 | |
88 function registerBrowserPluginElement() { | |
89 var proto = Object.create(HTMLObjectElement.prototype); | |
90 | |
91 proto.createdCallback = function() { | |
92 this.setAttribute('type', 'application/browser-plugin'); | |
93 this.style.width = '100%'; | |
94 this.style.height = '100%'; | |
95 }; | |
96 | |
97 proto.attachedCallback = function() { | |
98 // Load the plugin immediately. | |
99 var unused = this.nonExistentAttribute; | |
100 }; | |
101 | |
102 ExtensionOptionsInternal.BrowserPlugin = | |
103 DocumentNatives.RegisterElement('extensionoptionsplugin', | |
104 {extends: 'object', prototype: proto}); | |
105 delete proto.createdCallback; | |
106 delete proto.attachedCallback; | |
107 delete proto.detachedCallback; | |
108 delete proto.attributeChangedCallback; | |
109 } | |
110 | |
111 function registerExtensionOptionsElement() { | |
112 var proto = Object.create(HTMLElement.prototype); | |
113 | |
114 proto.createdCallback = function() { | |
115 new ExtensionOptionsInternal(this); | |
116 }; | |
117 | |
118 proto.attributeChangedCallback = function(name, oldValue, newValue) { | |
119 var internal = privates(this).internal; | |
120 if (!internal) | |
121 return; | |
122 internal.handleExtensionOptionsAttributeMutation(name, oldValue, newValue); | |
123 }; | |
124 | |
125 window.ExtensionOptions = | |
126 DocumentNatives.RegisterElement('extensionoptions', {prototype: proto}); | |
Devlin
2014/07/16 20:55:07
this indentation is off by one.
ericzeng
2014/07/16 22:27:38
Done.
| |
127 | |
128 // Delete the callbacks so developers cannot call them and produce unexpected | |
129 // behavior. | |
130 delete proto.createdCallback; | |
131 delete proto.attachedCallback; | |
132 delete proto.detachedCallback; | |
133 delete proto.attributeChangedCallback; | |
134 } | |
135 | |
136 var useCapture = true; | |
137 window.addEventListener('readystatechange', function listener(event) { | |
138 if (document.readyState == 'loading') | |
139 return; | |
140 | |
141 registerBrowserPluginElement(); | |
142 registerExtensionOptionsElement(); | |
143 window.removeEventListener(event.type, listener, useCapture); | |
144 }, useCapture); | |
OLD | NEW |