Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / resources / extensions / extension_error.js
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
3 // found in the LICENSE file.
4
5 <include src="extension_error_overlay.js"></include>
6
7 cr.define('extensions', function() {
8   'use strict';
9
10   /**
11    * Clone a template within the extension error template collection.
12    * @param {string} templateName The class name of the template to clone.
13    * @return {HTMLElement} The clone of the template.
14    */
15   function cloneTemplate(templateName) {
16     return $('template-collection-extension-error').
17         querySelector('.' + templateName).cloneNode(true);
18   }
19
20   /**
21    * Checks that an Extension ID follows the proper format (i.e., is 32
22    * characters long, is lowercase, and contains letters in the range [a, p]).
23    * @param {string} id The Extension ID to test.
24    * @return {boolean} Whether or not the ID is valid.
25    */
26   function idIsValid(id) {
27     return /^[a-p]{32}$/.test(id);
28   }
29
30   /**
31    * Creates a new ExtensionError HTMLElement; this is used to show a
32    * notification to the user when an error is caused by an extension.
33    * @param {Object} error The error the element should represent.
34    * @constructor
35    * @extends {HTMLDivElement}
36    */
37   function ExtensionError(error) {
38     var div = cloneTemplate('extension-error-metadata');
39     div.__proto__ = ExtensionError.prototype;
40     div.decorate(error);
41     return div;
42   }
43
44   ExtensionError.prototype = {
45     __proto__: HTMLDivElement.prototype,
46
47     /** @override */
48     decorate: function(error) {
49       // Add an additional class for the severity level.
50       if (error.level == 0)
51         this.classList.add('extension-error-severity-info');
52       else if (error.level == 1)
53         this.classList.add('extension-error-severity-warning');
54       else
55         this.classList.add('extension-error-severity-fatal');
56
57       var iconNode = document.createElement('img');
58       iconNode.className = 'extension-error-icon';
59       this.insertBefore(iconNode, this.firstChild);
60
61       var messageSpan = this.querySelector('.extension-error-message');
62       messageSpan.textContent = error.message;
63       messageSpan.title = error.message;
64
65       var extensionUrl = 'chrome-extension://' + error.extensionId + '/';
66       var viewDetailsLink = this.querySelector('.extension-error-view-details');
67
68       // If we cannot open the file source and there are no external frames in
69       // the stack, then there are no details to display.
70       if (!extensions.ExtensionErrorOverlay.canShowOverlayForError(
71               error, extensionUrl)) {
72         viewDetailsLink.hidden = true;
73       } else {
74         var stringId = extensionUrl.toLowerCase() == 'manifest.json' ?
75             'extensionErrorViewManifest' : 'extensionErrorViewDetails';
76         viewDetailsLink.textContent = loadTimeData.getString(stringId);
77
78         viewDetailsLink.addEventListener('click', function(e) {
79           extensions.ExtensionErrorOverlay.getInstance().setErrorAndShowOverlay(
80               error, extensionUrl);
81         });
82       }
83     },
84   };
85
86   /**
87    * A variable length list of runtime or manifest errors for a given extension.
88    * @param {Array.<Object>} errors The list of extension errors with which
89    *     to populate the list.
90    * @constructor
91    * @extends {HTMLDivElement}
92    */
93   function ExtensionErrorList(errors) {
94     var div = cloneTemplate('extension-error-list');
95     div.__proto__ = ExtensionErrorList.prototype;
96     div.errors_ = errors;
97     div.decorate();
98     return div;
99   }
100
101   ExtensionErrorList.prototype = {
102     __proto__: HTMLDivElement.prototype,
103
104     /**
105      * @private
106      * @const
107      * @type {number}
108      */
109     MAX_ERRORS_TO_SHOW_: 3,
110
111     /** @override */
112     decorate: function() {
113       this.contents_ = this.querySelector('.extension-error-list-contents');
114       this.errors_.forEach(function(error) {
115         if (idIsValid(error.extensionId)) {
116           this.contents_.appendChild(document.createElement('li')).appendChild(
117               new ExtensionError(error));
118         }
119       }, this);
120
121       if (this.contents_.children.length > this.MAX_ERRORS_TO_SHOW_)
122         this.initShowMoreButton_();
123     },
124
125     /**
126      * Initialize the "Show More" button for the error list. If there are more
127      * than |MAX_ERRORS_TO_SHOW_| errors in the list.
128      * @private
129      */
130     initShowMoreButton_: function() {
131       var button = this.querySelector('.extension-error-list-show-more button');
132       button.hidden = false;
133       button.isShowingAll = false;
134       var listContents = this.querySelector('.extension-error-list-contents');
135       listContents.addEventListener('webkitTransitionEnd', function(e) {
136         if (listContents.classList.contains('active'))
137           listContents.classList.add('scrollable');
138       });
139       button.addEventListener('click', function(e) {
140         // Disable scrolling while transitioning. If the element is active,
141         // scrolling is enabled when the transition ends.
142         listContents.classList.toggle('active');
143         listContents.classList.remove('scrollable');
144         var message = button.isShowingAll ? 'extensionErrorsShowMore' :
145                                             'extensionErrorsShowFewer';
146         button.textContent = loadTimeData.getString(message);
147         button.isShowingAll = !button.isShowingAll;
148       }.bind(this));
149     }
150   };
151
152   return {
153     ExtensionErrorList: ExtensionErrorList
154   };
155 });