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

Side by Side Diff: chrome/browser/resources/extensions/update_node.js

Issue 893453002: Stop rebuilding all elements in chrome://extensions to preserve focus on refresh (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: DO NOT COMMIT - Applied feedback Created 5 years, 10 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 // TODO(hcarmona): Remove this temporary file.
2
3 /**
4 * Updates an HTML element for the extension metadata given in |extension|.
5 * @param {ExtensionData} extension A dictionary of extension metadata.
6 * @param {Element} node The node that is being updated.
7 * @private
8 */
9 updateNode_: function(extension, node) {
10 node.classList.toggle('inactive-extension',
11 !extension.enabled || extension.terminated);
12
13 var toRemove = ['policy-controlled', 'may-not-modify', 'may-not-remove'];
14 node.classList.remove.apply(node.classList, toRemove);
15 var classes = [];
16 if (extension.managedInstall) {
17 classes.push('policy-controlled', 'may-not-modify');
18 } else if (extension.dependentExtensions.length > 0) {
19 classes.push('may-not-remove', 'may-not-modify');
20 } else if (extension.recommendedInstall) {
21 classes.push('may-not-remove');
22 } else if (extension.suspiciousInstall ||
23 extension.corruptInstall ||
24 extension.updateRequiredByPolicy) {
25 classes.push('may-not-modify');
26 }
27 node.classList.add.apply(node.classList, classes);
28
29 node.classList.toggle('extension-highlight',
30 node.id == this.getIdQueryParam_());
31
32 var item = node.querySelector('.extension-list-item');
33 // Prevent the image cache of extension icon by using the reloaded
34 // timestamp as a query string. The timestamp is recorded when the user
35 // clicks the 'Reload' link. http://crbug.com/159302.
36 if (extensionReloadedTimestamp[extension.id]) {
37 item.style.backgroundImage =
38 'url(' + extension.icon + '?' +
39 extensionReloadedTimestamp[extension.id] + ')';
40 } else {
41 item.style.backgroundImage = 'url(' + extension.icon + ')';
42 }
43
44 var title = node.querySelector('.extension-title');
45 title.textContent = extension.name;
46
47 var version = node.querySelector('.extension-version');
48 version.textContent = extension.version;
49
50 var locationText = node.querySelector('.location-text');
51 locationText.textContent = extension.locationText;
52
53 var blacklistText = node.querySelector('.blacklist-text');
54 blacklistText.textContent = extension.blacklistText;
55
56 var description = document.createElement('span');
57 description.textContent = extension.description;
58 var descriptionHolder = node.querySelector('.extension-description');
59 descriptionHolder.textContent = '';
60 descriptionHolder.appendChild(description);
not at google - send to devlin 2015/02/05 22:25:03 Any reason why this isn't all just "descriptionHol
hcarmona 2015/02/05 23:27:14 This was done to avoid changing the structure of t
61
62 // The 'Show Browser Action' button.
63 var showButton = node.querySelector('.show-button');
not at google - send to devlin 2015/02/05 22:25:03 General function-level comment, which applies to c
hcarmona 2015/02/05 23:27:14 Awesome, I'll create an update function.
64 showButton.hidden = !extension.enable_show_button;
65
66 // The 'allow in incognito' checkbox.
67 node.querySelector('.incognito-control').hidden =
68 !this.data_.incognitoAvailable;
69 var incognito = node.querySelector('.incognito-control input');
70 incognito.disabled = !extension.incognitoCanBeEnabled;
71 incognito.checked = extension.enabledIncognito;
72 var butterBar = node.querySelector('.butter-bar');
73 butterBar.hidden = !butterBarVisibility[extension.id];
74
75 // The 'collect errors' checkbox. This should only be visible if the
76 // error console is enabled - we can detect this by the existence of the
77 // |errorCollectionEnabled| property.
78 node.querySelector('.error-collection-control').hidden =
79 !extension.wantsErrorCollection;
80 var errorCollection =
81 node.querySelector('.error-collection-control input');
82 errorCollection.checked = extension.wantsErrorCollection &&
83 extension.errorCollectionEnabled;
84
85 // The 'allow on all urls' checkbox. This should only be visible if
86 // active script restrictions are enabled. If they are not enabled, no
87 // extensions should want all urls.
88 var allUrls = node.querySelector('.all-urls-control');
89 allUrls.querySelector('input').checked = extension.wantsAllUrls &&
90 extension.allowAllUrls;
91 allUrls.hidden = !extension.wantsAllUrls;
92
93 // The 'allow file:// access' checkbox.
94 var fileAccess = node.querySelector('.file-access-control');
95 fileAccess.querySelector('input').checked = extension.wantsFileAccess &&
96 extension.allowFileAccess;
97 fileAccess.hidden = !extension.wantsFileAccess;
98
99 // The 'Options' button or link, depending on its behaviour.
100 var optionsEnabled = extension.enabled && extension.optionsUrl;
101
102 var optionsLink = node.querySelector('.options-link');
103 var optionsLinkEnabled = optionsEnabled && extension.optionsOpenInTab;
104 optionsLink.hidden = !optionsLinkEnabled;
105
106 var optionsButton = options = node.querySelector('.options-button');
107 var optionsButtonEnabled = optionsEnabled && !extension.optionsOpenInTab;
108 optionsButton.hidden = !optionsButtonEnabled;
109
110 // The 'View in Web Store/View Web Site' link.
111 var siteLinkEnabled = extension.homepageUrl &&
112 !extension.enableExtensionInfoDialog;
113 var siteLink = node.querySelector('.site-link');
114 siteLink.href = extension.homepageUrl;
115 siteLink.textContent = loadTimeData.getString(
116 extension.homepageProvided ? 'extensionSettingsVisitWebsite' :
117 'extensionSettingsVisitWebStore');
118 siteLink.hidden = !siteLinkEnabled;
119
120 // The 'Reload' link.
121 var reload = node.querySelector('.reload-link');
122 reload.hidden = !extension.allow_reload;
123
124 var canLaunch = extension.allow_reload && extension.is_platform_app;
125 // The 'Launch' link.
126 var launch = node.querySelector('.launch-link');
127 launch.hidden = !canLaunch;
128
129 // The 'Reload' terminated link.
130 var isTerminated = extension.terminated;
131 var terminatedReload = node.querySelector('.terminated-reload-link');
132 terminatedReload.hidden = !isTerminated;
133
134 // The 'Repair' corrupted link.
135 var canRepair = !isTerminated && extension.corruptInstall &&
136 extension.isFromStore;
137 var repair = node.querySelector('.corrupted-repair-button');
138 repair.hidden = !canRepair;
139
140 // The 'Enabled' checkbox.
141 var isOK = !isTerminated && !canRepair;
142 var enable = node.querySelector('.enable-checkbox');
143 enable.hidden = !isOK;
144 var enableCheckboxDisabled = extension.managedInstall ||
145 extension.suspiciousInstall ||
146 extension.corruptInstall ||
147 extension.updateRequiredByPolicy ||
148 extension.dependentExtensions.length > 0;
149 enable.querySelector('input').disabled = enableCheckboxDisabled;
150
151 enable.querySelector('input').checked = isOK && extension.enabled;
152
153 // Button for extensions controlled by policy.
154 var controlNode = node.querySelector('.enable-controls');
155 if (extension.managedInstall &&
156 !controlNode.querySelector('.controlled-extension-indicator')) {
157 var indicator = new cr.ui.ControlledIndicator();
158 indicator.classList.add('controlled-extension-indicator');
159 indicator.setAttribute('controlled-by', 'policy');
160 indicator.setAttribute('textpolicy', extension.policyText || '');
161 controlNode.appendChild(indicator);
162 } else if (!extension.managedInstall) {
163 var indicator = controlNode.querySelector(
164 '.controlled-extension-indicator');
165 if (indicator)
166 controlNode.removeChild(indicator);
167 }
168
169 // Developer mode ////////////////////////////////////////////////////////
170
171 // First we have the id.
172 var idLabel = node.querySelector('.extension-id');
173 idLabel.textContent = ' ' + extension.id;
174
175 // Then the path, if provided by unpacked extension.
176 var loadPath = node.querySelector('.load-path');
177 loadPath.hidden = !extension.isUnpacked;
178 var pathLink = loadPath.querySelector('a:nth-of-type(1)');
179 pathLink.textContent = ' ' + extension.prettifiedPath;
180
181 // Then the 'managed, cannot uninstall/disable' message.
182 var isRequired = extension.managedInstall || extension.recommendedInstall;
183 node.querySelector('.managed-message').hidden = !isRequired;
184
185 // Then the 'This isn't from the webstore, looks suspicious' message.
186 var isSuspicious = !isRequired && extension.suspiciousInstall;
187 node.querySelector('.suspicious-install-message').hidden = !isSuspicious;
188
189 // Then the 'This is a corrupt extension' message.
190 var isCorrupt = !isRequired && extension.corruptInstall;
191 node.querySelector('.corrupt-install-message').hidden = !isCorrupt;
192
193 // Then the 'An update required by enterprise policy' message. Note that
194 // a force-installed extension might be disabled due to being outdated
195 // as well.
196 node.querySelector('.update-required-message').hidden =
197 !extension.updateRequiredByPolicy;
198 // We would like to hide managed installed message since this
199 // extension is disabled.
200 node.querySelector('.managed-message').hidden =
201 extension.updateRequiredByPolicy;
202
203 // The 'following extensions depend on this extension' list.
204 var hasDependents = extension.dependentExtensions.length > 0;
205 node.classList.toggle('developer-extras', hasDependents);
206 var dependentMessage =
207 node.querySelector('.dependent-extensions-message');
208 dependentMessage.hidden = !hasDependents;
209 var dependentList = dependentMessage.querySelector('ul');
210 dependentList.textContent = '';
211 var dependentTemplate = $('template-collection').querySelector(
212 '.dependent-list-item');
213 extension.dependentExtensions.forEach(function(elem) {
214 var depNode = dependentTemplate.cloneNode(true);
215 depNode.querySelector('.dep-extension-title').textContent = elem.name;
216 depNode.querySelector('.dep-extension-id').textContent = elem.id;
217 dependentList.appendChild(depNode);
218 });
219
220 // The active views.
221 var hasActiveViews = extension.views.length > 0;
222 var activeViews = node.querySelector('.active-views');
223 activeViews.hidden = !hasActiveViews;
224
225 var link = activeViews.querySelector('a');
226
227 // Link needs to be an only child before the list is updated.
228 while (link.nextElementSibling)
229 activeViews.removeChild(link.nextElementSibling);
230
231 // Link needs to be cleaned up if it was used before.
232 link.textContent = '';
233 if (link.clickHandler)
234 link.removeEventListener('click', link.clickHandler);
235
236 if (hasActiveViews) {
237 extension.views.forEach(function(view, i) {
238 var displayName = view.generatedBackgroundPage ?
239 loadTimeData.getString('backgroundPage') : view.path;
240 var label = displayName +
241 (view.incognito ?
242 ' ' + loadTimeData.getString('viewIncognito') : '') +
243 (view.renderProcessId == -1 ?
244 ' ' + loadTimeData.getString('viewInactive') : '');
245 link.textContent = label;
246 link.clickHandler = function(e) {
247 // TODO(estade): remove conversion to string?
248 chrome.send('extensionSettingsInspect', [
249 String(extension.id),
250 String(view.renderProcessId),
251 String(view.renderViewId),
252 view.incognito
253 ]);
254 };
255 link.addEventListener('click', link.clickHandler);
256
257 if (i < extension.views.length - 1) {
258 link = link.cloneNode(true);
259 activeViews.appendChild(link);
260 }
261 });
262 }
263
264 // The extension warnings (describing runtime issues).
265 var warningPanel = node.querySelector('.extension-warnings');
266 warningPanel.hidden = !extension.warnings;
267 var warningList = warningPanel.querySelector('ul');
268 warningList.textContent = '';
269 if (extension.warnings) {
270 extension.warnings.forEach(function(warning) {
271 warningList.appendChild(document.createElement('li')).innerText =
272 warning;
273 });
274 }
275
276 // If the ErrorConsole is enabled, we should have manifest and/or runtime
277 // errors. Otherwise, we may have install warnings. We should not have
278 // both ErrorConsole errors and install warnings.
279 // Errors.
280 this.updateErrors_(node.querySelector('.manifest-errors'),
281 extension.manifestErrors);
282 this.updateErrors_(node.querySelector('.runtime-errors'),
283 extension.runtimeErrors);
284
285 // Install warnings.
286 var installWarningPanel = node.querySelector('.install-warnings');
287 installWarningPanel.hidden = !extension.installWarnings;
288 var installWarningList = installWarningPanel.querySelector('ul');
289 installWarningList.textContent = '';
290 if (extension.installWarnings) {
291 extension.installWarnings.forEach(function(warning) {
292 var li = document.createElement('li');
293 li.innerText = warning.message;
294 installWarningList.appendChild(li);
295 });
296 }
297
298 if (location.hash.substr(1) == extension.id) {
299 // Scroll beneath the fixed header so that the extension is not
300 // obscured.
301 var topScroll = node.offsetTop - $('page-header').offsetHeight;
302 var pad = parseInt(window.getComputedStyle(node, null).marginTop, 10);
303 if (!isNaN(pad))
304 topScroll -= pad / 2;
305 setScrollTopForDocument(document, topScroll);
306 }
307 },
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698