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.
4
5cr.define('extensions', function() {
6  'use strict';
7
8  /**
9   * Construct an ExtensionLoadError around the given |div|.
10   * @param {HTMLDivElement} div The HTML div for the extension load error.
11   * @constructor
12   */
13  function ExtensionLoadError(div) {
14    div.__proto__ = ExtensionLoadError.prototype;
15    div.init();
16    return div;
17  }
18
19  ExtensionLoadError.prototype = {
20    __proto__: HTMLDivElement.prototype,
21
22    /**
23     * Initialize the ExtensionLoadError div.
24     */
25    init: function() {
26      /**
27       * The element which displays the path of the extension.
28       * @type {HTMLSpanElement}
29       * @private
30       */
31      this.path_ = this.querySelector('#extension-load-error-path');
32
33      /**
34       * The element which displays the reason the extension failed to load.
35       * @type {HTMLSpanElement}
36       * @private
37       */
38      this.reason_ = this.querySelector('#extension-load-error-reason');
39
40      /**
41       * The element which displays the manifest code.
42       * @type {ExtensionCode}
43       * @private
44       */
45      this.manifest_ = new extensions.ExtensionCode(
46          this.querySelector('#extension-load-error-manifest'));
47
48      this.querySelector('#extension-load-error-retry-button').addEventListener(
49          'click', function(e) {
50        chrome.send('extensionLoaderRetry');
51        this.hide_();
52      }.bind(this));
53
54      this.querySelector('#extension-load-error-give-up-button').
55          addEventListener('click', function(e) {
56        this.hide_();
57      }.bind(this));
58    },
59
60    /**
61     * Display the load error to the user.
62     * @param {string} path The path from which the extension was loaded.
63     * @param {string} reason The reason the extension failed to load.
64     * @param {string} manifest The manifest object, with highlighted regions.
65     */
66    show: function(path, reason, manifest) {
67      this.path_.textContent = path;
68      this.reason_.textContent = reason;
69
70      manifest.message = reason;
71      this.manifest_.populate(
72          manifest,
73          loadTimeData.getString('extensionLoadCouldNotLoadManifest'));
74      this.hidden = false;
75      this.manifest_.scrollToError();
76    },
77
78    /**
79     * Hide the extension load error.
80     * @private
81     */
82    hide_: function() {
83      this.hidden = true;
84    }
85  };
86
87  /**
88   * The ExtensionLoader is the class in charge of loading unpacked extensions.
89   * @constructor
90   */
91  function ExtensionLoader() {
92    /**
93     * The ExtensionLoadError to show any errors from loading an unpacked
94     * extension.
95     * @type {ExtensionLoadError}
96     * @private
97     */
98    this.loadError_ = new ExtensionLoadError($('extension-load-error'));
99  }
100
101  cr.addSingletonGetter(ExtensionLoader);
102
103  ExtensionLoader.prototype = {
104    /**
105     * Begin the sequence of loading an unpacked extension. If an error is
106     * encountered, this object will get notified via notifyFailed().
107     */
108    loadUnpacked: function() {
109      chrome.send('extensionLoaderLoadUnpacked');
110    },
111
112    /**
113     * Notify the ExtensionLoader that loading an unpacked extension failed.
114     * Show the ExtensionLoadError.
115     * @param {string} filePath The path to the unpacked extension.
116     * @param {string} reason The reason the extension failed to load.
117     * @param {Object} manifest An object with three strings: beforeHighlight,
118     *     afterHighlight, and highlight. These represent three portions of the
119     *     file's content to display - the portion which is most relevant and
120     *     should be emphasized (highlight), and the parts both before and after
121     *     this portion. These may be empty.
122     */
123    notifyFailed: function(filePath, reason, manifest) {
124      this.loadError_.show(filePath, reason, manifest);
125    }
126  };
127
128  /*
129   * A static forwarding function for ExtensionLoader.notifyFailed.
130   * @param {string} filePath The path to the unpacked extension.
131   * @param {string} reason The reason the extension failed to load.
132   * @param {Object} manifest The manifest of the failed extension.
133   * @see ExtensionLoader.notifyFailed
134   */
135  ExtensionLoader.notifyLoadFailed = function(filePath, reason, manifest) {
136    ExtensionLoader.getInstance().notifyFailed(filePath, reason, manifest);
137  };
138
139  return {
140    ExtensionLoader: ExtensionLoader
141  };
142});
143