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