| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 <include src="extension_error_overlay.js"></include> | 5 <include src="extension_error_overlay.js"></include> |
| 6 | 6 |
| 7 cr.define('extensions', function() { | 7 cr.define('extensions', function() { |
| 8 'use strict'; | 8 'use strict'; |
| 9 | 9 |
| 10 /** | 10 /** |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 * @constructor | 34 * @constructor |
| 35 * @extends {HTMLDivElement} | 35 * @extends {HTMLDivElement} |
| 36 */ | 36 */ |
| 37 function ExtensionError(error) { | 37 function ExtensionError(error) { |
| 38 var div = cloneTemplate('extension-error-metadata'); | 38 var div = cloneTemplate('extension-error-metadata'); |
| 39 div.__proto__ = ExtensionError.prototype; | 39 div.__proto__ = ExtensionError.prototype; |
| 40 div.decorate(error); | 40 div.decorate(error); |
| 41 return div; | 41 return div; |
| 42 } | 42 } |
| 43 | 43 |
| 44 /** | |
| 45 * The manifest filename. | |
| 46 * @type {string} | |
| 47 * @const | |
| 48 * @private | |
| 49 */ | |
| 50 ExtensionError.MANIFEST_FILENAME_ = 'manifest.json'; | |
| 51 | |
| 52 /** | |
| 53 * Determine whether or not chrome can load the source for a given file; this | |
| 54 * can only be done if the file belongs to the extension. | |
| 55 * @param {string} file The file to load. | |
| 56 * @param {string} extensionUrl The url for the extension, in the form | |
| 57 * chrome-extension://<extension-id>/. | |
| 58 * @return {boolean} True if the file can be loaded, false otherwise. | |
| 59 * @private | |
| 60 */ | |
| 61 ExtensionError.canLoadFileSource_ = function(file, extensionUrl) { | |
| 62 return RegExp('^' + extensionUrl).test(file) || | |
| 63 file.toLowerCase() == ExtensionError.MANIFEST_FILENAME_; | |
| 64 }; | |
| 65 | |
| 66 /** | |
| 67 * Determine whether or not there are any user-friendly (non-internal) frames | |
| 68 * in the error's stack trace. | |
| 69 * @param {Object} error The error to examine. | |
| 70 * @return {boolean} True if there are user-friendly stack frames for the | |
| 71 * error, false otherwise. | |
| 72 * @private | |
| 73 */ | |
| 74 ExtensionError.hasExternalStackFrames_ = function(error) { | |
| 75 // All our internal source begins with the "extensions::" prefix. | |
| 76 var extensionPrefix = /^extensions::/; | |
| 77 for (var i = 0; i < error.stackTrace.length; ++i) { | |
| 78 if (!extensionPrefix.test(error.stackTrace[i].url)) | |
| 79 return true; | |
| 80 } | |
| 81 return false; | |
| 82 }; | |
| 83 | |
| 84 ExtensionError.prototype = { | 44 ExtensionError.prototype = { |
| 85 __proto__: HTMLDivElement.prototype, | 45 __proto__: HTMLDivElement.prototype, |
| 86 | 46 |
| 87 /** @override */ | 47 /** @override */ |
| 88 decorate: function(error) { | 48 decorate: function(error) { |
| 89 // Add an additional class for the severity level. | 49 // Add an additional class for the severity level. |
| 90 if (error.level == 0) | 50 if (error.level == 0) |
| 91 this.classList.add('extension-error-severity-info'); | 51 this.classList.add('extension-error-severity-info'); |
| 92 else if (error.level == 1) | 52 else if (error.level == 1) |
| 93 this.classList.add('extension-error-severity-warning'); | 53 this.classList.add('extension-error-severity-warning'); |
| 94 else | 54 else |
| 95 this.classList.add('extension-error-severity-fatal'); | 55 this.classList.add('extension-error-severity-fatal'); |
| 96 | 56 |
| 97 var iconNode = document.createElement('img'); | 57 var iconNode = document.createElement('img'); |
| 98 iconNode.className = 'extension-error-icon'; | 58 iconNode.className = 'extension-error-icon'; |
| 99 this.insertBefore(iconNode, this.firstChild); | 59 this.insertBefore(iconNode, this.firstChild); |
| 100 | 60 |
| 101 var messageSpan = this.querySelector('.extension-error-message'); | 61 var messageSpan = this.querySelector('.extension-error-message'); |
| 102 messageSpan.textContent = error.message; | 62 messageSpan.textContent = error.message; |
| 103 messageSpan.title = error.message; | 63 messageSpan.title = error.message; |
| 104 | 64 |
| 105 var extensionUrl = 'chrome-extension://' + error.extensionId + '/'; | 65 var extensionUrl = 'chrome-extension://' + error.extensionId + '/'; |
| 106 var viewDetailsLink = this.querySelector('.extension-error-view-details'); | 66 var viewDetailsLink = this.querySelector('.extension-error-view-details'); |
| 107 | 67 |
| 108 // If we cannot open the file source and there are no external frames in | 68 // If we cannot open the file source and there are no external frames in |
| 109 // the stack, then there are no details to display. | 69 // the stack, then there are no details to display. |
| 110 if (!ExtensionError.canLoadFileSource_(error.source, extensionUrl) && | 70 if (!extensions.ExtensionErrorOverlay.canShowOverlayForError( |
| 111 !ExtensionError.hasExternalStackFrames_(error)) { | 71 error, extensionUrl)) { |
| 112 viewDetailsLink.hidden = true; | 72 viewDetailsLink.hidden = true; |
| 113 return; | 73 } else { |
| 74 var stringId = extensionUrl.toLowerCase() == 'manifest.json' ? |
| 75 'extensionErrorViewManifest' : 'extensionErrorViewDetails'; |
| 76 viewDetailsLink.textContent = loadTimeData.getString(stringId); |
| 77 |
| 78 viewDetailsLink.addEventListener('click', function(e) { |
| 79 extensions.ExtensionErrorOverlay.getInstance().setErrorAndShowOverlay( |
| 80 error, extensionUrl); |
| 81 }); |
| 114 } | 82 } |
| 115 | |
| 116 // The relative url is the url without the preceeding | |
| 117 // "chrome-extension://<id>"; this is the format which the | |
| 118 // requestFileSource call expects. | |
| 119 var relativeUrl = | |
| 120 error.source.substring(0, extensionUrl.length) == extensionUrl ? | |
| 121 error.source.substring(extensionUrl.length) : error.source; | |
| 122 | |
| 123 var requestFileSourceArgs = {extensionId: error.extensionId, | |
| 124 message: error.message, | |
| 125 pathSuffix: relativeUrl}; | |
| 126 | |
| 127 var viewDetailsStringId; | |
| 128 if (relativeUrl.toLowerCase() == 'manifest.json') { | |
| 129 requestFileSourceArgs.manifestKey = error.manifestKey; | |
| 130 requestFileSourceArgs.manifestSpecific = error.manifestSpecific; | |
| 131 viewDetailsStringId = 'extensionErrorViewManifest'; | |
| 132 } else { | |
| 133 requestFileSourceArgs.lineNumber = | |
| 134 error.stackTrace && error.stackTrace[0] ? | |
| 135 error.stackTrace[0].lineNumber : 0; | |
| 136 viewDetailsStringId = 'extensionErrorViewDetails'; | |
| 137 } | |
| 138 viewDetailsLink.textContent = loadTimeData.getString(viewDetailsStringId); | |
| 139 | |
| 140 viewDetailsLink.addEventListener('click', function(e) { | |
| 141 var overlay = extensions.ExtensionErrorOverlay.getInstance(); | |
| 142 overlay.setError(error); | |
| 143 | |
| 144 // If we can, request the file source to show to the user in the | |
| 145 // overlay. Otherwise, simply show the overlay. | |
| 146 if (ExtensionError.canLoadFileSource_(error.source, extensionUrl)) { | |
| 147 chrome.send('extensionErrorRequestFileSource', | |
| 148 [requestFileSourceArgs]); | |
| 149 } else { | |
| 150 overlay.requestFileSourceResponse(null); | |
| 151 } | |
| 152 }.bind(this)); | |
| 153 }, | 83 }, |
| 154 }; | 84 }; |
| 155 | 85 |
| 156 /** | 86 /** |
| 157 * A variable length list of runtime or manifest errors for a given extension. | 87 * A variable length list of runtime or manifest errors for a given extension. |
| 158 * @param {Array.<Object>} errors The list of extension errors with which | 88 * @param {Array.<Object>} errors The list of extension errors with which |
| 159 * to populate the list. | 89 * to populate the list. |
| 160 * @constructor | 90 * @constructor |
| 161 * @extends {HTMLDivElement} | 91 * @extends {HTMLDivElement} |
| 162 */ | 92 */ |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 216 button.textContent = loadTimeData.getString(message); | 146 button.textContent = loadTimeData.getString(message); |
| 217 button.isShowingAll = !button.isShowingAll; | 147 button.isShowingAll = !button.isShowingAll; |
| 218 }.bind(this)); | 148 }.bind(this)); |
| 219 } | 149 } |
| 220 }; | 150 }; |
| 221 | 151 |
| 222 return { | 152 return { |
| 223 ExtensionErrorList: ExtensionErrorList | 153 ExtensionErrorList: ExtensionErrorList |
| 224 }; | 154 }; |
| 225 }); | 155 }); |
| OLD | NEW |