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