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