Index: chrome/browser/resources/extensions/extension_error.js |
diff --git a/chrome/browser/resources/extensions/extension_error.js b/chrome/browser/resources/extensions/extension_error.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..223645810eb60df5ea81205c64f703698a27d25e |
--- /dev/null |
+++ b/chrome/browser/resources/extensions/extension_error.js |
@@ -0,0 +1,188 @@ |
+// Copyright 2013 The Chromium Authors. All rights reserved. |
Yoyo Zhou
2013/08/16 00:17:26
P.S. You might want to find a qualified Javascript
Devlin
2013/08/16 18:07:49
Yep :) I'm gonna run c/b/r/e and c/b/ui/webui by
|
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+cr.define('extensions', function() { |
+ 'use strict'; |
+ |
+ /** |
+ * Returns whether or not a given |link| is associated with an extension. |
Yoyo Zhou
2013/08/16 00:17:26
Why use 'link' here when you are referring to URLs
Devlin
2013/08/16 18:07:49
My thinking was that things like "manifest.json" o
|
+ * @param {string} link The link to examine. |
+ * @param {string} extensionUrl The url of the extension. |
+ * @return {boolean} Whether or not the link is prefixed by the prefix. |
+ */ |
+ function isExtensionLink(link, extensionUrl) { |
+ return link.substring(0, extensionUrl.length) === extensionUrl; |
+ } |
+ |
+ /** |
+ * Get the link relative to the main extension url. If the link is |
+ * unassociated with the extension, this will be the full link. |
+ * @param {link} The link to make relative. |
+ * @param {extensionUrl} The host for which the link is relative. |
+ * @return {string} The link relative to the host. |
+ */ |
+ function getRelativeLink(link, extensionUrl) { |
Yoyo Zhou
2013/08/16 00:17:26
Same here - I would call this getRelativePath(url,
Devlin
2013/08/16 18:07:49
Done.
|
+ return isExtensionLink(link, extensionUrl) ? |
+ link.substring(extensionUrl.length) : link; |
+ } |
+ |
+ /** |
+ * Clone a template within the extension error template collection. |
+ * @param {string} templateName The class name of the template to clone. |
+ * @return {HTMLElement} The clone of the template. |
+ */ |
+ function cloneTemplate(templateName) { |
+ return $('template-collection-extension-error') |
+ .querySelector(templateName).cloneNode(true); |
+ } |
+ |
+ /** |
+ * Creates a new ExtensionError HTMLElement. |
+ * @param {Object} error The error the element should represent. |
+ * @return {HTMLElement} The created error element. |
+ */ |
+ function ExtensionError(error) { |
+ var div = document.createElement('div'); |
+ div.__proto__ = ExtensionError.prototype; |
+ div.className = 'extension-error-simple-wrapper'; |
+ div.error_ = error; |
+ div.decorate(); |
+ return div; |
+ } |
+ |
+ ExtensionError.prototype = { |
+ __proto__: HTMLDivElement.prototype, |
+ |
+ /** @override */ |
+ decorate: function() { |
+ var metadata = cloneTemplate('.extension-error-metadata'); |
+ |
+ // Set an icon for the level of severity... |
+ var iconNode = metadata.querySelector('img'); |
+ iconNode.className = |
+ this.error_.level == 0 ? 'extension-error-icon-log' : |
+ this.error_.level == 1 ? 'extension-error-icon-warn' : |
+ 'extension-error-icon-error'; |
+ |
+ // Add a property for the extension's base url in order to determine if |
+ // a link belongs to the extension. |
+ this.extensionUrl_ = |
+ 'chrome-extension://' + this.error_.extensionId + '/'; |
+ |
+ // The error message... |
+ metadata.querySelector('.extension-error-message').innerText = |
+ this.error_.message; |
+ |
+ // The error source... |
+ metadata.querySelector('.extension-error-source').innerText = |
+ '(' + getRelativeLink(this.error_.source, this.extensionUrl_) + ')'; |
+ |
+ this.appendChild(metadata); |
+ this.addViewLinkToNode_(this, this.error_.source); |
+ }, |
+ |
+ /** |
+ * Add a "view" link to the given node, if a user can view the source of the |
+ * specified link. |
+ * @param {HTMLElement} node The node to which we append the view link. |
+ * @param {string} link The link to the resource to view. |
+ */ |
+ addViewLinkToNode_: function(node, link) { |
+ if (this.canViewSource_(link)) |
+ node.appendChild(this.getViewSourceLink_(link)); |
+ }, |
+ |
+ /** |
+ * Determine whether we can view the source of a given link. |
+ * @param {string} link The link to the resource to view. |
+ * @return {boolean} Whether or not we can view the source for the link. |
+ */ |
+ canViewSource_: function(link) { |
+ return isExtensionLink(link, this.extensionUrl_) || |
+ link === 'manifest.json'; |
+ }, |
+ |
+ /** |
+ * Create a clickable node to view the source for the given link. |
+ * @param {string} link The link t othe resource to view. |
+ * @return {HTMLElement} The clickable node to view the source. |
+ */ |
+ getViewSourceLink_: function(link) { |
+ var node = document.createElement('a'); |
+ node.innerText = loadTimeData.getString('extensionErrorViewSource'); |
+ |
+ var relativeLink = getRelativeLink(link, this.extensionUrl_); |
+ node.addEventListener('click', function(e) { |
+ chrome.send('extensionErrorRequestFileSource', |
+ [{ |
+ 'extensionId': this.error_.extensionId, |
+ 'errorMessage': this.error_.message, |
+ 'fileType': 'manifest', |
+ 'pathSuffix': relativeLink, |
+ 'feature': this.error_.manifestKey, |
+ 'specific': this.error_.manifestSpecific |
+ }]); |
+ }.bind(this)); |
+ return node; |
+ } |
+ }; |
+ |
+ function ExtensionErrorList(errors) { |
+ var div = cloneTemplate('.extension-error-list'); |
+ div.__proto__ = ExtensionErrorList.prototype; |
+ div.errors_ = errors; |
+ div.decorate(); |
+ return div; |
+ } |
+ |
+ ExtensionErrorList.prototype = { |
+ __proto__: HTMLDivElement.prototype, |
+ |
+ kMaxErrorsToShow_: 3, |
+ |
+ /** @override */ |
+ decorate: function() { |
+ this.contents_ = this.querySelector('.extension-error-list-contents'); |
+ this.errors_.forEach(function(error) { |
+ this.contents_.appendChild(document.createElement('li')).appendChild( |
+ new ExtensionError(error)); |
+ }.bind(this)); |
+ |
+ if (this.contents_.children.length > this.kMaxErrorsToShow_) { |
+ for (var i = this.kMaxErrorsToShow_; |
+ i < this.contents_.children.length; ++i) |
+ this.contents_.children[i].hidden = true; |
+ this.initShowMoreButton_(); |
+ } |
+ }, |
+ |
+ initShowMoreButton_: function() { |
+ var button = this.querySelector('.extension-error-list-show-more') |
+ .querySelector('a'); |
+ button.hidden = false; |
+ button.isShowingAll = false; |
+ button.addEventListener('click', function(e) { |
+ if (button.isShowingAll) { |
+ for (var i = this.kMaxErrorsToShow_; |
+ i < this.contents_.children.length; ++i) { |
+ this.contents_.children[i].hidden = true; |
+ } |
+ button.innerText = loadTimeData.getString('extensionErrorsShowMore'); |
+ } else { |
+ for (var i = this.kMaxErrorsToShow_; |
+ i < this.contents_.children.length; ++i) { |
+ this.contents_.children[i].hidden = false; |
+ } |
+ button.innerText = loadTimeData.getString('extensionErrorsShowFewer'); |
+ } |
+ |
+ button.isShowingAll = !button.isShowingAll; |
+ }.bind(this)); |
+ } |
+ }; |
+ |
+ return { |
+ ExtensionErrorList: ExtensionErrorList |
+ }; |
+}); |