Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / ui / file_manager / file_manager / background / js / progress_center.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 'use strict';
6
7 /**
8  * Progress center at the background page.
9  * @constructor
10  */
11 var ProgressCenter = function() {
12   /**
13    * Current items managed by the progress center.
14    * @type {Array.<ProgressItem>}
15    * @private
16    */
17   this.items_ = [];
18
19   /**
20    * Map of progress ID and notification ID.
21    * @type {Object.<string, string>}
22    * @private
23    */
24   this.notifications_ = new ProgressCenter.Notifications_(
25       this.requestCancel.bind(this));
26
27   /**
28    * List of panel UI managed by the progress center.
29    * @type {Array.<ProgressCenterPanel>}
30    * @private
31    */
32   this.panels_ = [];
33
34   Object.seal(this);
35 };
36
37 /**
38  * Notifications created by progress center.
39  * @param {function(string)} cancelCallback Callback to notify the progress
40  *     center of cancel operation.
41  * @constructor
42  * @private
43  */
44 ProgressCenter.Notifications_ = function(cancelCallback) {
45   /**
46    * ID set of notifications that is progressing now.
47    * @type {Object.<string, ProgressCenter.Notifications_.NotificationState_>}
48    * @private
49    */
50   this.ids_ = {};
51
52   /**
53    * Async queue.
54    * @type {AsyncUtil.Queue}
55    * @private
56    */
57   this.queue_ = new AsyncUtil.Queue();
58
59   /**
60    * Callback to notify the progress center of cancel operation.
61    * @type {function(string)}
62    * @private
63    */
64   this.cancelCallback_ = cancelCallback;
65
66   chrome.notifications.onButtonClicked.addListener(
67       this.onButtonClicked_.bind(this));
68   chrome.notifications.onClosed.addListener(this.onClosed_.bind(this));
69
70   Object.seal(this);
71 };
72
73 /**
74  * State of notification.
75  * @enum {string}
76  * @const
77  * @private
78  */
79 ProgressCenter.Notifications_.NotificationState_ = Object.freeze({
80   VISIBLE: 'visible',
81   DISMISSED: 'dismissed'
82 });
83
84 /**
85  * Updates the notification according to the item.
86  * @param {ProgressCenterItem} item Item to contain new information.
87  * @param {boolean} newItemAcceptable Whether to accept new item or not.
88  */
89 ProgressCenter.Notifications_.prototype.updateItem = function(
90     item, newItemAcceptable) {
91   var NotificationState = ProgressCenter.Notifications_.NotificationState_;
92   var newlyAdded = !(item.id in this.ids_);
93
94   // If new item is not acceptable, just return.
95   if (newlyAdded && !newItemAcceptable)
96     return;
97
98   // Update the ID map and return if we does not show a notification for the
99   // item.
100   if (item.state === ProgressItemState.PROGRESSING) {
101     if (newlyAdded)
102       this.ids_[item.id] = NotificationState.VISIBLE;
103     else if (this.ids_[item.id] === NotificationState.DISMISSED)
104       return;
105   } else {
106     // This notification is no longer tracked.
107     var previousState = this.ids_[item.id];
108     delete this.ids_[item.id];
109     // Clear notifications for complete or canceled items.
110     if (item.state === ProgressItemState.CANCELED ||
111         item.state === ProgressItemState.COMPLETED) {
112       if (previousState === NotificationState.VISIBLE) {
113         this.queue_.run(function(proceed) {
114           chrome.notifications.clear(item.id, proceed);
115         });
116       }
117       return;
118     }
119   }
120
121   // Create/update the notification with the item.
122   this.queue_.run(function(proceed) {
123     var params = {
124       title: chrome.runtime.getManifest().name,
125       iconUrl: chrome.runtime.getURL('/common/images/icon96.png'),
126       type: item.state === ProgressItemState.PROGRESSING ? 'progress' : 'basic',
127       message: item.message,
128       buttons: item.cancelable ? [{title: str('CANCEL_LABEL')}] : undefined,
129       progress: item.state === ProgressItemState.PROGRESSING ?
130           item.progressRateInPercent : undefined,
131       priority: (item.state === ProgressItemState.ERROR || !item.quiet) ? 0 : -1
132     };
133     if (newlyAdded)
134       chrome.notifications.create(item.id, params, proceed);
135     else
136       chrome.notifications.update(item.id, params, proceed);
137   }.bind(this));
138 };
139
140 /**
141  * Handles cancel button click.
142  * @param {string} id Item ID.
143  * @private
144  */
145 ProgressCenter.Notifications_.prototype.onButtonClicked_ = function(id) {
146   if (id in this.ids_)
147     this.cancelCallback_(id);
148 };
149
150 /**
151  * Handles notification close.
152  * @param {string} id Item ID.
153  * @private
154  */
155 ProgressCenter.Notifications_.prototype.onClosed_ = function(id) {
156   if (id in this.ids_)
157     this.ids_[id] = ProgressCenter.Notifications_.NotificationState_.DISMISSED;
158 };
159
160 /**
161  * Updates the item in the progress center.
162  * If the item has a new ID, the item is added to the item list.
163  *
164  * @param {ProgressCenterItem} item Updated item.
165  */
166 ProgressCenter.prototype.updateItem = function(item) {
167   // Update item.
168   var index = this.getItemIndex_(item.id);
169   if (item.state === ProgressItemState.PROGRESSING) {
170     if (index === -1)
171       this.items_.push(item);
172     else
173       this.items_[index] = item;
174   } else {
175     if (index !== -1)
176       this.items_.splice(index, 1);
177   }
178
179   // Update panels.
180   for (var i = 0; i < this.panels_.length; i++) {
181     this.panels_[i].updateItem(item);
182   }
183
184   // Update notifications.
185   this.notifications_.updateItem(item, !this.panels_.length);
186 };
187
188 /**
189  * Requests to cancel the progress item.
190  * @param {string} id Progress ID to be requested to cancel.
191  */
192 ProgressCenter.prototype.requestCancel = function(id) {
193   var item = this.getItemById(id);
194   if (item && item.cancelCallback)
195     item.cancelCallback();
196 };
197
198 /**
199  * Adds a panel UI to the notification center.
200  * @param {ProgressCenterPanel} panel Panel UI.
201  */
202 ProgressCenter.prototype.addPanel = function(panel) {
203   if (this.panels_.indexOf(panel) !== -1)
204     return;
205
206   // Update the panel list.
207   this.panels_.push(panel);
208
209   // Set the current items.
210   for (var i = 0; i < this.items_.length; i++)
211     panel.updateItem(this.items_[i]);
212
213   // Register the cancel callback.
214   panel.cancelCallback = this.requestCancel.bind(this);
215 };
216
217 /**
218  * Removes a panel UI from the notification center.
219  * @param {ProgressCenterPanel} panel Panel UI.
220  */
221 ProgressCenter.prototype.removePanel = function(panel) {
222   var index = this.panels_.indexOf(panel);
223   if (index === -1)
224     return;
225
226   this.panels_.splice(index, 1);
227   panel.cancelCallback = null;
228
229   // If there is no panel, show the notifications.
230   if (this.panels_.length)
231     return;
232   for (var i = 0; i < this.items_.length; i++)
233     this.notifications_.updateItem(this.items_[i], true);
234 };
235
236 /**
237  * Obtains item by ID.
238  * @param {string} id ID of progress item.
239  * @return {ProgressCenterItem} Progress center item having the specified
240  *     ID. Null if the item is not found.
241  */
242 ProgressCenter.prototype.getItemById = function(id) {
243   return this.items_[this.getItemIndex_(id)];
244 };
245
246 /**
247  * Obtains item index that have the specifying ID.
248  * @param {string} id Item ID.
249  * @return {number} Item index. Returns -1 If the item is not found.
250  * @private
251  */
252 ProgressCenter.prototype.getItemIndex_ = function(id) {
253   for (var i = 0; i < this.items_.length; i++) {
254     if (this.items_[i].id === id)
255       return i;
256   }
257   return -1;
258 };