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.
8 * Progress center at the background page.
11 var ProgressCenter = function() {
13 * Current items managed by the progress center.
14 * @type {Array.<ProgressItem>}
20 * Map of progress ID and notification ID.
21 * @type {Object.<string, string>}
24 this.notifications_ = new ProgressCenter.Notifications_(
25 this.requestCancel.bind(this));
28 * List of panel UI managed by the progress center.
29 * @type {Array.<ProgressCenterPanel>}
38 * Notifications created by progress center.
39 * @param {function(string)} cancelCallback Callback to notify the progress
40 * center of cancel operation.
44 ProgressCenter.Notifications_ = function(cancelCallback) {
46 * ID set of notifications that is progressing now.
47 * @type {Object.<string, ProgressCenter.Notifications_.NotificationState_>}
54 * @type {AsyncUtil.Queue}
57 this.queue_ = new AsyncUtil.Queue();
60 * Callback to notify the progress center of cancel operation.
61 * @type {function(string)}
64 this.cancelCallback_ = cancelCallback;
66 chrome.notifications.onButtonClicked.addListener(
67 this.onButtonClicked_.bind(this));
68 chrome.notifications.onClosed.addListener(this.onClosed_.bind(this));
74 * State of notification.
79 ProgressCenter.Notifications_.NotificationState_ = Object.freeze({
81 DISMISSED: 'dismissed'
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.
89 ProgressCenter.Notifications_.prototype.updateItem = function(
90 item, newItemAcceptable) {
91 var NotificationState = ProgressCenter.Notifications_.NotificationState_;
92 var newlyAdded = !(item.id in this.ids_);
94 // If new item is not acceptable, just return.
95 if (newlyAdded && !newItemAcceptable)
98 // Update the ID map and return if we does not show a notification for the
100 if (item.state === ProgressItemState.PROGRESSING) {
102 this.ids_[item.id] = NotificationState.VISIBLE;
103 else if (this.ids_[item.id] === NotificationState.DISMISSED)
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);
121 // Create/update the notification with the item.
122 this.queue_.run(function(proceed) {
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
134 chrome.notifications.create(item.id, params, proceed);
136 chrome.notifications.update(item.id, params, proceed);
141 * Handles cancel button click.
142 * @param {string} id Item ID.
145 ProgressCenter.Notifications_.prototype.onButtonClicked_ = function(id) {
147 this.cancelCallback_(id);
151 * Handles notification close.
152 * @param {string} id Item ID.
155 ProgressCenter.Notifications_.prototype.onClosed_ = function(id) {
157 this.ids_[id] = ProgressCenter.Notifications_.NotificationState_.DISMISSED;
161 * Updates the item in the progress center.
162 * If the item has a new ID, the item is added to the item list.
164 * @param {ProgressCenterItem} item Updated item.
166 ProgressCenter.prototype.updateItem = function(item) {
168 var index = this.getItemIndex_(item.id);
169 if (item.state === ProgressItemState.PROGRESSING) {
171 this.items_.push(item);
173 this.items_[index] = item;
176 this.items_.splice(index, 1);
180 for (var i = 0; i < this.panels_.length; i++) {
181 this.panels_[i].updateItem(item);
184 // Update notifications.
185 this.notifications_.updateItem(item, !this.panels_.length);
189 * Requests to cancel the progress item.
190 * @param {string} id Progress ID to be requested to cancel.
192 ProgressCenter.prototype.requestCancel = function(id) {
193 var item = this.getItemById(id);
194 if (item && item.cancelCallback)
195 item.cancelCallback();
199 * Adds a panel UI to the notification center.
200 * @param {ProgressCenterPanel} panel Panel UI.
202 ProgressCenter.prototype.addPanel = function(panel) {
203 if (this.panels_.indexOf(panel) !== -1)
206 // Update the panel list.
207 this.panels_.push(panel);
209 // Set the current items.
210 for (var i = 0; i < this.items_.length; i++)
211 panel.updateItem(this.items_[i]);
213 // Register the cancel callback.
214 panel.cancelCallback = this.requestCancel.bind(this);
218 * Removes a panel UI from the notification center.
219 * @param {ProgressCenterPanel} panel Panel UI.
221 ProgressCenter.prototype.removePanel = function(panel) {
222 var index = this.panels_.indexOf(panel);
226 this.panels_.splice(index, 1);
227 panel.cancelCallback = null;
229 // If there is no panel, show the notifications.
230 if (this.panels_.length)
232 for (var i = 0; i < this.items_.length; i++)
233 this.notifications_.updateItem(this.items_[i], true);
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.
242 ProgressCenter.prototype.getItemById = function(id) {
243 return this.items_[this.getItemIndex_(id)];
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.
252 ProgressCenter.prototype.getItemIndex_ = function(id) {
253 for (var i = 0; i < this.items_.length; i++) {
254 if (this.items_[i].id === id)