OLD | NEW |
---|---|
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 'use strict'; | 5 'use strict'; |
6 | 6 |
7 /** | 7 /** |
8 * @fileoverview The event page for Google Now for Chrome implementation. | 8 * @fileoverview The event page for Google Now for Chrome implementation. |
9 * The Google Now event page gets Google Now cards from the server and shows | 9 * The Google Now event page gets Google Now cards from the server and shows |
10 * them as Chrome notifications. | 10 * them as Chrome notifications. |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
108 // send dismissals is scheduled. | 108 // send dismissals is scheduled. |
109 return true; | 109 return true; |
110 } | 110 } |
111 | 111 |
112 return false; | 112 return false; |
113 } | 113 } |
114 | 114 |
115 var tasks = buildTaskManager(areTasksConflicting); | 115 var tasks = buildTaskManager(areTasksConflicting); |
116 | 116 |
117 // Add error processing to API calls. | 117 // Add error processing to API calls. |
118 tasks.instrumentApiFunction(chrome.alarms, 'getAll', 0); | |
rgustafson
2013/07/19 23:37:12
Where is alarms.getAll used?
vadimt
2013/07/22 19:22:52
Done.
| |
118 tasks.instrumentApiFunction(chrome.identity, 'getAuthToken', 1); | 119 tasks.instrumentApiFunction(chrome.identity, 'getAuthToken', 1); |
119 tasks.instrumentApiFunction(chrome.identity, 'removeCachedAuthToken', 1); | 120 tasks.instrumentApiFunction(chrome.identity, 'removeCachedAuthToken', 1); |
120 tasks.instrumentApiFunction(chrome.location.onLocationUpdate, 'addListener', 0); | 121 tasks.instrumentApiFunction(chrome.location.onLocationUpdate, 'addListener', 0); |
121 tasks.instrumentApiFunction(chrome.notifications, 'create', 2); | 122 tasks.instrumentApiFunction(chrome.notifications, 'create', 2); |
122 tasks.instrumentApiFunction(chrome.notifications, 'update', 2); | 123 tasks.instrumentApiFunction(chrome.notifications, 'update', 2); |
123 tasks.instrumentApiFunction(chrome.notifications, 'getAll', 0); | 124 tasks.instrumentApiFunction(chrome.notifications, 'getAll', 0); |
124 tasks.instrumentApiFunction( | 125 tasks.instrumentApiFunction( |
125 chrome.notifications.onButtonClicked, 'addListener', 0); | 126 chrome.notifications.onButtonClicked, 'addListener', 0); |
126 tasks.instrumentApiFunction(chrome.notifications.onClicked, 'addListener', 0); | 127 tasks.instrumentApiFunction(chrome.notifications.onClicked, 'addListener', 0); |
127 tasks.instrumentApiFunction(chrome.notifications.onClosed, 'addListener', 0); | 128 tasks.instrumentApiFunction(chrome.notifications.onClosed, 'addListener', 0); |
128 tasks.instrumentApiFunction(chrome.runtime.onInstalled, 'addListener', 0); | 129 tasks.instrumentApiFunction(chrome.runtime.onInstalled, 'addListener', 0); |
129 tasks.instrumentApiFunction(chrome.runtime.onStartup, 'addListener', 0); | 130 tasks.instrumentApiFunction(chrome.runtime.onStartup, 'addListener', 0); |
130 tasks.instrumentApiFunction(chrome.tabs, 'create', 1); | 131 tasks.instrumentApiFunction(chrome.tabs, 'create', 1); |
131 tasks.instrumentApiFunction(storage, 'get', 1); | 132 tasks.instrumentApiFunction(storage, 'get', 1); |
132 | 133 |
133 var updateCardsAttempts = buildAttemptManager( | 134 var updateCardsAttempts = buildAttemptManager( |
134 'cards-update', | 135 'cards-update', |
135 requestLocation, | 136 requestLocation, |
136 INITIAL_POLLING_PERIOD_SECONDS, | 137 INITIAL_POLLING_PERIOD_SECONDS, |
137 MAXIMUM_POLLING_PERIOD_SECONDS); | 138 MAXIMUM_POLLING_PERIOD_SECONDS); |
138 var dismissalAttempts = buildAttemptManager( | 139 var dismissalAttempts = buildAttemptManager( |
139 'dismiss', | 140 'dismiss', |
140 retryPendingDismissals, | 141 retryPendingDismissals, |
141 INITIAL_RETRY_DISMISS_PERIOD_SECONDS, | 142 INITIAL_RETRY_DISMISS_PERIOD_SECONDS, |
142 MAXIMUM_RETRY_DISMISS_PERIOD_SECONDS); | 143 MAXIMUM_RETRY_DISMISS_PERIOD_SECONDS); |
144 var cardSet = buildCardManager(); | |
143 | 145 |
144 /** | 146 /** |
145 * Diagnostic event identifier. | 147 * Diagnostic event identifier. |
146 * @enum {number} | 148 * @enum {number} |
147 */ | 149 */ |
148 var DiagnosticEvent = { | 150 var DiagnosticEvent = { |
149 REQUEST_FOR_CARDS_TOTAL: 0, | 151 REQUEST_FOR_CARDS_TOTAL: 0, |
150 REQUEST_FOR_CARDS_SUCCESS: 1, | 152 REQUEST_FOR_CARDS_SUCCESS: 1, |
151 CARDS_PARSE_SUCCESS: 2, | 153 CARDS_PARSE_SUCCESS: 2, |
152 DISMISS_REQUEST_TOTAL: 3, | 154 DISMISS_REQUEST_TOTAL: 3, |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
210 } else { | 212 } else { |
211 originalOnLoadEnd(event); | 213 originalOnLoadEnd(event); |
212 } | 214 } |
213 }); | 215 }); |
214 | 216 |
215 callbackBoolean(true); | 217 callbackBoolean(true); |
216 }); | 218 }); |
217 } | 219 } |
218 | 220 |
219 /** | 221 /** |
220 * Shows a notification and remembers information associated with it. | |
221 * @param {Object} card Google Now card represented as a set of parameters for | |
222 * showing a Chrome notification. | |
223 * @param {Object} notificationsData Map from notification id to the data | |
224 * associated with a notification. | |
225 * @param {number=} opt_previousVersion The version of the shown card with this | |
226 * id, if it exists, undefined otherwise. | |
227 */ | |
228 function showNotification(card, notificationsData, opt_previousVersion) { | |
229 console.log('showNotification ' + JSON.stringify(card) + ' ' + | |
230 opt_previousVersion); | |
231 | |
232 if (typeof card.version != 'number') { | |
233 console.error('card.version is not a number'); | |
234 // Fix card version. | |
235 card.version = opt_previousVersion !== undefined ? opt_previousVersion : 0; | |
236 } | |
237 | |
238 if (opt_previousVersion !== card.version) { | |
239 try { | |
240 // Delete a notification with the specified id if it already exists, and | |
241 // then create a notification. | |
242 chrome.notifications.create( | |
243 card.notificationId, | |
244 card.notification, | |
245 function(notificationId) { | |
246 if (!notificationId || chrome.runtime.lastError) { | |
247 var errorMessage = | |
248 chrome.runtime.lastError && chrome.runtime.lastError.message; | |
249 console.error('notifications.create: ID=' + notificationId + | |
250 ', ERROR=' + errorMessage); | |
251 } | |
252 }); | |
253 } catch (error) { | |
254 console.error('Error in notifications.create: ' + error); | |
255 } | |
256 } else { | |
257 try { | |
258 // Update existing notification. | |
259 chrome.notifications.update( | |
260 card.notificationId, | |
261 card.notification, | |
262 function(wasUpdated) { | |
263 if (!wasUpdated || chrome.runtime.lastError) { | |
264 var errorMessage = | |
265 chrome.runtime.lastError && chrome.runtime.lastError.message; | |
266 console.error('notifications.update: UPDATED=' + wasUpdated + | |
267 ', ERROR=' + errorMessage); | |
268 } | |
269 }); | |
270 } catch (error) { | |
271 console.error('Error in notifications.update: ' + error); | |
272 } | |
273 } | |
274 | |
275 notificationsData[card.notificationId] = { | |
276 actionUrls: card.actionUrls, | |
277 version: card.version | |
278 }; | |
279 } | |
280 | |
281 /** | |
282 * Parses JSON response from the notification server, show notifications and | 222 * Parses JSON response from the notification server, show notifications and |
283 * schedule next update. | 223 * schedule next update. |
284 * @param {string} response Server response. | 224 * @param {string} response Server response. |
285 * @param {function()} callback Completion callback. | 225 * @param {function()} callback Completion callback. |
286 */ | 226 */ |
287 function parseAndShowNotificationCards(response, callback) { | 227 function parseAndShowNotificationCards(response, callback) { |
288 console.log('parseAndShowNotificationCards ' + response); | 228 console.log('parseAndShowNotificationCards ' + response); |
289 try { | 229 try { |
290 var parsedResponse = JSON.parse(response); | 230 var parsedResponse = JSON.parse(response); |
291 } catch (error) { | 231 } catch (error) { |
292 console.error('parseAndShowNotificationCards parse error: ' + error); | 232 console.error('parseAndShowNotificationCards parse error: ' + error); |
293 callback(); | 233 callback(); |
294 return; | 234 return; |
295 } | 235 } |
296 | 236 |
297 var cards = parsedResponse.cards; | 237 var cards = parsedResponse.cards; |
298 | 238 |
299 if (!(cards instanceof Array)) { | 239 if (!(cards instanceof Array)) { |
300 callback(); | 240 callback(); |
301 return; | 241 return; |
302 } | 242 } |
303 | 243 |
304 if (typeof parsedResponse.expiration_timestamp_seconds != 'number') { | 244 if (typeof parsedResponse.expiration_timestamp_seconds != 'number') { |
rgustafson
2013/07/22 17:48:07
Can we change expiration_timestamp_seconds to next
vadimt
2013/07/22 19:22:52
Done.
| |
305 callback(); | 245 callback(); |
306 return; | 246 return; |
307 } | 247 } |
308 | 248 |
309 tasks.debugSetStepName('parseAndShowNotificationCards-storage-get'); | 249 tasks.debugSetStepName('parseAndShowNotificationCards-storage-get'); |
310 storage.get(['notificationsData', 'recentDismissals'], function(items) { | 250 storage.get(['notificationsData', 'recentDismissals'], function(items) { |
311 console.log('parseAndShowNotificationCards-get ' + JSON.stringify(items)); | 251 console.log('parseAndShowNotificationCards-get ' + JSON.stringify(items)); |
312 items.notificationsData = items.notificationsData || {}; | 252 items.notificationsData = items.notificationsData || {}; |
313 items.recentDismissals = items.recentDismissals || {}; | 253 items.recentDismissals = items.recentDismissals || {}; |
314 | 254 |
315 tasks.debugSetStepName( | 255 tasks.debugSetStepName( |
316 'parseAndShowNotificationCards-notifications-getAll'); | 256 'parseAndShowNotificationCards-notifications-getAll'); |
317 chrome.notifications.getAll(function(notifications) { | 257 chrome.notifications.getAll(function(notifications) { |
318 console.log('parseAndShowNotificationCards-getAll ' + | 258 console.log('parseAndShowNotificationCards-getAll ' + |
319 JSON.stringify(notifications)); | 259 JSON.stringify(notifications)); |
320 // TODO(vadimt): Figure out what to do when notifications are disabled for | 260 // TODO(vadimt): Figure out what to do when notifications are disabled for |
rgustafson
2013/07/19 23:37:12
Why was this un-tabbed? It should be on the level
vadimt
2013/07/22 19:22:52
Done. I probably need to see my doctor.
| |
321 // our extension. | 261 // our extension. |
322 notifications = notifications || {}; | 262 notifications = notifications || {}; |
323 | 263 |
324 // Build a set of non-expired recent dismissals. It will be used for | 264 // Build a set of non-expired recent dismissals. It will be used for |
325 // client-side filtering of cards. | 265 // client-side filtering of cards. |
326 var updatedRecentDismissals = {}; | 266 var updatedRecentDismissals = {}; |
327 var currentTimeMs = Date.now(); | 267 var currentTimeMs = Date.now(); |
328 for (var notificationId in items.recentDismissals) { | 268 for (var notificationId in items.recentDismissals) { |
329 if (currentTimeMs - items.recentDismissals[notificationId] < | 269 if (currentTimeMs - items.recentDismissals[notificationId] < |
330 DISMISS_RETENTION_TIME_MS) { | 270 DISMISS_RETENTION_TIME_MS) { |
331 updatedRecentDismissals[notificationId] = | 271 updatedRecentDismissals[notificationId] = |
332 items.recentDismissals[notificationId]; | 272 items.recentDismissals[notificationId]; |
(...skipping 11 matching lines...) Expand all Loading... | |
344 updatedNotifications[notificationId] = true; | 284 updatedNotifications[notificationId] = true; |
345 } | 285 } |
346 } | 286 } |
347 | 287 |
348 // Delete notifications that didn't receive an update. | 288 // Delete notifications that didn't receive an update. |
349 for (var notificationId in notifications) { | 289 for (var notificationId in notifications) { |
350 console.log('parseAndShowNotificationCards-delete-check ' + | 290 console.log('parseAndShowNotificationCards-delete-check ' + |
351 notificationId); | 291 notificationId); |
352 if (!(notificationId in updatedNotifications)) { | 292 if (!(notificationId in updatedNotifications)) { |
353 console.log('parseAndShowNotificationCards-delete ' + notificationId); | 293 console.log('parseAndShowNotificationCards-delete ' + notificationId); |
354 chrome.notifications.clear( | 294 cardSet.clear(notificationId); |
355 notificationId, | |
356 function() {}); | |
357 } | 295 } |
358 } | 296 } |
359 | 297 |
360 recordEvent(DiagnosticEvent.CARDS_PARSE_SUCCESS); | 298 recordEvent(DiagnosticEvent.CARDS_PARSE_SUCCESS); |
361 | 299 |
362 // Create/update notifications and store their new properties. | 300 // Create/update notifications and store their new properties. |
363 var newNotificationsData = {}; | 301 var newNotificationsData = {}; |
364 for (var i = 0; i < cards.length; ++i) { | 302 for (var i = 0; i < cards.length; ++i) { |
365 var card = cards[i]; | 303 var card = cards[i]; |
366 if (!(card.notificationId in updatedRecentDismissals)) { | 304 if (!(card.notificationId in updatedRecentDismissals)) { |
367 var notificationData = items.notificationsData[card.notificationId]; | 305 var notificationData = items.notificationsData[card.notificationId]; |
368 var previousVersion = notifications[card.notificationId] && | 306 var previousVersion = notifications[card.notificationId] && |
369 notificationData && | 307 notificationData && |
370 notificationData.previousVersion; | 308 notificationData.cardCreateInfo && |
371 showNotification(card, newNotificationsData, previousVersion); | 309 notificationData.cardCreateInfo.version; |
310 newNotificationsData[card.notificationId] = | |
311 cardSet.update(card, previousVersion); | |
372 } | 312 } |
373 } | 313 } |
374 | 314 |
375 updateCardsAttempts.start(parsedResponse.expiration_timestamp_seconds); | 315 updateCardsAttempts.start(parsedResponse.expiration_timestamp_seconds); |
rgustafson
2013/07/22 17:48:07
expiration_timestamp_seconds to next_poll_seconds
vadimt
2013/07/22 19:22:52
Done.
| |
376 | 316 |
377 storage.set({ | 317 storage.set({ |
378 notificationsData: newNotificationsData, | 318 notificationsData: newNotificationsData, |
379 recentDismissals: updatedRecentDismissals | 319 recentDismissals: updatedRecentDismissals |
380 }); | 320 }); |
381 callback(); | 321 callback(); |
382 }); | 322 }); |
383 }); | 323 }); |
384 } | 324 } |
385 | 325 |
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
634 } | 574 } |
635 | 575 |
636 // At this point we are guaranteed that the notification is a now card. | 576 // At this point we are guaranteed that the notification is a now card. |
637 chrome.metricsPrivate.recordUserAction('GoogleNow.Dismissed'); | 577 chrome.metricsPrivate.recordUserAction('GoogleNow.Dismissed'); |
638 | 578 |
639 tasks.add(DISMISS_CARD_TASK_NAME, function(callback) { | 579 tasks.add(DISMISS_CARD_TASK_NAME, function(callback) { |
640 dismissalAttempts.start(); | 580 dismissalAttempts.start(); |
641 | 581 |
642 // Deleting the notification in case it was re-added while this task was | 582 // Deleting the notification in case it was re-added while this task was |
643 // scheduled, waiting for execution. | 583 // scheduled, waiting for execution. |
644 chrome.notifications.clear( | 584 cardSet.clear(notificationId); |
645 notificationId, | |
646 function() {}); | |
647 | 585 |
648 tasks.debugSetStepName('onNotificationClosed-get-pendingDismissals'); | 586 tasks.debugSetStepName('onNotificationClosed-get-pendingDismissals'); |
649 storage.get('pendingDismissals', function(items) { | 587 storage.get('pendingDismissals', function(items) { |
650 items.pendingDismissals = items.pendingDismissals || []; | 588 items.pendingDismissals = items.pendingDismissals || []; |
651 | 589 |
652 var dismissal = { | 590 var dismissal = { |
653 notificationId: notificationId, | 591 notificationId: notificationId, |
654 time: Date.now() | 592 time: Date.now() |
655 }; | 593 }; |
656 items.pendingDismissals.push(dismissal); | 594 items.pendingDismissals.push(dismissal); |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
758 | 696 |
759 chrome.location.onLocationUpdate.addListener(function(position) { | 697 chrome.location.onLocationUpdate.addListener(function(position) { |
760 recordEvent(DiagnosticEvent.LOCATION_UPDATE); | 698 recordEvent(DiagnosticEvent.LOCATION_UPDATE); |
761 updateNotificationsCards(position); | 699 updateNotificationsCards(position); |
762 }); | 700 }); |
763 | 701 |
764 chrome.omnibox.onInputEntered.addListener(function(text) { | 702 chrome.omnibox.onInputEntered.addListener(function(text) { |
765 localStorage['server_url'] = NOTIFICATION_CARDS_URL = text; | 703 localStorage['server_url'] = NOTIFICATION_CARDS_URL = text; |
766 initialize(); | 704 initialize(); |
767 }); | 705 }); |
OLD | NEW |