1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 cr
.define('extensions', function() {
9 * Construct an ExtensionLoadError around the given |div|.
10 * @param {HTMLDivElement} div The HTML div for the extension load error.
12 * @extends {HTMLDivElement}
14 function ExtensionLoadError(div
) {
15 div
.__proto__
= ExtensionLoadError
.prototype;
21 * Construct a Failure.
22 * @param {string} filePath The path to the unpacked extension.
23 * @param {string} error The reason the extension failed to load.
24 * @param {ExtensionHighlight} manifest Three 'highlight' strings in
25 * |manifest| represent three portions of the file's content to display -
26 * the portion which is most relevant and should be emphasized
27 * (highlight), and the parts both before and after this portion. These
29 * @param {HTMLLIElement} listElement The HTML element used for displaying the
30 * failure path for the additional failures UI.
32 * @extends {HTMLDivElement}
34 function Failure(filePath
, error
, manifest
, listElement
) {
37 this.manifest
= manifest
;
38 this.listElement
= listElement
;
41 ExtensionLoadError
.prototype = {
42 __proto__
: HTMLDivElement
.prototype,
45 * Initialize the ExtensionLoadError div.
49 * The element which displays the path of the extension.
53 this.path_
= /** @type {HTMLElement} */(
54 this.querySelector('#extension-load-error-path'));
57 * The element which displays the reason the extension failed to load.
61 this.reason_
= /** @type {HTMLElement} */(
62 this.querySelector('#extension-load-error-reason'));
65 * The element which displays the manifest code.
66 * @type {extensions.ExtensionCode}
69 this.manifest_
= new extensions
.ExtensionCode(
70 this.querySelector('#extension-load-error-manifest'));
73 * The element which displays information about additional errors.
77 this.additional_
= /** @type {HTMLUListElement} */(
78 this.querySelector('#extension-load-error-additional'));
79 this.additional_
.list
= this.additional_
.getElementsByTagName('ul')[0];
82 * An array of Failures for keeping track of multiple active failures.
83 * @type {Array<Failure>}
88 this.querySelector('#extension-load-error-retry-button').addEventListener(
89 'click', function(e
) {
90 chrome
.send('extensionLoaderRetry');
94 this.querySelector('#extension-load-error-give-up-button').
95 addEventListener('click', function(e
) {
96 chrome
.send('extensionLoaderIgnoreFailure');
100 chrome
.send('extensionLoaderDisplayFailures');
104 * Add a failure to failures_ array. If there is already a displayed
105 * failure, display the additional failures element.
106 * @param {Array<Object>} failures Array of failures containing paths,
107 * errors, and manifests.
110 add_: function(failures
) {
111 // If a failure is already being displayed, unhide the last item.
112 if (this.failures_
.length
> 0)
113 this.failures_
[this.failures_
.length
- 1].listElement
.hidden
= false;
114 failures
.forEach(function(failure
) {
115 var listItem
= /** @type {HTMLLIElement} */(
116 document
.createElement('li'));
117 listItem
.textContent
= failure
.path
;
118 this.additional_
.list
.appendChild(listItem
);
119 this.failures_
.push(new Failure(failure
.path
,
124 // Hide the last item because the UI is displaying its information.
125 this.failures_
[this.failures_
.length
- 1].listElement
.hidden
= true;
130 * Remove a failure from |failures_| array. If this was the last failure,
131 * hide the error UI. If this was the last additional failure, hide
132 * the additional failures UI.
135 remove_: function() {
136 this.additional_
.list
.removeChild(
137 this.failures_
[this.failures_
.length
- 1].listElement
);
138 this.failures_
.pop();
139 if (this.failures_
.length
> 0) {
140 this.failures_
[this.failures_
.length
- 1].listElement
.hidden
= true;
148 * Display the load error to the user. The last failure gets its manifest
149 * and error displayed, while additional failures have their path names
150 * displayed in the additional failures element.
154 assert(this.failures_
.length
>= 1);
155 var failure
= this.failures_
[this.failures_
.length
- 1];
156 this.path_
.textContent
= failure
.path
;
157 this.reason_
.textContent
= failure
.error
;
159 failure
.manifest
.message
= failure
.error
;
160 this.manifest_
.populate(
162 loadTimeData
.getString('extensionLoadCouldNotLoadManifest'));
164 this.manifest_
.scrollToError();
166 this.additional_
.hidden
= this.failures_
.length
== 1;
171 * The ExtensionLoader is the class in charge of loading unpacked extensions.
174 function ExtensionLoader() {
176 * The ExtensionLoadError to show any errors from loading an unpacked
178 * @type {ExtensionLoadError}
181 this.loadError_
= new ExtensionLoadError(
182 /** @type {HTMLDivElement} */($('extension-load-error')));
185 cr
.addSingletonGetter(ExtensionLoader
);
187 ExtensionLoader
.prototype = {
189 * Whether or not we are currently loading an unpacked extension.
195 * Begin the sequence of loading an unpacked extension. If an error is
196 * encountered, this object will get notified via notifyFailed().
198 loadUnpacked: function() {
199 if (this.isLoading_
) // Only one running load at a time.
201 this.isLoading_
= true;
202 chrome
.developerPrivate
.loadUnpacked({failQuietly
: true}, function() {
203 // Check lastError to avoid the log, but don't do anything with it -
204 // error-handling is done on the C++ side.
205 var lastError
= chrome
.runtime
.lastError
;
206 this.isLoading_
= false;
211 * Notify the ExtensionLoader that loading an unpacked extension failed.
212 * Add the failure to failures_ and show the ExtensionLoadError.
213 * @param {Array<Object>} failures Array of failures containing paths,
214 * errors, and manifests.
216 notifyFailed: function(failures
) {
217 this.loadError_
.add_(failures
);
222 * A static forwarding function for ExtensionLoader.notifyFailed.
223 * @param {Array<Object>} failures Array of failures containing paths,
224 * errors, and manifests.
225 * @see ExtensionLoader.notifyFailed
227 ExtensionLoader
.notifyLoadFailed = function(failures
) {
228 ExtensionLoader
.getInstance().notifyFailed(failures
);
232 ExtensionLoader
: ExtensionLoader