| 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
|
| index fb2699c73b5ada3ce8fd87809d3f315d56e8149b..774c9bbb02f5cbd46a97356b70ca5a183856a184 100644
|
| --- a/chrome/browser/resources/extensions/extension_error.js
|
| +++ b/chrome/browser/resources/extensions/extension_error.js
|
| @@ -41,13 +41,14 @@ cr.define('extensions', function() {
|
| * Creates a new ExtensionError HTMLElement; this is used to show a
|
| * notification to the user when an error is caused by an extension.
|
| * @param {Object} error The error the element should represent.
|
| + * @param {string} templateName The name of the template to clone for the
|
| + * error ('extension-error-[detailed|simple]-wrapper').
|
| * @constructor
|
| * @extends {HTMLDivElement}
|
| */
|
| - function ExtensionError(error) {
|
| - var div = document.createElement('div');
|
| + function ExtensionError(error, templateName) {
|
| + var div = cloneTemplate(templateName);
|
| div.__proto__ = ExtensionError.prototype;
|
| - div.className = 'extension-error-simple-wrapper';
|
| div.error_ = error;
|
| div.decorate();
|
| return div;
|
| @@ -77,14 +78,23 @@ cr.define('extensions', function() {
|
| this.extensionUrl_ =
|
| 'chrome-extension://' + this.error_.extensionId + '/';
|
|
|
| - metadata.querySelector('.extension-error-message').innerText =
|
| + metadata.querySelector('.extension-error-message').textContent =
|
| this.error_.message;
|
|
|
| metadata.appendChild(this.getViewSourceOrPlain_(
|
| getRelativeUrl(this.error_.source, this.extensionUrl_),
|
| this.error_.source));
|
|
|
| - this.appendChild(metadata);
|
| + // The error template may specify a <summary> to put template metadata in.
|
| + // If not, just append it to the top-level element.
|
| + var metadataContainer = this.querySelector('summary') || this;
|
| + metadataContainer.appendChild(metadata);
|
| +
|
| + var detailsNode = this.querySelector('.extension-error-details');
|
| + if (detailsNode && this.error_.contextUrl)
|
| + detailsNode.appendChild(this.getContextNode_());
|
| + if (detailsNode && this.error_.stackTrace)
|
| + detailsNode.appendChild(this.getStackNode_());
|
| },
|
|
|
| /**
|
| @@ -93,16 +103,17 @@ cr.define('extensions', function() {
|
| * @param {string} description a human-friendly description the location
|
| * (e.g., filename, line).
|
| * @param {string} url The url of the resource to view.
|
| + * @param {?number} line An optional line number of the resource.
|
| * @return {HTMLElement} The created node, either a link or plaintext.
|
| * @private
|
| */
|
| - getViewSourceOrPlain_: function(description, url) {
|
| + getViewSourceOrPlain_: function(description, url, line) {
|
| if (this.canViewSource_(url))
|
| - var node = this.getViewSourceLink_(url);
|
| + var node = this.getViewSourceLink_(url, line);
|
| else
|
| var node = document.createElement('div');
|
| node.className = 'extension-error-view-source';
|
| - node.innerText = description;
|
| + node.textContent = description;
|
| return node;
|
| },
|
|
|
| @@ -119,35 +130,106 @@ cr.define('extensions', function() {
|
| /**
|
| * Create a clickable node to view the source for the given url.
|
| * @param {string} url The url to the resource to view.
|
| + * @param {?number} line An optional line number of the resource (for
|
| + * source files).
|
| * @return {HTMLElement} The clickable node to view the source.
|
| * @private
|
| */
|
| - getViewSourceLink_: function(url) {
|
| + getViewSourceLink_: function(url, line) {
|
| var node = document.createElement('a');
|
| var relativeUrl = getRelativeUrl(url, this.extensionUrl_);
|
| + var requestFileSourceArgs = { 'extensionId': this.error_.extensionId,
|
| + 'message': this.error_.message,
|
| + 'pathSuffix': relativeUrl };
|
| + if (relativeUrl == 'manifest.json') {
|
| + requestFileSourceArgs.manifestKey = this.error_.manifestKey;
|
| + requestFileSourceArgs.manifestSpecific = this.error_.manifestSpecific;
|
| + } else {
|
| + // Prefer |line| if available, or default to the line of the last stack
|
| + // frame.
|
| + if (line) {
|
| + requestFileSourceArgs.lineNumber = line;
|
| + } else if (this.error_.stackTrace) {
|
| + requestFileSourceArgs.lineNumber =
|
| + this.error_.stackTrace[0].lineNumber;
|
| + }
|
| + }
|
|
|
| node.addEventListener('click', function(e) {
|
| - chrome.send('extensionErrorRequestFileSource',
|
| - [{'extensionId': this.error_.extensionId,
|
| - 'message': this.error_.message,
|
| - 'fileType': 'manifest',
|
| - 'pathSuffix': relativeUrl,
|
| - 'manifestKey': this.error_.manifestKey,
|
| - 'manifestSpecific': this.error_.manifestSpecific}]);
|
| - }.bind(this));
|
| + chrome.send('extensionErrorRequestFileSource', [requestFileSourceArgs]);
|
| + });
|
| + node.title = loadTimeData.getString('extensionErrorViewSource');
|
| + return node;
|
| + },
|
| +
|
| + /**
|
| + * Get the context node for this error. This will attempt to link to the
|
| + * context in which the error occurred, and can be either an extension page
|
| + * or an external page.
|
| + * @return {HTMLDivElement} The context node for the error, including the
|
| + * label and a link to the context.
|
| + * @private
|
| + */
|
| + getContextNode_: function() {
|
| + var node = cloneTemplate('extension-error-context-wrapper');
|
| + var linkNode = node.querySelector('a');
|
| + if (isExtensionUrl(this.error_.contextUrl, this.extensionUrl_)) {
|
| + linkNode.textContent = getRelativeUrl(this.error_.contextUrl,
|
| + this.extensionUrl_);
|
| + } else {
|
| + linkNode.textContent = this.error_.contextUrl;
|
| + }
|
| + linkNode.href = this.error_.contextUrl;
|
| + linkNode.target = '_blank';
|
| + return node;
|
| + },
|
| +
|
| + /**
|
| + * Get a node for the stack trace for this error. Each stack frame will
|
| + * include a resource url, line number, and function name (possibly
|
| + * anonymous). If possible, these frames will also be linked for viewing the
|
| + * source.
|
| + * @return {HTMLDetailsElement} The stack trace node for this error, with
|
| + * all stack frames nested in a details-summary object.
|
| + * @private
|
| + */
|
| + getStackNode_: function() {
|
| + var node = cloneTemplate('extension-error-stack-trace');
|
| + var listNode = node.querySelector('.extension-error-stack-trace-list');
|
| + this.error_.stackTrace.forEach(function(frame) {
|
| + var frameNode = document.createElement('div');
|
| + var description = getRelativeUrl(frame.url, this.extensionUrl_) +
|
| + ':' + frame.lineNumber;
|
| + if (frame.functionName) {
|
| + var functionName = frame.functionName == '(anonymous function)' ?
|
| + loadTimeData.getString('extensionErrorAnonymousFunction') :
|
| + frame.functionName;
|
| + description += ' (' + functionName + ')';
|
| + }
|
| + frameNode.appendChild(this.getViewSourceOrPlain_(
|
| + description, frame.url, frame.lineNumber));
|
| + listNode.appendChild(
|
| + document.createElement('li')).appendChild(frameNode);
|
| + }, this);
|
| +
|
| return node;
|
| },
|
| };
|
|
|
| /**
|
| * A variable length list of runtime or manifest errors for a given extension.
|
| + * @param {Array.<Object>} errors The list of extension errors with which
|
| + * to populate the list.
|
| + * @param {string} title The i18n key for the title of the error list, i.e.
|
| + * 'extensionErrors[Manifest,Runtime]Errors'.
|
| * @constructor
|
| * @extends {HTMLDivElement}
|
| */
|
| - function ExtensionErrorList(errors) {
|
| + function ExtensionErrorList(errors, title) {
|
| var div = cloneTemplate('extension-error-list');
|
| div.__proto__ = ExtensionErrorList.prototype;
|
| div.errors_ = errors;
|
| + div.title_ = title;
|
| div.decorate();
|
| return div;
|
| }
|
| @@ -164,10 +246,16 @@ cr.define('extensions', function() {
|
|
|
| /** @override */
|
| decorate: function() {
|
| + this.querySelector('.extension-error-list-title').textContent =
|
| + loadTimeData.getString(this.title_);
|
| +
|
| this.contents_ = this.querySelector('.extension-error-list-contents');
|
| this.errors_.forEach(function(error) {
|
| this.contents_.appendChild(document.createElement('li')).appendChild(
|
| - new ExtensionError(error));
|
| + new ExtensionError(error,
|
| + error.contextUrl || error.stackTrace ?
|
| + 'extension-error-detailed-wrapper' :
|
| + 'extension-error-simple-wrapper'));
|
| }, this);
|
|
|
| if (this.contents_.children.length > this.MAX_ERRORS_TO_SHOW_) {
|
| @@ -195,7 +283,7 @@ cr.define('extensions', function() {
|
| }
|
| var message = button.isShowingAll ? 'extensionErrorsShowMore' :
|
| 'extensionErrorsShowFewer';
|
| - button.innerText = loadTimeData.getString(message);
|
| + button.textContent = loadTimeData.getString(message);
|
| button.isShowingAll = !button.isShowingAll;
|
| }.bind(this));
|
| }
|
|
|