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

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

Issue 512003002: Revert of Revert "Typecheck JS files for chrome://extensions" (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 3 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 /**
6 * The type of the stack trace object. The definition is based on
7 * extensions/browser/extension_error.cc:RuntimeError::ToValue().
8 * @typedef {{columnNumber: number,
9 * functionName: string,
10 * lineNumber: number,
11 * url: string}}
12 */
13 var StackTrace;
14
15 /**
16 * The type of the extension error trace object. The definition is based on
17 * extensions/browser/extension_error.cc:RuntimeError::ToValue().
18 * @typedef {{canInspect: (boolean|undefined),
19 * contextUrl: (string|undefined),
20 * extensionId: string,
21 * fromIncognito: boolean,
22 * level: number,
23 * manifestKey: string,
24 * manifestSpecific: string,
25 * message: string,
26 * renderProcessId: (number|undefined),
27 * renderViewId: (number|undefined),
28 * source: string,
29 * stackTrace: (Array.<StackTrace>|undefined),
30 * type: number}}
31 */
32 var RuntimeError;
33
5 cr.define('extensions', function() { 34 cr.define('extensions', function() {
6 'use strict'; 35 'use strict';
7 36
8 /** 37 /**
9 * Clear all the content of a given element. 38 * Clear all the content of a given element.
10 * @param {HTMLElement} element The element to be cleared. 39 * @param {HTMLElement} element The element to be cleared.
11 */ 40 */
12 function clearElement(element) { 41 function clearElement(element) {
13 while (element.firstChild) 42 while (element.firstChild)
14 element.removeChild(element.firstChild); 43 element.removeChild(element.firstChild);
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
78 chrome.developerPrivate.openDevTools(args); 107 chrome.developerPrivate.openDevTools(args);
79 else 108 else
80 assertNotReached('Cannot call either openDevTools function.'); 109 assertNotReached('Cannot call either openDevTools function.');
81 }; 110 };
82 111
83 RuntimeErrorContent.prototype = { 112 RuntimeErrorContent.prototype = {
84 __proto__: HTMLDivElement.prototype, 113 __proto__: HTMLDivElement.prototype,
85 114
86 /** 115 /**
87 * The underlying error whose details are being displayed. 116 * The underlying error whose details are being displayed.
88 * @type {Object} 117 * @type {?RuntimeError}
89 * @private 118 * @private
90 */ 119 */
91 error_: undefined, 120 error_: null,
92 121
93 /** 122 /**
94 * The URL associated with this extension, i.e. chrome-extension://<id>/. 123 * The URL associated with this extension, i.e. chrome-extension://<id>/.
95 * @type {string} 124 * @type {?string}
96 * @private 125 * @private
97 */ 126 */
98 extensionUrl_: undefined, 127 extensionUrl_: null,
99 128
100 /** 129 /**
101 * The node of the stack trace which is currently active. 130 * The node of the stack trace which is currently active.
102 * @type {HTMLElement} 131 * @type {?HTMLElement}
103 * @private 132 * @private
104 */ 133 */
105 currentFrameNode_: undefined, 134 currentFrameNode_: null,
106 135
107 /** 136 /**
108 * Initialize the RuntimeErrorContent for the first time. 137 * Initialize the RuntimeErrorContent for the first time.
109 */ 138 */
110 init: function() { 139 init: function() {
111 /** 140 /**
112 * The stack trace element in the overlay. 141 * The stack trace element in the overlay.
113 * @type {HTMLElement} 142 * @type {HTMLElement}
114 * @private 143 * @private
115 */ 144 */
116 this.stackTrace_ = 145 this.stackTrace_ = /** @type {HTMLElement} */(
117 this.querySelector('.extension-error-overlay-stack-trace-list'); 146 this.querySelector('.extension-error-overlay-stack-trace-list'));
118 assert(this.stackTrace_); 147 assert(this.stackTrace_);
119 148
120 /** 149 /**
121 * The context URL element in the overlay. 150 * The context URL element in the overlay.
122 * @type {HTMLElement} 151 * @type {HTMLElement}
123 * @private 152 * @private
124 */ 153 */
125 this.contextUrl_ = 154 this.contextUrl_ = /** @type {HTMLElement} */(
126 this.querySelector('.extension-error-overlay-context-url'); 155 this.querySelector('.extension-error-overlay-context-url'));
127 assert(this.contextUrl_); 156 assert(this.contextUrl_);
128 }, 157 },
129 158
130 /** 159 /**
131 * Sets the error for the content. 160 * Sets the error for the content.
132 * @param {Object} error The error whose content should be displayed. 161 * @param {RuntimeError} error The error whose content should
162 * be displayed.
133 * @param {string} extensionUrl The URL associated with this extension. 163 * @param {string} extensionUrl The URL associated with this extension.
134 */ 164 */
135 setError: function(error, extensionUrl) { 165 setError: function(error, extensionUrl) {
136 this.error_ = error; 166 this.error_ = error;
137 this.extensionUrl_ = extensionUrl; 167 this.extensionUrl_ = extensionUrl;
138 this.contextUrl_.textContent = error.contextUrl ? 168 this.contextUrl_.textContent = error.contextUrl ?
139 getRelativeUrl(error.contextUrl, this.extensionUrl_) : 169 getRelativeUrl(error.contextUrl, this.extensionUrl_) :
140 loadTimeData.getString('extensionErrorOverlayContextUnknown'); 170 loadTimeData.getString('extensionErrorOverlayContextUnknown');
141 this.initStackTrace_(); 171 this.initStackTrace_();
142 }, 172 },
143 173
144 /** 174 /**
145 * Wipe content associated with a specific error. 175 * Wipe content associated with a specific error.
146 */ 176 */
147 clearError: function() { 177 clearError: function() {
148 this.error_ = undefined; 178 this.error_ = null;
149 this.extensionUrl_ = undefined; 179 this.extensionUrl_ = null;
150 this.currentFrameNode_ = undefined; 180 this.currentFrameNode_ = null;
151 clearElement(this.stackTrace_); 181 clearElement(this.stackTrace_);
152 this.stackTrace_.hidden = true; 182 this.stackTrace_.hidden = true;
153 }, 183 },
154 184
155 /** 185 /**
156 * Makes |frame| active and deactivates the previously active frame (if 186 * Makes |frame| active and deactivates the previously active frame (if
157 * there was one). 187 * there was one).
158 * @param {HTMLElement} frame The frame to activate. 188 * @param {HTMLElement} frameNode The frame to activate.
159 * @private 189 * @private
160 */ 190 */
161 setActiveFrame_: function(frameNode) { 191 setActiveFrame_: function(frameNode) {
162 if (this.currentFrameNode_) { 192 if (this.currentFrameNode_) {
163 this.currentFrameNode_.classList.remove( 193 this.currentFrameNode_.classList.remove(
164 RuntimeErrorContent.ACTIVE_CLASS_NAME); 194 RuntimeErrorContent.ACTIVE_CLASS_NAME);
165 } 195 }
166 196
167 this.currentFrameNode_ = frameNode; 197 this.currentFrameNode_ = frameNode;
168 this.currentFrameNode_.classList.add( 198 this.currentFrameNode_.classList.add(
(...skipping 13 matching lines...) Expand all
182 continue; 212 continue;
183 213
184 var frameNode = document.createElement('li'); 214 var frameNode = document.createElement('li');
185 // Attach the index of the frame to which this node refers (since we 215 // Attach the index of the frame to which this node refers (since we
186 // may skip some, this isn't a 1-to-1 match). 216 // may skip some, this isn't a 1-to-1 match).
187 frameNode.indexIntoTrace = i; 217 frameNode.indexIntoTrace = i;
188 218
189 // The description is a human-readable summation of the frame, in the 219 // The description is a human-readable summation of the frame, in the
190 // form "<relative_url>:<line_number> (function)", e.g. 220 // form "<relative_url>:<line_number> (function)", e.g.
191 // "myfile.js:25 (myFunction)". 221 // "myfile.js:25 (myFunction)".
192 var description = getRelativeUrl(frame.url, this.extensionUrl_) + 222 var description = getRelativeUrl(frame.url,
193 ':' + frame.lineNumber; 223 assert(this.extensionUrl_)) + ':' + frame.lineNumber;
194 if (frame.functionName) { 224 if (frame.functionName) {
195 var functionName = frame.functionName == '(anonymous function)' ? 225 var functionName = frame.functionName == '(anonymous function)' ?
196 loadTimeData.getString('extensionErrorOverlayAnonymousFunction') : 226 loadTimeData.getString('extensionErrorOverlayAnonymousFunction') :
197 frame.functionName; 227 frame.functionName;
198 description += ' (' + functionName + ')'; 228 description += ' (' + functionName + ')';
199 } 229 }
200 frameNode.textContent = description; 230 frameNode.textContent = description;
201 231
202 // When the user clicks on a frame in the stack trace, we should 232 // When the user clicks on a frame in the stack trace, we should
203 // highlight that overlay in the list, display the appropriate source 233 // highlight that overlay in the list, display the appropriate source
204 // code with the line highlighted, and link the "Open DevTools" button 234 // code with the line highlighted, and link the "Open DevTools" button
205 // with that frame. 235 // with that frame.
206 frameNode.addEventListener('click', function(frame, frameNode, e) { 236 frameNode.addEventListener('click', function(frame, frameNode, e) {
207 if (this.currStackFrame_ == frameNode)
208 return;
209
210 this.setActiveFrame_(frameNode); 237 this.setActiveFrame_(frameNode);
211 238
212 // Request the file source with the section highlighted; this will 239 // Request the file source with the section highlighted; this will
213 // call ExtensionErrorOverlay.requestFileSourceResponse() when 240 // call ExtensionErrorOverlay.requestFileSourceResponse() when
214 // completed, which in turn calls setCode(). 241 // completed, which in turn calls setCode().
215 ExtensionErrorOverlay.requestFileSource( 242 ExtensionErrorOverlay.requestFileSource(
216 {extensionId: this.error_.extensionId, 243 {extensionId: this.error_.extensionId,
217 message: this.error_.message, 244 message: this.error_.message,
218 pathSuffix: getRelativeUrl(frame.url, this.extensionUrl_), 245 pathSuffix: getRelativeUrl(frame.url, this.extensionUrl_),
219 lineNumber: frame.lineNumber}); 246 lineNumber: frame.lineNumber});
220 }.bind(this, frame, frameNode)); 247 }.bind(this, frame, frameNode));
221 248
222 this.stackTrace_.appendChild(frameNode); 249 this.stackTrace_.appendChild(frameNode);
223 } 250 }
224 251
225 // Set the current stack frame to the first stack frame and show the 252 // Set the current stack frame to the first stack frame and show the
226 // trace, if one exists. (We can't just check error.stackTrace, because 253 // trace, if one exists. (We can't just check error.stackTrace, because
227 // it's possible the trace was purely internal, and we don't show 254 // it's possible the trace was purely internal, and we don't show
228 // internal frames.) 255 // internal frames.)
229 if (this.stackTrace_.children.length > 0) { 256 if (this.stackTrace_.children.length > 0) {
230 this.stackTrace_.hidden = false; 257 this.stackTrace_.hidden = false;
231 this.setActiveFrame_(this.stackTrace_.firstChild); 258 this.setActiveFrame_(assertInstanceof(this.stackTrace_.firstChild,
259 HTMLElement));
232 } 260 }
233 }, 261 },
234 262
235 /** 263 /**
236 * Open the developer tools for the active stack frame. 264 * Open the developer tools for the active stack frame.
237 */ 265 */
238 openDevtools: function() { 266 openDevtools: function() {
239 var stackFrame = 267 var stackFrame =
240 this.error_.stackTrace[this.currentFrameNode_.indexIntoTrace]; 268 this.error_.stackTrace[this.currentFrameNode_.indexIntoTrace];
241 269
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 } else { 365 } else {
338 assertNotReached('Cannot call either requestFileSource function.'); 366 assertNotReached('Cannot call either requestFileSource function.');
339 } 367 }
340 }; 368 };
341 369
342 cr.addSingletonGetter(ExtensionErrorOverlay); 370 cr.addSingletonGetter(ExtensionErrorOverlay);
343 371
344 ExtensionErrorOverlay.prototype = { 372 ExtensionErrorOverlay.prototype = {
345 /** 373 /**
346 * The underlying error whose details are being displayed. 374 * The underlying error whose details are being displayed.
347 * @type {Object} 375 * @type {?RuntimeError}
348 * @private 376 * @private
349 */ 377 */
350 error_: undefined, 378 error_: null,
351 379
352 /** 380 /**
353 * Initialize the page. 381 * Initialize the page.
354 * @param {function(HTMLDivElement)} showOverlay The function to show or 382 * @param {function(HTMLDivElement)} showOverlay The function to show or
355 * hide the ExtensionErrorOverlay; this should take a single parameter 383 * hide the ExtensionErrorOverlay; this should take a single parameter
356 * which is either the overlay Div if the overlay should be displayed, 384 * which is either the overlay Div if the overlay should be displayed,
357 * or null if the overlay should be hidden. 385 * or null if the overlay should be hidden.
358 */ 386 */
359 initializePage: function(showOverlay) { 387 initializePage: function(showOverlay) {
360 var overlay = $('overlay'); 388 var overlay = $('overlay');
361 cr.ui.overlay.setupOverlay(overlay); 389 cr.ui.overlay.setupOverlay(overlay);
362 cr.ui.overlay.globalInitialization(); 390 cr.ui.overlay.globalInitialization();
363 overlay.addEventListener('cancelOverlay', this.handleDismiss_.bind(this)); 391 overlay.addEventListener('cancelOverlay', this.handleDismiss_.bind(this));
364 392
365 $('extension-error-overlay-dismiss').addEventListener( 393 $('extension-error-overlay-dismiss').addEventListener(
366 'click', this.handleDismiss_.bind(this)); 394 'click', this.handleDismiss_.bind(this));
367 395
368 /** 396 /**
369 * The element of the full overlay. 397 * The element of the full overlay.
370 * @type {HTMLDivElement} 398 * @type {HTMLDivElement}
371 * @private 399 * @private
372 */ 400 */
373 this.overlayDiv_ = $('extension-error-overlay'); 401 this.overlayDiv_ = /** @type {HTMLDivElement} */(
402 $('extension-error-overlay'));
374 403
375 /** 404 /**
376 * The portion of the overlay which shows the code relating to the error 405 * The portion of the overlay which shows the code relating to the error
377 * and the corresponding line numbers. 406 * and the corresponding line numbers.
378 * @type {ExtensionCode} 407 * @type {extensions.ExtensionCode}
379 * @private 408 * @private
380 */ 409 */
381 this.codeDiv_ = 410 this.codeDiv_ =
382 new extensions.ExtensionCode($('extension-error-overlay-code')); 411 new extensions.ExtensionCode($('extension-error-overlay-code'));
383 412
384 /** 413 /**
385 * The function to show or hide the ExtensionErrorOverlay. 414 * The function to show or hide the ExtensionErrorOverlay.
386 * @type {function}
387 * @param {boolean} isVisible Whether the overlay should be visible. 415 * @param {boolean} isVisible Whether the overlay should be visible.
388 */ 416 */
389 this.setVisible = function(isVisible) { 417 this.setVisible = function(isVisible) {
390 showOverlay(isVisible ? this.overlayDiv_ : null); 418 showOverlay(isVisible ? this.overlayDiv_ : null);
391 if (isVisible) 419 if (isVisible)
392 this.codeDiv_.scrollToError(); 420 this.codeDiv_.scrollToError();
393 }; 421 };
394 422
395 /** 423 /**
396 * The button to open the developer tools (only available for runtime 424 * The button to open the developer tools (only available for runtime
397 * errors). 425 * errors).
398 * @type {HTMLButtonElement} 426 * @type {HTMLButtonElement}
399 * @private 427 * @private
400 */ 428 */
401 this.openDevtoolsButton_ = $('extension-error-overlay-devtools-button'); 429 this.openDevtoolsButton_ = /** @type {HTMLButtonElement} */(
430 $('extension-error-overlay-devtools-button'));
402 this.openDevtoolsButton_.addEventListener('click', function() { 431 this.openDevtoolsButton_.addEventListener('click', function() {
403 this.runtimeErrorContent_.openDevtools(); 432 this.runtimeErrorContent_.openDevtools();
404 }.bind(this)); 433 }.bind(this));
405 }, 434 },
406 435
407 /** 436 /**
408 * Handles a click on the dismiss ("OK" or close) buttons. 437 * Handles a click on the dismiss ("OK" or close) buttons.
409 * @param {Event} e The click event. 438 * @param {Event} e The click event.
410 * @private 439 * @private
411 */ 440 */
(...skipping 10 matching lines...) Expand all
422 this.codeDiv_.clear(); 451 this.codeDiv_.clear();
423 452
424 this.openDevtoolsButton_.hidden = true; 453 this.openDevtoolsButton_.hidden = true;
425 454
426 if (this.error_.type == ExtensionErrorOverlay.RUNTIME_ERROR_TYPE_) { 455 if (this.error_.type == ExtensionErrorOverlay.RUNTIME_ERROR_TYPE_) {
427 this.overlayDiv_.querySelector('.content-area').removeChild( 456 this.overlayDiv_.querySelector('.content-area').removeChild(
428 this.runtimeErrorContent_); 457 this.runtimeErrorContent_);
429 this.runtimeErrorContent_.clearError(); 458 this.runtimeErrorContent_.clearError();
430 } 459 }
431 460
432 this.error_ = undefined; 461 this.error_ = null;
433 }, 462 },
434 463
435 /** 464 /**
436 * Associate an error with the overlay. This will set the error for the 465 * Associate an error with the overlay. This will set the error for the
437 * overlay, and, if possible, will populate the code section of the overlay 466 * overlay, and, if possible, will populate the code section of the overlay
438 * with the relevant file, load the stack trace, and generate links for 467 * with the relevant file, load the stack trace, and generate links for
439 * opening devtools (the latter two only happen for runtime errors). 468 * opening devtools (the latter two only happen for runtime errors).
440 * @param {Object} error The error to show in the overlay. 469 * @param {RuntimeError} error The error to show in the overlay.
441 * @param {string} extensionUrl The URL of the extension, in the form 470 * @param {string} extensionUrl The URL of the extension, in the form
442 * "chrome-extension://<extension_id>". 471 * "chrome-extension://<extension_id>".
443 */ 472 */
444 setErrorAndShowOverlay: function(error, extensionUrl) { 473 setErrorAndShowOverlay: function(error, extensionUrl) {
445 this.error_ = error; 474 this.error_ = error;
446 475
447 if (this.error_.type == ExtensionErrorOverlay.RUNTIME_ERROR_TYPE_) { 476 if (this.error_.type == ExtensionErrorOverlay.RUNTIME_ERROR_TYPE_) {
448 this.runtimeErrorContent_.setError(this.error_, extensionUrl); 477 this.runtimeErrorContent_.setError(this.error_, extensionUrl);
449 this.overlayDiv_.querySelector('.content-area').insertBefore( 478 this.overlayDiv_.querySelector('.content-area').insertBefore(
450 this.runtimeErrorContent_, 479 this.runtimeErrorContent_,
(...skipping 17 matching lines...) Expand all
468 requestFileSourceArgs.lineNumber = 497 requestFileSourceArgs.lineNumber =
469 error.stackTrace && error.stackTrace[0] ? 498 error.stackTrace && error.stackTrace[0] ?
470 error.stackTrace[0].lineNumber : 0; 499 error.stackTrace[0].lineNumber : 0;
471 } 500 }
472 ExtensionErrorOverlay.requestFileSource(requestFileSourceArgs); 501 ExtensionErrorOverlay.requestFileSource(requestFileSourceArgs);
473 } else { 502 } else {
474 ExtensionErrorOverlay.requestFileSourceResponse(null); 503 ExtensionErrorOverlay.requestFileSourceResponse(null);
475 } 504 }
476 }, 505 },
477 506
507
478 /** 508 /**
479 * Set the code to be displayed in the code portion of the overlay. 509 * Set the code to be displayed in the code portion of the overlay.
480 * @see ExtensionErrorOverlay.requestFileSourceResponse(). 510 * @see ExtensionErrorOverlay.requestFileSourceResponse().
481 * @param {?Object} code The code to be displayed. If |code| is null, then 511 * @param {?ExtensionHighlight} code The code to be displayed. If |code| is
512 * null, then
482 * a "Could not display code" message will be displayed instead. 513 * a "Could not display code" message will be displayed instead.
483 */ 514 */
484 setCode: function(code) { 515 setCode: function(code) {
485 document.querySelector( 516 document.querySelector(
486 '#extension-error-overlay .extension-error-overlay-title'). 517 '#extension-error-overlay .extension-error-overlay-title').
487 textContent = code.title; 518 textContent = code.title;
488 519
489 this.codeDiv_.populate( 520 this.codeDiv_.populate(
490 code, 521 code,
491 loadTimeData.getString('extensionErrorOverlayNoCodeToDisplay')); 522 loadTimeData.getString('extensionErrorOverlayNoCodeToDisplay'));
492 }, 523 },
493 }; 524 };
494 525
495 /** 526 /**
496 * Called by the ExtensionErrorHandler responding to the request for a file's 527 * Called by the ExtensionErrorHandler responding to the request for a file's
497 * source. Populate the content area of the overlay and display the overlay. 528 * source. Populate the content area of the overlay and display the overlay.
498 * @param {Object?} result An object with four strings - the title, 529 * @param {?ExtensionHighlight} result The three 'highlight' strings represent
499 * beforeHighlight, afterHighlight, and highlight. The three 'highlight' 530 * three portions of the file's content to display - the portion which is
500 * strings represent three portions of the file's content to display - the 531 * most relevant and should be emphasized (highlight), and the parts both
501 * portion which is most relevant and should be emphasized (highlight), 532 * before and after this portion. These may be empty.
502 * and the parts both before and after this portion. These may be empty.
503 */ 533 */
504 ExtensionErrorOverlay.requestFileSourceResponse = function(result) { 534 ExtensionErrorOverlay.requestFileSourceResponse = function(result) {
505 var overlay = extensions.ExtensionErrorOverlay.getInstance(); 535 var overlay = extensions.ExtensionErrorOverlay.getInstance();
506 overlay.setCode(result); 536 overlay.setCode(result);
507 overlay.setVisible(true); 537 overlay.setVisible(true);
508 }; 538 };
509 539
510 // Export 540 // Export
511 return { 541 return {
512 ExtensionErrorOverlay: ExtensionErrorOverlay 542 ExtensionErrorOverlay: ExtensionErrorOverlay
513 }; 543 };
514 }); 544 });
OLDNEW
« no previous file with comments | « chrome/browser/resources/extensions/extension_error.js ('k') | chrome/browser/resources/extensions/extension_list.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698