Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(459)

Side by Side Diff: chrome/browser/resources/extensions/extension_error_overlay.js

Issue 1016413004: [Extensions] Update Error Console UI (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 * Clear all the content of a given element. 9 * Clear all the content of a given element.
10 * @param {HTMLElement} element The element to be cleared. 10 * @param {HTMLElement} element The element to be cleared.
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 assert(this.contextUrl_); 109 assert(this.contextUrl_);
110 }, 110 },
111 111
112 /** 112 /**
113 * Sets the error for the content. 113 * Sets the error for the content.
114 * @param {(RuntimeError|ManifestError)} error The error whose content 114 * @param {(RuntimeError|ManifestError)} error The error whose content
115 * should be displayed. 115 * should be displayed.
116 * @param {string} extensionUrl The URL associated with this extension. 116 * @param {string} extensionUrl The URL associated with this extension.
117 */ 117 */
118 setError: function(error, extensionUrl) { 118 setError: function(error, extensionUrl) {
119 this.clearError();
120
119 this.error_ = error; 121 this.error_ = error;
120 this.extensionUrl_ = extensionUrl; 122 this.extensionUrl_ = extensionUrl;
121 this.contextUrl_.textContent = error.contextUrl ? 123 this.contextUrl_.textContent = error.contextUrl ?
122 getRelativeUrl(error.contextUrl, this.extensionUrl_) : 124 getRelativeUrl(error.contextUrl, this.extensionUrl_) :
123 loadTimeData.getString('extensionErrorOverlayContextUnknown'); 125 loadTimeData.getString('extensionErrorOverlayContextUnknown');
124 this.initStackTrace_(); 126 this.initStackTrace_();
125 }, 127 },
126 128
127 /** 129 /**
128 * Wipe content associated with a specific error. 130 * Wipe content associated with a specific error.
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 /** 241 /**
240 * The content section for runtime errors; this is re-used for all 242 * The content section for runtime errors; this is re-used for all
241 * runtime errors and attached/detached from the overlay as needed. 243 * runtime errors and attached/detached from the overlay as needed.
242 * @type {RuntimeErrorContent} 244 * @type {RuntimeErrorContent}
243 * @private 245 * @private
244 */ 246 */
245 this.runtimeErrorContent_ = new RuntimeErrorContent(); 247 this.runtimeErrorContent_ = new RuntimeErrorContent();
246 } 248 }
247 249
248 /** 250 /**
249 * Value of ExtensionError::RUNTIME_ERROR enum.
250 * @see extensions/browser/extension_error.h
251 * @type {number}
252 * @const
253 * @private
254 */
255 ExtensionErrorOverlay.RUNTIME_ERROR_TYPE_ = 1;
256
257 /**
258 * The manifest filename. 251 * The manifest filename.
259 * @type {string} 252 * @type {string}
260 * @const 253 * @const
261 * @private 254 * @private
262 */ 255 */
263 ExtensionErrorOverlay.MANIFEST_FILENAME_ = 'manifest.json'; 256 ExtensionErrorOverlay.MANIFEST_FILENAME_ = 'manifest.json';
264 257
265 /** 258 /**
266 * Determine whether or not chrome can load the source for a given file; this 259 * Determine whether or not chrome can load the source for a given file; this
267 * can only be done if the file belongs to the extension. 260 * can only be done if the file belongs to the extension.
268 * @param {string} file The file to load. 261 * @param {string} file The file to load.
269 * @param {string} extensionUrl The url for the extension, in the form 262 * @param {string} extensionUrl The url for the extension, in the form
270 * chrome-extension://<extension-id>/. 263 * chrome-extension://<extension-id>/.
271 * @return {boolean} True if the file can be loaded, false otherwise. 264 * @return {boolean} True if the file can be loaded, false otherwise.
272 * @private 265 * @private
273 */ 266 */
274 ExtensionErrorOverlay.canLoadFileSource = function(file, extensionUrl) { 267 ExtensionErrorOverlay.canLoadFileSource = function(file, extensionUrl) {
275 return file.substr(0, extensionUrl.length) == extensionUrl || 268 return file.substr(0, extensionUrl.length) == extensionUrl ||
276 file.toLowerCase() == ExtensionErrorOverlay.MANIFEST_FILENAME_; 269 file.toLowerCase() == ExtensionErrorOverlay.MANIFEST_FILENAME_;
277 }; 270 };
278 271
279 /**
280 * Determine whether or not we can show an overlay with more details for
281 * the given extension error.
282 * @param {Object} error The extension error.
283 * @param {string} extensionUrl The url for the extension, in the form
284 * "chrome-extension://<extension-id>/".
285 * @return {boolean} True if we can show an overlay for the error,
286 * false otherwise.
287 */
288 ExtensionErrorOverlay.canShowOverlayForError = function(error, extensionUrl) {
289 if (ExtensionErrorOverlay.canLoadFileSource(error.source, extensionUrl))
290 return true;
291
292 if (error.stackTrace) {
293 for (var i = 0; i < error.stackTrace.length; ++i) {
294 if (RuntimeErrorContent.shouldDisplayForUrl(error.stackTrace[i].url))
295 return true;
296 }
297 }
298
299 return false;
300 };
301
302 cr.addSingletonGetter(ExtensionErrorOverlay); 272 cr.addSingletonGetter(ExtensionErrorOverlay);
303 273
304 ExtensionErrorOverlay.prototype = { 274 ExtensionErrorOverlay.prototype = {
305 /** 275 /**
306 * The underlying error whose details are being displayed. 276 * The underlying error whose details are being displayed.
307 * @type {?(RuntimeError|ManifestError)} 277 * @type {?(RuntimeError|ManifestError)}
308 * @private 278 * @private
309 */ 279 */
310 error_: null, 280 selectedError_: null,
311 281
312 /** 282 /**
313 * Initialize the page. 283 * Initialize the page.
314 * @param {function(HTMLDivElement)} showOverlay The function to show or 284 * @param {function(HTMLDivElement)} showOverlay The function to show or
315 * hide the ExtensionErrorOverlay; this should take a single parameter 285 * hide the ExtensionErrorOverlay; this should take a single parameter
316 * which is either the overlay Div if the overlay should be displayed, 286 * which is either the overlay Div if the overlay should be displayed,
317 * or null if the overlay should be hidden. 287 * or null if the overlay should be hidden.
318 */ 288 */
319 initializePage: function(showOverlay) { 289 initializePage: function(showOverlay) {
320 var overlay = $('overlay'); 290 var overlay = $('overlay');
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
369 * Handles a click on the dismiss ("OK" or close) buttons. 339 * Handles a click on the dismiss ("OK" or close) buttons.
370 * @param {Event} e The click event. 340 * @param {Event} e The click event.
371 * @private 341 * @private
372 */ 342 */
373 handleDismiss_: function(e) { 343 handleDismiss_: function(e) {
374 this.setVisible(false); 344 this.setVisible(false);
375 345
376 // There's a chance that the overlay receives multiple dismiss events; in 346 // There's a chance that the overlay receives multiple dismiss events; in
377 // this case, handle it gracefully and return (since all necessary work 347 // this case, handle it gracefully and return (since all necessary work
378 // will already have been done). 348 // will already have been done).
379 if (!this.error_) 349 if (!this.selectedError_)
380 return; 350 return;
381 351
382 // Remove all previous content. 352 // Remove all previous content.
383 this.codeDiv_.clear(); 353 this.codeDiv_.clear();
384 354
385 this.openDevtoolsButton_.hidden = true; 355 this.overlayDiv_.querySelector('.extension-error-list').onRemoved();
386 356
387 if (this.error_.type == ExtensionErrorOverlay.RUNTIME_ERROR_TYPE_) { 357 this.clearRuntimeContent_();
388 this.overlayDiv_.querySelector('.content-area').removeChild( 358
359 this.selectedError_ = null;
360 },
361
362 /**
363 * Clears the current content.
364 * @private
365 */
366 clearRuntimeContent_: function() {
367 if (this.runtimeErrorContent_.parentNode) {
368 this.runtimeErrorContent_.parentNode.removeChild(
389 this.runtimeErrorContent_); 369 this.runtimeErrorContent_);
390 this.runtimeErrorContent_.clearError(); 370 this.runtimeErrorContent_.clearError();
391 } 371 }
392 372 this.openDevtoolsButton_.hidden = true;
393 this.error_ = null;
394 }, 373 },
395 374
396 /** 375 /**
397 * Associate an error with the overlay. This will set the error for the 376 * Sets the active error for the overlay.
398 * overlay, and, if possible, will populate the code section of the overlay 377 * @param {?(ManifestError|RuntimeError)} error The error to make active.
399 * with the relevant file, load the stack trace, and generate links for
400 * opening devtools (the latter two only happen for runtime errors).
401 * @param {(RuntimeError|ManifestError)} error The error to show in the
402 * overlay.
403 * @param {string} extensionUrl The URL of the extension, in the form
404 * "chrome-extension://<extension_id>".
405 * TODO(dbeam): add URL externs and re-enable typechecking in this method. 378 * TODO(dbeam): add URL externs and re-enable typechecking in this method.
406 * @suppress {missingProperties} 379 * @suppress {missingProperties}
380 * @private
407 */ 381 */
408 setErrorAndShowOverlay: function(error, extensionUrl) { 382 setActiveError_: function(error) {
409 this.error_ = error; 383 this.selectedError_ = error;
410 384
411 if (this.error_.type == ExtensionErrorOverlay.RUNTIME_ERROR_TYPE_) { 385 // If there is no error (this can happen if, e.g., the user deleted all
412 this.runtimeErrorContent_.setError(this.error_, extensionUrl); 386 // the errors), then clear the content.
387 if (!error) {
388 this.codeDiv_.populate(
389 null, loadTimeData.getString('extensionErrorNoErrorsCodeMessage'));
390 this.clearRuntimeContent_();
391 return;
392 }
393
394 var extensionUrl = 'chrome-extension://' + error.extensionId + '/';
395 // Set or hide runtime content.
396 if (error.type == chrome.developerPrivate.ErrorType.RUNTIME) {
397 this.runtimeErrorContent_.setError(error, extensionUrl);
413 this.overlayDiv_.querySelector('.content-area').insertBefore( 398 this.overlayDiv_.querySelector('.content-area').insertBefore(
414 this.runtimeErrorContent_, 399 this.runtimeErrorContent_,
415 this.codeDiv_.nextSibling); 400 this.codeDiv_.nextSibling);
416 this.openDevtoolsButton_.hidden = false; 401 this.openDevtoolsButton_.hidden = false;
417 this.openDevtoolsButton_.disabled = !error.canInspect; 402 this.openDevtoolsButton_.disabled = !error.canInspect;
403 } else {
404 this.clearRuntimeContent_();
418 } 405 }
419 406
407 // Read the file source to populate the code section, or set it to null if
408 // the file is unreadable.
420 if (ExtensionErrorOverlay.canLoadFileSource(error.source, extensionUrl)) { 409 if (ExtensionErrorOverlay.canLoadFileSource(error.source, extensionUrl)) {
421 // slice(1) because pathname starts with a /.
422 var pathname = new URL(error.source).pathname.slice(1);
423
424 // Use pathname instead of relativeUrl. 410 // Use pathname instead of relativeUrl.
425 var requestFileSourceArgs = {extensionId: error.extensionId, 411 var requestFileSourceArgs = {extensionId: error.extensionId,
426 message: error.message, 412 message: error.message};
427 pathSuffix: pathname}; 413 switch (error.type) {
428 414 case chrome.developerPrivate.ErrorType.MANIFEST:
429 if (pathname.toLowerCase() == 415 requestFileSourceArgs.pathSuffix = error.source;
430 ExtensionErrorOverlay.MANIFEST_FILENAME_) { 416 requestFileSourceArgs.manifestKey = error.manifestKey;
431 requestFileSourceArgs.manifestKey = error.manifestKey; 417 requestFileSourceArgs.manifestSpecific = error.manifestSpecific;
432 requestFileSourceArgs.manifestSpecific = error.manifestSpecific; 418 break;
433 } else { 419 case chrome.developerPrivate.ErrorType.RUNTIME:
434 requestFileSourceArgs.lineNumber = 420 // slice(1) because pathname starts with a /.
435 error.stackTrace && error.stackTrace[0] ? 421 var pathname = new URL(error.source).pathname.slice(1);
436 error.stackTrace[0].lineNumber : 0; 422 requestFileSourceArgs.pathSuffix = pathname;
423 requestFileSourceArgs.lineNumber =
424 error.stackTrace && error.stackTrace[0] ?
425 error.stackTrace[0].lineNumber : 0;
426 break;
427 default:
428 assertNotReached();
437 } 429 }
438 this.requestFileSource(requestFileSourceArgs); 430 this.requestFileSource(requestFileSourceArgs);
439 } else { 431 } else {
440 this.onFileSourceResponse_(null); 432 this.onFileSourceResponse_(null);
441 } 433 }
442 }, 434 },
443 435
444 /** 436 /**
437 * Associate an error with the overlay. This will set the error for the
438 * overlay, and, if possible, will populate the code section of the overlay
439 * with the relevant file, load the stack trace, and generate links for
440 * opening devtools (the latter two only happen for runtime errors).
441 * @param {Array<(RuntimeError|ManifestError)>} errors The error to show in
442 * the overlay.
443 * @param {string} extensionId The id of the extension.
444 * @param {string} extensionName The name of the extension.
445 */
446 setErrorsAndShowOverlay: function(errors, extensionId, extensionName) {
447 document.querySelector(
448 '#extension-error-overlay .extension-error-overlay-title').
449 textContent = extensionName;
450 var errorsDiv = this.overlayDiv_.querySelector('.extension-error-list');
451 var extensionErrors =
452 new extensions.ExtensionErrorList(errors, extensionId);
453 errorsDiv.parentNode.replaceChild(extensionErrors, errorsDiv);
454 extensionErrors.addEventListener('activeExtensionErrorChanged',
455 function(e) {
456 this.setActiveError_(e.detail);
457 }.bind(this));
458
459 if (errors.length > 0)
460 this.setActiveError_(errors[0]);
461 this.setVisible(true);
462 },
463
464 /**
445 * Requests a file's source. 465 * Requests a file's source.
446 * @param {RequestFileSourceProperties} args The arguments for the call. 466 * @param {RequestFileSourceProperties} args The arguments for the call.
447 */ 467 */
448 requestFileSource: function(args) { 468 requestFileSource: function(args) {
449 chrome.developerPrivate.requestFileSource( 469 chrome.developerPrivate.requestFileSource(
450 args, this.onFileSourceResponse_.bind(this)); 470 args, this.onFileSourceResponse_.bind(this));
451 }, 471 },
452 472
453 /** 473 /**
454 * Set the code to be displayed in the code portion of the overlay. 474 * Set the code to be displayed in the code portion of the overlay.
455 * @see ExtensionErrorOverlay.requestFileSourceResponse(). 475 * @see ExtensionErrorOverlay.requestFileSourceResponse().
456 * @param {?RequestFileSourceResponse} response The response from the 476 * @param {?RequestFileSourceResponse} response The response from the
457 * request file source call, which will be shown as code. If |response| 477 * request file source call, which will be shown as code. If |response|
458 * is null, then a "Could not display code" message will be displayed 478 * is null, then a "Could not display code" message will be displayed
459 * instead. 479 * instead.
460 */ 480 */
461 onFileSourceResponse_: function(response) { 481 onFileSourceResponse_: function(response) {
462 if (response) {
463 document.querySelector(
464 '#extension-error-overlay .extension-error-overlay-title').
465 textContent = response.title;
466 }
467 this.codeDiv_.populate( 482 this.codeDiv_.populate(
468 response, // ExtensionCode can handle a null response. 483 response, // ExtensionCode can handle a null response.
469 loadTimeData.getString('extensionErrorOverlayNoCodeToDisplay')); 484 loadTimeData.getString('extensionErrorOverlayNoCodeToDisplay'));
470 this.setVisible(true); 485 this.setVisible(true);
471 }, 486 },
472 }; 487 };
473 488
474 // Export 489 // Export
475 return { 490 return {
476 ExtensionErrorOverlay: ExtensionErrorOverlay 491 ExtensionErrorOverlay: ExtensionErrorOverlay
477 }; 492 };
478 }); 493 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698