OLD | NEW |
| (Empty) |
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 }; | |
OLD | NEW |