| 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 cr.define('extensions', function() { | 5 cr.define('extensions', function() { |
| 6 'use strict'; | 6 'use strict'; |
| 7 | 7 |
| 8 /** | 8 /** |
| 9 * Get the url relative to the main extension url. If the url is |
| 10 * unassociated with the extension, this will be the full url. |
| 11 * @param {string} url The url to make relative. |
| 12 * @param {string} extensionUrl The url for the extension resources, in the |
| 13 * form "chrome-etxension://<extension_id>/". |
| 14 * @return {string} The url relative to the host. |
| 15 */ |
| 16 function getRelativeUrl(url, extensionUrl) { |
| 17 return url.substring(0, extensionUrl.length) == extensionUrl ? |
| 18 url.substring(extensionUrl.length) : url; |
| 19 } |
| 20 |
| 21 /** |
| 9 * The RuntimeErrorContent manages all content specifically associated with | 22 * The RuntimeErrorContent manages all content specifically associated with |
| 10 * runtime errors; this includes stack frames and the context url. | 23 * runtime errors; this includes stack frames and the context url. |
| 11 * @constructor | 24 * @constructor |
| 12 * @extends {HTMLDivElement} | 25 * @extends {HTMLDivElement} |
| 13 */ | 26 */ |
| 14 function RuntimeErrorContent() { | 27 function RuntimeErrorContent() { |
| 15 var contentArea = $('template-collection-extension-error-overlay'). | 28 var contentArea = $('template-collection-extension-error-overlay'). |
| 16 querySelector('.extension-error-overlay-runtime-content'). | 29 querySelector('.extension-error-overlay-runtime-content'). |
| 17 cloneNode(true); | 30 cloneNode(true); |
| 18 contentArea.__proto__ = RuntimeErrorContent.prototype; | 31 contentArea.__proto__ = RuntimeErrorContent.prototype; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 33 * want to include any of our own code in stack traces. | 46 * want to include any of our own code in stack traces. |
| 34 * @param {string} url The url in question. | 47 * @param {string} url The url in question. |
| 35 * @return {boolean} True if the url should be displayed, and false | 48 * @return {boolean} True if the url should be displayed, and false |
| 36 * otherwise (i.e., if it is an internal script). | 49 * otherwise (i.e., if it is an internal script). |
| 37 */ | 50 */ |
| 38 RuntimeErrorContent.shouldDisplayForUrl = function(url) { | 51 RuntimeErrorContent.shouldDisplayForUrl = function(url) { |
| 39 // All our internal scripts are in the 'extensions::' namespace. | 52 // All our internal scripts are in the 'extensions::' namespace. |
| 40 return !/^extensions::/.test(url); | 53 return !/^extensions::/.test(url); |
| 41 }; | 54 }; |
| 42 | 55 |
| 56 /** |
| 57 * Send a call to chrome to open the developer tools for an error. |
| 58 * This will call either the bound function in ExtensionErrorHandler or the |
| 59 * API function from developerPrivate, depending on whether this is being |
| 60 * used in the native chrome:extensions page or the Apps Developer Tool. |
| 61 * @see chrome/browser/ui/webui/extensions/extension_error_ui_util.h |
| 62 * @param {Object} args The arguments to pass to openDevTools. |
| 63 * @private |
| 64 */ |
| 65 RuntimeErrorContent.openDevtools_ = function(args) { |
| 66 if (chrome.send) |
| 67 chrome.send('extensionErrorOpenDevTools', [args]); |
| 68 else if (chrome.developerPrivate) |
| 69 chrome.developerPrivate.openDevTools(args); |
| 70 else |
| 71 assert(false, 'Cannot call either openDevTools function.'); |
| 72 }; |
| 73 |
| 43 RuntimeErrorContent.prototype = { | 74 RuntimeErrorContent.prototype = { |
| 44 __proto__: HTMLDivElement.prototype, | 75 __proto__: HTMLDivElement.prototype, |
| 45 | 76 |
| 46 /** | 77 /** |
| 47 * The underlying error whose details are being displayed. | 78 * The underlying error whose details are being displayed. |
| 48 * @type {Object} | 79 * @type {Object} |
| 49 * @private | 80 * @private |
| 50 */ | 81 */ |
| 51 error_: undefined, | 82 error_: undefined, |
| 52 | 83 |
| 53 /** | 84 /** |
| 54 * The URL associated with this extension, i.e. chrome-extension://<id>. | 85 * The URL associated with this extension, i.e. chrome-extension://<id>/. |
| 55 * @type {string} | 86 * @type {string} |
| 56 * @private | 87 * @private |
| 57 */ | 88 */ |
| 58 extensionUrl_: undefined, | 89 extensionUrl_: undefined, |
| 59 | 90 |
| 60 /** | 91 /** |
| 61 * The node of the stack trace which is currently active. | 92 * The node of the stack trace which is currently active. |
| 62 * @type {HTMLElement} | 93 * @type {HTMLElement} |
| 63 * @private | 94 * @private |
| 64 */ | 95 */ |
| (...skipping 18 matching lines...) Expand all Loading... |
| 83 * @private | 114 * @private |
| 84 */ | 115 */ |
| 85 this.contextUrl_ = | 116 this.contextUrl_ = |
| 86 this.querySelector('.extension-error-overlay-context-url'); | 117 this.querySelector('.extension-error-overlay-context-url'); |
| 87 assert(this.contextUrl_); | 118 assert(this.contextUrl_); |
| 88 }, | 119 }, |
| 89 | 120 |
| 90 /** | 121 /** |
| 91 * Sets the error for the content. | 122 * Sets the error for the content. |
| 92 * @param {Object} error The error whose content should be displayed. | 123 * @param {Object} error The error whose content should be displayed. |
| 124 * @param {string} extensionUrl The URL associated with this extension. |
| 93 */ | 125 */ |
| 94 setError: function(error) { | 126 setError: function(error, extensionUrl) { |
| 95 this.error_ = error; | 127 this.error_ = error; |
| 96 this.extensionUrl_ = 'chrome-extension://' + error.extensionId + '/'; | 128 this.extensionUrl_ = extensionUrl; |
| 97 this.contextUrl_.textContent = error.contextUrl ? | 129 this.contextUrl_.textContent = error.contextUrl ? |
| 98 this.getRelativeUrl_(error.contextUrl) : | 130 getRelativeUrl(error.contextUrl, this.extensionUrl_) : |
| 99 loadTimeData.getString('extensionErrorOverlayContextUnknown'); | 131 loadTimeData.getString('extensionErrorOverlayContextUnknown'); |
| 100 this.initStackTrace_(); | 132 this.initStackTrace_(); |
| 101 }, | 133 }, |
| 102 | 134 |
| 103 /** | 135 /** |
| 104 * Wipe content associated with a specific error. | 136 * Wipe content associated with a specific error. |
| 105 */ | 137 */ |
| 106 clearError: function() { | 138 clearError: function() { |
| 107 this.error_ = undefined; | 139 this.error_ = undefined; |
| 108 this.extensionUrl_ = undefined; | 140 this.extensionUrl_ = undefined; |
| 109 this.currentFrameNode_ = undefined; | 141 this.currentFrameNode_ = undefined; |
| 110 this.stackTrace_.innerHTML = ''; | 142 this.stackTrace_.innerHTML = ''; |
| 111 this.stackTrace_.hidden = true; | 143 this.stackTrace_.hidden = true; |
| 112 }, | 144 }, |
| 113 | 145 |
| 114 /** | 146 /** |
| 115 * Returns whether or not a given |url| is associated with the current | |
| 116 * extension. | |
| 117 * @param {string} url The url to examine. | |
| 118 * @return {boolean} Whether or not the url is associated with the extension | |
| 119 * @private | |
| 120 */ | |
| 121 isRelatedUrl_: function(url) { | |
| 122 return url.substring(0, this.extensionUrl_.length) == this.extensionUrl_; | |
| 123 }, | |
| 124 | |
| 125 /** | |
| 126 * Get the url relative to the main extension url. If the url is | |
| 127 * unassociated with the extension, this will be the full url. | |
| 128 * @param {string} url The url to make relative. | |
| 129 * @return {string} The url relative to the host. | |
| 130 * @private | |
| 131 */ | |
| 132 getRelativeUrl_: function(url) { | |
| 133 return this.isRelatedUrl_(url, this.extensionUrl_) ? | |
| 134 url.substring(this.extensionUrl_.length) : url; | |
| 135 }, | |
| 136 | |
| 137 /** | |
| 138 * Makes |frame| active and deactivates the previously active frame (if | 147 * Makes |frame| active and deactivates the previously active frame (if |
| 139 * there was one). | 148 * there was one). |
| 140 * @param {HTMLElement} frame The frame to activate. | 149 * @param {HTMLElement} frame The frame to activate. |
| 141 * @private | 150 * @private |
| 142 */ | 151 */ |
| 143 setActiveFrame_: function(frameNode) { | 152 setActiveFrame_: function(frameNode) { |
| 144 if (this.currentFrameNode_) { | 153 if (this.currentFrameNode_) { |
| 145 this.currentFrameNode_.classList.remove( | 154 this.currentFrameNode_.classList.remove( |
| 146 RuntimeErrorContent.ACTIVE_CLASS_NAME); | 155 RuntimeErrorContent.ACTIVE_CLASS_NAME); |
| 147 } | 156 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 164 continue; | 173 continue; |
| 165 | 174 |
| 166 var frameNode = document.createElement('li'); | 175 var frameNode = document.createElement('li'); |
| 167 // Attach the index of the frame to which this node refers (since we | 176 // Attach the index of the frame to which this node refers (since we |
| 168 // may skip some, this isn't a 1-to-1 match). | 177 // may skip some, this isn't a 1-to-1 match). |
| 169 frameNode.indexIntoTrace = i; | 178 frameNode.indexIntoTrace = i; |
| 170 | 179 |
| 171 // The description is a human-readable summation of the frame, in the | 180 // The description is a human-readable summation of the frame, in the |
| 172 // form "<relative_url>:<line_number> (function)", e.g. | 181 // form "<relative_url>:<line_number> (function)", e.g. |
| 173 // "myfile.js:25 (myFunction)". | 182 // "myfile.js:25 (myFunction)". |
| 174 var description = | 183 var description = getRelativeUrl(frame.url, this.extensionUrl_) + |
| 175 this.getRelativeUrl_(frame.url) + ':' + frame.lineNumber; | 184 ':' + frame.lineNumber; |
| 176 if (frame.functionName) { | 185 if (frame.functionName) { |
| 177 var functionName = frame.functionName == '(anonymous function)' ? | 186 var functionName = frame.functionName == '(anonymous function)' ? |
| 178 loadTimeData.getString('extensionErrorOverlayAnonymousFunction') : | 187 loadTimeData.getString('extensionErrorOverlayAnonymousFunction') : |
| 179 frame.functionName; | 188 frame.functionName; |
| 180 description += ' (' + functionName + ')'; | 189 description += ' (' + functionName + ')'; |
| 181 } | 190 } |
| 182 frameNode.textContent = description; | 191 frameNode.textContent = description; |
| 183 | 192 |
| 184 // When the user clicks on a frame in the stack trace, we should | 193 // When the user clicks on a frame in the stack trace, we should |
| 185 // highlight that overlay in the list, display the appropriate source | 194 // highlight that overlay in the list, display the appropriate source |
| 186 // code with the line highlighted, and link the "Open DevTools" button | 195 // code with the line highlighted, and link the "Open DevTools" button |
| 187 // with that frame. | 196 // with that frame. |
| 188 frameNode.addEventListener('click', function(frame, frameNode, e) { | 197 frameNode.addEventListener('click', function(frame, frameNode, e) { |
| 189 if (this.currStackFrame_ == frameNode) | 198 if (this.currStackFrame_ == frameNode) |
| 190 return; | 199 return; |
| 191 | 200 |
| 192 this.setActiveFrame_(frameNode); | 201 this.setActiveFrame_(frameNode); |
| 193 | 202 |
| 194 // Request the file source with the section highlighted; this will | 203 // Request the file source with the section highlighted; this will |
| 195 // call ExtensionErrorOverlay.requestFileSourceResponse() when | 204 // call ExtensionErrorOverlay.requestFileSourceResponse() when |
| 196 // completed, which in turn calls setCode(). | 205 // completed, which in turn calls setCode(). |
| 197 chrome.send('extensionErrorRequestFileSource', | 206 ExtensionErrorOverlay.requestFileSource( |
| 198 [{extensionId: this.error_.extensionId, | 207 {extensionId: this.error_.extensionId, |
| 199 message: this.error_.message, | 208 message: this.error_.message, |
| 200 pathSuffix: this.getRelativeUrl_(frame.url), | 209 pathSuffix: getRelativeUrl(frame.url, this.extensionUrl_), |
| 201 lineNumber: frame.lineNumber}]); | 210 lineNumber: frame.lineNumber}); |
| 202 }.bind(this, frame, frameNode)); | 211 }.bind(this, frame, frameNode)); |
| 203 | 212 |
| 204 this.stackTrace_.appendChild(frameNode); | 213 this.stackTrace_.appendChild(frameNode); |
| 205 } | 214 } |
| 206 | 215 |
| 207 // Set the current stack frame to the first stack frame and show the | 216 // Set the current stack frame to the first stack frame and show the |
| 208 // trace, if one exists. (We can't just check error.stackTrace, because | 217 // trace, if one exists. (We can't just check error.stackTrace, because |
| 209 // it's possible the trace was purely internal, and we don't show | 218 // it's possible the trace was purely internal, and we don't show |
| 210 // internal frames.) | 219 // internal frames.) |
| 211 if (this.stackTrace_.children.length > 0) { | 220 if (this.stackTrace_.children.length > 0) { |
| 212 this.stackTrace_.hidden = false; | 221 this.stackTrace_.hidden = false; |
| 213 this.setActiveFrame_(this.stackTrace_.firstChild); | 222 this.setActiveFrame_(this.stackTrace_.firstChild); |
| 214 } | 223 } |
| 215 }, | 224 }, |
| 216 | 225 |
| 217 /** | 226 /** |
| 218 * Open the developer tools for the active stack frame. | 227 * Open the developer tools for the active stack frame. |
| 219 */ | 228 */ |
| 220 openDevtools: function() { | 229 openDevtools: function() { |
| 221 var stackFrame = | 230 var stackFrame = |
| 222 this.error_.stackTrace[this.currentFrameNode_.indexIntoTrace]; | 231 this.error_.stackTrace[this.currentFrameNode_.indexIntoTrace]; |
| 223 | 232 |
| 224 chrome.send('extensionErrorOpenDevTools', | 233 RuntimeErrorContent.openDevtools_( |
| 225 [{renderProcessId: this.error_.renderProcessId, | 234 {renderProcessId: this.error_.renderProcessId, |
| 226 renderViewId: this.error_.renderViewId, | 235 renderViewId: this.error_.renderViewId, |
| 227 url: stackFrame.url, | 236 url: stackFrame.url, |
| 228 lineNumber: stackFrame.lineNumber || 0, | 237 lineNumber: stackFrame.lineNumber || 0, |
| 229 columnNumber: stackFrame.columnNumber || 0}]); | 238 columnNumber: stackFrame.columnNumber || 0}); |
| 230 } | 239 } |
| 231 }; | 240 }; |
| 232 | 241 |
| 233 /** | 242 /** |
| 234 * The ExtensionErrorOverlay will show the contents of a file which pertains | 243 * The ExtensionErrorOverlay will show the contents of a file which pertains |
| 235 * to the ExtensionError; this is either the manifest file (for manifest | 244 * to the ExtensionError; this is either the manifest file (for manifest |
| 236 * errors) or a source file (for runtime errors). If possible, the portion | 245 * errors) or a source file (for runtime errors). If possible, the portion |
| 237 * of the file which caused the error will be highlighted. | 246 * of the file which caused the error will be highlighted. |
| 238 * @constructor | 247 * @constructor |
| 239 */ | 248 */ |
| 240 function ExtensionErrorOverlay() { | 249 function ExtensionErrorOverlay() { |
| 241 /** | 250 /** |
| 242 * The content section for runtime errors; this is re-used for all | 251 * The content section for runtime errors; this is re-used for all |
| 243 * runtime errors and attached/detached from the overlay as needed. | 252 * runtime errors and attached/detached from the overlay as needed. |
| 244 * @type {RuntimeErrorContent} | 253 * @type {RuntimeErrorContent} |
| 245 * @private | 254 * @private |
| 246 */ | 255 */ |
| 247 this.runtimeErrorContent_ = new RuntimeErrorContent(); | 256 this.runtimeErrorContent_ = new RuntimeErrorContent(); |
| 248 } | 257 } |
| 249 | 258 |
| 250 /** | 259 /** |
| 251 * Value of ExtensionError::RUNTIME_ERROR enum. | 260 * Value of ExtensionError::RUNTIME_ERROR enum. |
| 252 * @see extensions/browser/extension_error.h | 261 * @see extensions/browser/extension_error.h |
| 253 * @type {number} | 262 * @type {number} |
| 254 * @const | 263 * @const |
| 255 * @private | 264 * @private |
| 256 */ | 265 */ |
| 257 ExtensionErrorOverlay.RUNTIME_ERROR_TYPE_ = 1; | 266 ExtensionErrorOverlay.RUNTIME_ERROR_TYPE_ = 1; |
| 258 | 267 |
| 268 /** |
| 269 * The manifest filename. |
| 270 * @type {string} |
| 271 * @const |
| 272 * @private |
| 273 */ |
| 274 ExtensionErrorOverlay.MANIFEST_FILENAME_ = 'manifest.json'; |
| 275 |
| 276 /** |
| 277 * Determine whether or not chrome can load the source for a given file; this |
| 278 * can only be done if the file belongs to the extension. |
| 279 * @param {string} file The file to load. |
| 280 * @param {string} extensionUrl The url for the extension, in the form |
| 281 * chrome-extension://<extension-id>/. |
| 282 * @return {boolean} True if the file can be loaded, false otherwise. |
| 283 * @private |
| 284 */ |
| 285 ExtensionErrorOverlay.canLoadFileSource = function(file, extensionUrl) { |
| 286 return file.substr(0, extensionUrl.length) == extensionUrl || |
| 287 file.toLowerCase() == ExtensionErrorOverlay.MANIFEST_FILENAME_; |
| 288 }; |
| 289 |
| 290 /** |
| 291 * Determine whether or not we can show an overlay with more details for |
| 292 * the given extension error. |
| 293 * @param {Object} error The extension error. |
| 294 * @param {string} extensionUrl The url for the extension, in the form |
| 295 * "chrome-extension://<extension-id>/". |
| 296 * @return {boolean} True if we can show an overlay for the error, |
| 297 * false otherwise. |
| 298 */ |
| 299 ExtensionErrorOverlay.canShowOverlayForError = function(error, extensionUrl) { |
| 300 if (ExtensionErrorOverlay.canLoadFileSource(error.source, extensionUrl)) |
| 301 return true; |
| 302 |
| 303 if (error.stackTrace) { |
| 304 for (var i = 0; i < error.stackTrace.length; ++i) { |
| 305 if (RuntimeErrorContent.shouldDisplayForUrl(error.stackTrace[i].url)) |
| 306 return true; |
| 307 } |
| 308 } |
| 309 |
| 310 return false; |
| 311 }; |
| 312 |
| 313 /** |
| 314 * Send a call to chrome to request the source of a given file. |
| 315 * This will call either the bound function in ExtensionErrorHandler or the |
| 316 * API function from developerPrivate, depending on whether this is being |
| 317 * used in the native chrome:extensions page or the Apps Developer Tool. |
| 318 * @see chrome/browser/ui/webui/extensions/extension_error_ui_util.h |
| 319 * @param {Object} args The arguments to pass to requestFileSource. |
| 320 */ |
| 321 ExtensionErrorOverlay.requestFileSource = function(args) { |
| 322 if (chrome.send) { |
| 323 chrome.send('extensionErrorRequestFileSource', [args]); |
| 324 } else if (chrome.developerPrivate) { |
| 325 chrome.developerPrivate.requestFileSource(args, function(result) { |
| 326 extensions.ExtensionErrorOverlay.requestFileSourceResponse(result); |
| 327 }); |
| 328 } else { |
| 329 assert(false, 'Cannot call either requestFileSource function.'); |
| 330 } |
| 331 }; |
| 332 |
| 259 cr.addSingletonGetter(ExtensionErrorOverlay); | 333 cr.addSingletonGetter(ExtensionErrorOverlay); |
| 260 | 334 |
| 261 ExtensionErrorOverlay.prototype = { | 335 ExtensionErrorOverlay.prototype = { |
| 262 /** | 336 /** |
| 263 * The underlying error whose details are being displayed. | 337 * The underlying error whose details are being displayed. |
| 264 * @type {Object} | 338 * @type {Object} |
| 265 * @private | 339 * @private |
| 266 */ | 340 */ |
| 267 error_: undefined, | 341 error_: undefined, |
| 268 | 342 |
| 269 /** | 343 /** |
| 270 * Initialize the page. | 344 * Initialize the page. |
| 345 * @param {function(HTMLDivElement)} showOverlay The function to show or |
| 346 * hide the ExtensionErrorOverlay; this should take a single parameter |
| 347 * which is either the overlay Div if the overlay should be displayed, |
| 348 * or null if the overlay should be hidden. |
| 271 */ | 349 */ |
| 272 initializePage: function() { | 350 initializePage: function(showOverlay) { |
| 273 var overlay = $('overlay'); | 351 var overlay = $('overlay'); |
| 274 cr.ui.overlay.setupOverlay(overlay); | 352 cr.ui.overlay.setupOverlay(overlay); |
| 275 cr.ui.overlay.globalInitialization(); | 353 cr.ui.overlay.globalInitialization(); |
| 276 overlay.addEventListener('cancelOverlay', this.handleDismiss_.bind(this)); | 354 overlay.addEventListener('cancelOverlay', this.handleDismiss_.bind(this)); |
| 277 | 355 |
| 278 $('extension-error-overlay-dismiss').addEventListener( | 356 $('extension-error-overlay-dismiss').addEventListener( |
| 279 'click', this.handleDismiss_.bind(this)); | 357 'click', this.handleDismiss_.bind(this)); |
| 280 | 358 |
| 281 /** | 359 /** |
| 282 * The element of the full overlay. | 360 * The element of the full overlay. |
| 283 * @type {HTMLDivElement} | 361 * @type {HTMLDivElement} |
| 284 * @private | 362 * @private |
| 285 */ | 363 */ |
| 286 this.overlayDiv_ = $('extension-error-overlay'); | 364 this.overlayDiv_ = $('extension-error-overlay'); |
| 287 | 365 |
| 288 /** | 366 /** |
| 289 * The portion of the overlay which shows the code relating to the error. | 367 * The portion of the overlay which shows the code relating to the error. |
| 290 * @type {HTMLElement} | 368 * @type {HTMLElement} |
| 291 * @private | 369 * @private |
| 292 */ | 370 */ |
| 293 this.codeDiv_ = $('extension-error-overlay-code'); | 371 this.codeDiv_ = $('extension-error-overlay-code'); |
| 294 | 372 |
| 295 /** | 373 /** |
| 374 * The function to show or hide the ExtensionErrorOverlay. |
| 375 * @type {function} |
| 376 * @param {boolean} isVisible Whether the overlay should be visible. |
| 377 */ |
| 378 this.setVisible = function(isVisible) { |
| 379 showOverlay(isVisible ? this.overlayDiv_ : null); |
| 380 }; |
| 381 |
| 382 /** |
| 296 * The button to open the developer tools (only available for runtime | 383 * The button to open the developer tools (only available for runtime |
| 297 * errors). | 384 * errors). |
| 298 * @type {HTMLButtonElement} | 385 * @type {HTMLButtonElement} |
| 299 * @private | 386 * @private |
| 300 */ | 387 */ |
| 301 this.openDevtoolsButton_ = $('extension-error-overlay-devtools-button'); | 388 this.openDevtoolsButton_ = $('extension-error-overlay-devtools-button'); |
| 302 this.openDevtoolsButton_.addEventListener('click', function() { | 389 this.openDevtoolsButton_.addEventListener('click', function() { |
| 303 this.runtimeErrorContent_.openDevtools(); | 390 this.runtimeErrorContent_.openDevtools(); |
| 304 }.bind(this)); | 391 }.bind(this)); |
| 305 }, | 392 }, |
| 306 | 393 |
| 307 /** | 394 /** |
| 308 * Handles a click on the dismiss ("OK" or close) buttons. | 395 * Handles a click on the dismiss ("OK" or close) buttons. |
| 309 * @param {Event} e The click event. | 396 * @param {Event} e The click event. |
| 310 * @private | 397 * @private |
| 311 */ | 398 */ |
| 312 handleDismiss_: function(e) { | 399 handleDismiss_: function(e) { |
| 313 extensions.ExtensionSettings.showOverlay(null); | 400 this.setVisible(false); |
| 314 | 401 |
| 315 // There's a chance that the overlay receives multiple dismiss events; in | 402 // There's a chance that the overlay receives multiple dismiss events; in |
| 316 // this case, handle it gracefully and return (since all necessary work | 403 // this case, handle it gracefully and return (since all necessary work |
| 317 // will already have been done). | 404 // will already have been done). |
| 318 if (!this.error_) | 405 if (!this.error_) |
| 319 return; | 406 return; |
| 320 | 407 |
| 321 this.codeDiv_.innerHTML = ''; | 408 this.codeDiv_.innerHTML = ''; |
| 322 this.openDevtoolsButton_.hidden = true; | 409 this.openDevtoolsButton_.hidden = true; |
| 323 | 410 |
| 324 if (this.error_.type == ExtensionErrorOverlay.RUNTIME_ERROR_TYPE_) { | 411 if (this.error_.type == ExtensionErrorOverlay.RUNTIME_ERROR_TYPE_) { |
| 325 this.overlayDiv_.querySelector('.content-area').removeChild( | 412 this.overlayDiv_.querySelector('.content-area').removeChild( |
| 326 this.runtimeErrorContent_); | 413 this.runtimeErrorContent_); |
| 327 this.runtimeErrorContent_.clearError(); | 414 this.runtimeErrorContent_.clearError(); |
| 328 } | 415 } |
| 329 | 416 |
| 330 this.error_ = undefined; | 417 this.error_ = undefined; |
| 331 }, | 418 }, |
| 332 | 419 |
| 333 /** | 420 /** |
| 334 * Associate an error with the overlay. This will set the error for the | 421 * Associate an error with the overlay. This will set the error for the |
| 335 * overlay, and, if possible, will populate the code section of the overlay | 422 * overlay, and, if possible, will populate the code section of the overlay |
| 336 * with the relevant file, load the stack trace, and generate links for | 423 * with the relevant file, load the stack trace, and generate links for |
| 337 * opening devtools (the latter two only happen for runtime errors). | 424 * opening devtools (the latter two only happen for runtime errors). |
| 338 * @param {Object} error The error to show in the overlay. | 425 * @param {Object} error The error to show in the overlay. |
| 426 * @param {string} extensionUrl The URL of the extension, in the form |
| 427 * "chrome-extension://<extension_id>". |
| 339 */ | 428 */ |
| 340 setError: function(error) { | 429 setErrorAndShowOverlay: function(error, extensionUrl) { |
| 341 this.error_ = error; | 430 this.error_ = error; |
| 342 | 431 |
| 343 if (this.error_.type == ExtensionErrorOverlay.RUNTIME_ERROR_TYPE_) { | 432 if (this.error_.type == ExtensionErrorOverlay.RUNTIME_ERROR_TYPE_) { |
| 344 this.runtimeErrorContent_.setError(this.error_); | 433 this.runtimeErrorContent_.setError(this.error_, extensionUrl); |
| 345 this.overlayDiv_.querySelector('.content-area').insertBefore( | 434 this.overlayDiv_.querySelector('.content-area').insertBefore( |
| 346 this.runtimeErrorContent_, | 435 this.runtimeErrorContent_, |
| 347 this.codeDiv_.nextSibling); | 436 this.codeDiv_.nextSibling); |
| 348 this.openDevtoolsButton_.hidden = false; | 437 this.openDevtoolsButton_.hidden = false; |
| 349 this.openDevtoolsButton_.disabled = !error.canInspect; | 438 this.openDevtoolsButton_.disabled = !error.canInspect; |
| 350 } | 439 } |
| 440 |
| 441 if (ExtensionErrorOverlay.canLoadFileSource(error.source, extensionUrl)) { |
| 442 var relativeUrl = getRelativeUrl(error.source, extensionUrl); |
| 443 |
| 444 var requestFileSourceArgs = {extensionId: error.extensionId, |
| 445 message: error.message, |
| 446 pathSuffix: relativeUrl}; |
| 447 |
| 448 if (relativeUrl.toLowerCase() == |
| 449 ExtensionErrorOverlay.MANIFEST_FILENAME_) { |
| 450 requestFileSourceArgs.manifestKey = error.manifestKey; |
| 451 requestFileSourceArgs.manifestSpecific = error.manifestSpecific; |
| 452 } else { |
| 453 requestFileSourceArgs.lineNumber = |
| 454 error.stackTrace && error.stackTrace[0] ? |
| 455 error.stackTrace[0].lineNumber : 0; |
| 456 } |
| 457 ExtensionErrorOverlay.requestFileSource(requestFileSourceArgs); |
| 458 } else { |
| 459 ExtensionErrorOverlay.requestFileSourceResponse(null); |
| 460 } |
| 351 }, | 461 }, |
| 352 | 462 |
| 353 /** | 463 /** |
| 354 * Set the code to be displayed in the code portion of the overlay. | 464 * Set the code to be displayed in the code portion of the overlay. |
| 355 * @see ExtensionErrorOverlay.requestFileSourceResponse(). | 465 * @see ExtensionErrorOverlay.requestFileSourceResponse(). |
| 356 * @param {?Object} code The code to be displayed. If |code| is null, then | 466 * @param {?Object} code The code to be displayed. If |code| is null, then |
| 357 * a "Could not display code" message will be displayed instead. | 467 * a "Could not display code" message will be displayed instead. |
| 358 */ | 468 */ |
| 359 setCode: function(code) { | 469 setCode: function(code) { |
| 360 document.querySelector( | 470 document.querySelector( |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 396 /** | 506 /** |
| 397 * Called by the ExtensionErrorHandler responding to the request for a file's | 507 * Called by the ExtensionErrorHandler responding to the request for a file's |
| 398 * source. Populate the content area of the overlay and display the overlay. | 508 * source. Populate the content area of the overlay and display the overlay. |
| 399 * @param {Object?} result An object with four strings - the title, | 509 * @param {Object?} result An object with four strings - the title, |
| 400 * beforeHighlight, afterHighlight, and highlight. The three 'highlight' | 510 * beforeHighlight, afterHighlight, and highlight. The three 'highlight' |
| 401 * strings represent three portions of the file's content to display - the | 511 * strings represent three portions of the file's content to display - the |
| 402 * portion which is most relevant and should be emphasized (highlight), | 512 * portion which is most relevant and should be emphasized (highlight), |
| 403 * and the parts both before and after this portion. These may be empty. | 513 * and the parts both before and after this portion. These may be empty. |
| 404 */ | 514 */ |
| 405 ExtensionErrorOverlay.requestFileSourceResponse = function(result) { | 515 ExtensionErrorOverlay.requestFileSourceResponse = function(result) { |
| 406 extensions.ExtensionErrorOverlay.getInstance().setCode(result); | 516 var overlay = extensions.ExtensionErrorOverlay.getInstance(); |
| 407 extensions.ExtensionSettings.showOverlay($('extension-error-overlay')); | 517 overlay.setCode(result); |
| 518 overlay.setVisible(true); |
| 408 }; | 519 }; |
| 409 | 520 |
| 410 // Export | 521 // Export |
| 411 return { | 522 return { |
| 412 ExtensionErrorOverlay: ExtensionErrorOverlay | 523 ExtensionErrorOverlay: ExtensionErrorOverlay |
| 413 }; | 524 }; |
| 414 }); | 525 }); |
| OLD | NEW |