| 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 |