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 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 }, | |
| OLD | NEW |