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

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

Issue 378783002: Initial implementation of the <extensionoptions> GuestView tag (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Handle changing attribute values, prevent cross-extension options embedding Created 6 years, 5 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
(Empty)
1 // Copyright (c) 2014 The Chromium Authors. All rights reserved.
Devlin 2014/07/15 18:07:35 no (c)
ericzeng 2014/07/15 20:23:55 Done.
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()) {
15 this.browserPluginNode = this.createBrowserPluginNode();
16 var shadowRoot = this.extensionoptionsNode.createShadowRoot();
17 shadowRoot.appendChild(this.browserPluginNode);
18 this.viewInstanceId = IdGenerator.GetNextId();
19 this.createGuest();
20 }
21 };
22
23 ExtensionOptionsInternal.prototype.attachWindow = function(instanceId) {
24 this.instanceId = instanceId;
25 var params = {
26 'instanceId': this.viewInstanceId,
27 }
28 return this.browserPluginNode['-internal-attach'](instanceId, params);
29 };
30
31 ExtensionOptionsInternal.prototype.createBrowserPluginNode = function() {
32 var browserPluginNode = new ExtensionOptionsInternal.BrowserPlugin();
33 privates(browserPluginNode).internal = this;
34 return browserPluginNode;
35 };
36
37 ExtensionOptionsInternal.prototype.createGuest = function() {
38 var params = {
39 'extensionId': this.extensionId,
40 };
41 var self = this;
42 GuestViewInternal.createGuest(
43 'extensionoptions',
44 params,
45 function(instanceId) {
46 self.instanceId = instanceId;
47 self.attachWindow(instanceId);
48 });
Devlin 2014/07/15 18:07:35 I find it cleaner to do .bind(this) and use |this|
ericzeng 2014/07/16 01:52:01 Won't change for consistency with webview and appv
49 };
50
51 ExtensionOptionsInternal.prototype.handleExtensionOptionsAttributeMutation =
52 function(name, oldValue, newValue) {
53 if (name == 'extension') {
Devlin 2014/07/15 18:07:36 hmm... how about: if (name != 'extension) return
ericzeng 2014/07/15 20:23:55 Done.
54 // We treat null attribute (attribute removed) and the empty string as
55 // one case.
56 oldValue = oldValue || '';
57 newValue = newValue || '';
58
59 if (oldValue === newValue) {
Devlin 2014/07/15 18:07:36 nit: no brackets around single-line ifs.
ericzeng 2014/07/15 20:23:55 Done.
60 return;
61 }
62 this.extensionId = newValue;
63
64 // Create new guest view if one hasn't been created for this element
65 if (!this.instanceId) {
Devlin 2014/07/15 18:07:36 why separate ifs? if (!this.instanceId && this.par
ericzeng 2014/07/15 20:23:55 Done.
66 if (this.parseExtensionAttribute()) {
67 this.browserPluginNode = this.createBrowserPluginNode();
Devlin 2014/07/15 18:07:36 factor so this and line 14-20 share code.
ericzeng 2014/07/15 20:23:55 Done.
68 var shadowRoot = this.extensionoptionsNode.createShadowRoot();
69 shadowRoot.appendChild(this.browserPluginNode);
70 this.viewInstanceId = IdGenerator.GetNextId();
71 this.createGuest();
72 }
73 }
74 // TODO(ericzeng): Implement navigation to another guest view if we want
75 // that functionality
Devlin 2014/07/15 18:07:36 nit: add a period.
ericzeng 2014/07/15 20:23:55 Done.
76 }
77 };
78
79 ExtensionOptionsInternal.prototype.parseExtensionAttribute = function() {
80 if (this.extensionoptionsNode.hasAttribute('extension')) {
81 var extensionId = this.extensionoptionsNode.getAttribute('extension');
82 // Only allow extensions to embed their own options page
Devlin 2014/07/15 18:07:36 nit: add a period.
ericzeng 2014/07/15 20:23:55 Done.
83 if (chrome.runtime.id == extensionId) {
84 this.extensionId = extensionId;
85 return true;
86 }
87 }
88 return false;
89 };
90
91 function registerBrowserPluginElement() {
92 var proto = Object.create(HTMLObjectElement.prototype);
93
94 proto.createdCallback = function() {
95 this.setAttribute('type', 'application/browser-plugin');
96 this.style.width = '100%';
97 this.style.height = '100%';
98 };
99
100 proto.attachedCallback = function() {
101 // Load the plugin immediately.
102 var unused = this.nonExistentAttribute;
103 };
104
105 ExtensionOptionsInternal.BrowserPlugin =
106 DocumentNatives.RegisterElement("extensionoptionsplugin",
107 {extends: 'object', prototype: proto});
108 delete proto.createdCallback;
109 delete proto.attachedCallback;
110 delete proto.detachedCallback;
111 delete proto.attributeChangedCallback;
112 }
113
114 function registerExtensionOptionsElement() {
115 var proto = Object.create(HTMLElement.prototype);
116
117 proto.createdCallback = function() {
118 new ExtensionOptionsInternal(this);
119 };
120
121 proto.attributeChangedCallback = function(name, oldValue, newValue) {
122 var internal = privates(this).internal;
123 if (!internal) {
Devlin 2014/07/15 18:07:36 nit: no brackets.
ericzeng 2014/07/15 20:23:55 Done.
124 return;
125 }
126 internal.handleExtensionOptionsAttributeMutation(name, oldValue, newValue);
127 };
128
129 window.ExtensionOptions =
130 DocumentNatives.RegisterElement('extensionoptions', {prototype: proto});
131
132 // Delete the callbacks so developers cannot call them and produce unexpected
Devlin 2014/07/15 18:07:36 duplicate comment on 108.
ericzeng 2014/07/16 01:52:01 Done.
133 // behavior.
134 delete proto.createdCallback;
135 delete proto.attachedCallback;
136 delete proto.detachedCallback;
137 delete proto.attributeChangedCallback;
138 }
139
140 var useCapture = true;
141 window.addEventListener('readystatechange', function listener(event) {
142 if (document.readyState == 'loading')
143 return;
144
145 registerBrowserPluginElement();
146 registerExtensionOptionsElement();
147 window.removeEventListener(event.type, listener, useCapture);
148 }, useCapture);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698