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'; TODO(vadimt): Uncomment once crbug.com/237617 is fixed. | 5 // 'use strict'; TODO(vadimt): Uncomment once crbug.com/237617 is fixed. |
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. |
11 * The service performs periodic updating of Google Now cards. | 11 * The service performs periodic updating of Google Now cards. |
12 * Each updating of the cards includes 4 steps: | 12 * Each updating of the cards includes 4 steps: |
13 * 1. Obtaining the location of the machine; | 13 * 1. Obtaining the location of the machine; |
14 * 2. Processing requests for cards dismissals that are not yet sent to the | 14 * 2. Processing requests for cards dismissals that are not yet sent to the |
15 * server; | 15 * server; |
16 * 3. Making a server request based on that location; | 16 * 3. Making a server request based on that location; |
17 * 4. Showing the received cards as notifications. | 17 * 4. Showing the received cards as notifications. |
18 */ | 18 */ |
19 | 19 |
20 // TODO(vadimt): Use background permission to show notifications even when all | 20 // TODO(vadimt): Use background permission to show notifications even when all |
21 // browser windows are closed. | 21 // browser windows are closed. |
22 // TODO(vadimt): Decide what to do in incognito mode. | 22 // TODO(vadimt): Decide what to do in incognito mode. |
23 // TODO(vadimt): Honor the flag the enables Google Now integration. | 23 // TODO(vadimt): Honor the flag the enables Google Now integration. |
24 // TODO(vadimt): Figure out the final values of the constants. | 24 // TODO(vadimt): Figure out the final values of the constants. |
25 // TODO(vadimt): Remove 'console' calls. | 25 // TODO(vadimt): Remove 'console' calls. |
26 // TODO(vadimt): Consider sending JS stacks for unexpected exceptions (including | 26 // TODO(vadimt): Consider sending JS stacks for chrome.* API errors and |
27 // ones from verify()), unfinished and infinite tasks, chrome.* API errors and | |
28 // malformed server responses. | 27 // malformed server responses. |
29 | 28 |
30 /** | 29 /** |
31 * Standard response code for successful HTTP requests. This is the only success | 30 * Standard response code for successful HTTP requests. This is the only success |
32 * code the server will send. | 31 * code the server will send. |
33 */ | 32 */ |
34 var HTTP_OK = 200; | 33 var HTTP_OK = 200; |
35 | 34 |
36 /** | 35 /** |
37 * Initial period for polling for Google Now Notifications cards to use when the | 36 * Initial period for polling for Google Now Notifications cards to use when the |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
237 callback(); | 236 callback(); |
238 return; | 237 return; |
239 } | 238 } |
240 | 239 |
241 if (typeof parsedResponse.expiration_timestamp_seconds != 'number') { | 240 if (typeof parsedResponse.expiration_timestamp_seconds != 'number') { |
242 callback(); | 241 callback(); |
243 return; | 242 return; |
244 } | 243 } |
245 | 244 |
246 tasks.debugSetStepName('parseAndShowNotificationCards-storage-get'); | 245 tasks.debugSetStepName('parseAndShowNotificationCards-storage-get'); |
247 storage.get(['activeNotifications', 'recentDismissals'], function(items) { | 246 storage.get(['activeNotifications', 'recentDismissals'], function(items) { |
not at google - send to devlin
2013/05/24 00:01:12
instead you could call
storage.get({
'activeNot
| |
248 console.log('parseAndShowNotificationCards-get ' + JSON.stringify(items)); | 247 console.log('parseAndShowNotificationCards-get ' + JSON.stringify(items)); |
248 items.activeNotifications = items.activeNotifications || {}; | |
249 items.recentDismissals = items.recentDismissals || {}; | |
249 | 250 |
250 // Build a set of non-expired recent dismissals. It will be used for | 251 // Build a set of non-expired recent dismissals. It will be used for |
251 // client-side filtering of cards. | 252 // client-side filtering of cards. |
252 var updatedRecentDismissals = {}; | 253 var updatedRecentDismissals = {}; |
253 var currentTimeMs = Date.now(); | 254 var currentTimeMs = Date.now(); |
254 for (var notificationId in items.recentDismissals) { | 255 for (var notificationId in items.recentDismissals) { |
255 if (currentTimeMs - items.recentDismissals[notificationId] < | 256 if (currentTimeMs - items.recentDismissals[notificationId] < |
256 DISMISS_RETENTION_TIME_MS) { | 257 DISMISS_RETENTION_TIME_MS) { |
257 updatedRecentDismissals[notificationId] = | 258 updatedRecentDismissals[notificationId] = |
258 items.recentDismissals[notificationId]; | 259 items.recentDismissals[notificationId]; |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
409 /** | 410 /** |
410 * Tries to send dismiss requests for all pending dismissals. | 411 * Tries to send dismiss requests for all pending dismissals. |
411 * @param {function(boolean)} callbackBoolean Completion callback with 'success' | 412 * @param {function(boolean)} callbackBoolean Completion callback with 'success' |
412 * parameter. Success means that no pending dismissals are left. | 413 * parameter. Success means that no pending dismissals are left. |
413 */ | 414 */ |
414 function processPendingDismissals(callbackBoolean) { | 415 function processPendingDismissals(callbackBoolean) { |
415 tasks.debugSetStepName('processPendingDismissals-storage-get'); | 416 tasks.debugSetStepName('processPendingDismissals-storage-get'); |
416 storage.get(['pendingDismissals', 'recentDismissals'], function(items) { | 417 storage.get(['pendingDismissals', 'recentDismissals'], function(items) { |
417 console.log('processPendingDismissals-storage-get ' + | 418 console.log('processPendingDismissals-storage-get ' + |
418 JSON.stringify(items)); | 419 JSON.stringify(items)); |
420 items.pendingDismissals = items.pendingDismissals || []; | |
421 items.recentDismissals = items.recentDismissals || {}; | |
422 | |
419 var dismissalsChanged = false; | 423 var dismissalsChanged = false; |
420 | 424 |
421 function onFinish(success) { | 425 function onFinish(success) { |
422 if (dismissalsChanged) { | 426 if (dismissalsChanged) { |
423 storage.set({ | 427 storage.set({ |
424 pendingDismissals: items.pendingDismissals, | 428 pendingDismissals: items.pendingDismissals, |
425 recentDismissals: items.recentDismissals | 429 recentDismissals: items.recentDismissals |
426 }); | 430 }); |
427 } | 431 } |
428 callbackBoolean(success); | 432 callbackBoolean(success); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
469 /** | 473 /** |
470 * Opens URL corresponding to the clicked part of the notification. | 474 * Opens URL corresponding to the clicked part of the notification. |
471 * @param {string} notificationId Unique identifier of the notification. | 475 * @param {string} notificationId Unique identifier of the notification. |
472 * @param {function(Object): string} selector Function that extracts the url for | 476 * @param {function(Object): string} selector Function that extracts the url for |
473 * the clicked area from the button action URLs info. | 477 * the clicked area from the button action URLs info. |
474 */ | 478 */ |
475 function onNotificationClicked(notificationId, selector) { | 479 function onNotificationClicked(notificationId, selector) { |
476 tasks.add(CARD_CLICKED_TASK_NAME, function(callback) { | 480 tasks.add(CARD_CLICKED_TASK_NAME, function(callback) { |
477 tasks.debugSetStepName('onNotificationClicked-get-activeNotifications'); | 481 tasks.debugSetStepName('onNotificationClicked-get-activeNotifications'); |
478 storage.get('activeNotifications', function(items) { | 482 storage.get('activeNotifications', function(items) { |
483 items.activeNotifications = items.activeNotifications || {}; | |
484 | |
479 var actionUrls = items.activeNotifications[notificationId].actionUrls; | 485 var actionUrls = items.activeNotifications[notificationId].actionUrls; |
480 if (typeof actionUrls != 'object') { | 486 if (typeof actionUrls != 'object') { |
481 callback(); | 487 callback(); |
482 return; | 488 return; |
483 } | 489 } |
484 | 490 |
485 var url = selector(actionUrls); | 491 var url = selector(actionUrls); |
486 | 492 |
487 if (typeof url != 'string') { | 493 if (typeof url != 'string') { |
488 callback(); | 494 callback(); |
(...skipping 24 matching lines...) Expand all Loading... | |
513 dismissalAttempts.start(); | 519 dismissalAttempts.start(); |
514 | 520 |
515 // Deleting the notification in case it was re-added while this task was | 521 // Deleting the notification in case it was re-added while this task was |
516 // scheduled, waiting for execution. | 522 // scheduled, waiting for execution. |
517 chrome.notifications.clear( | 523 chrome.notifications.clear( |
518 notificationId, | 524 notificationId, |
519 function() {}); | 525 function() {}); |
520 | 526 |
521 tasks.debugSetStepName('onNotificationClosed-get-pendingDismissals'); | 527 tasks.debugSetStepName('onNotificationClosed-get-pendingDismissals'); |
522 storage.get('pendingDismissals', function(items) { | 528 storage.get('pendingDismissals', function(items) { |
529 items.pendingDismissals = items.pendingDismissals || []; | |
530 | |
523 var dismissal = { | 531 var dismissal = { |
524 notificationId: notificationId, | 532 notificationId: notificationId, |
525 time: Date.now() | 533 time: Date.now() |
526 }; | 534 }; |
527 items.pendingDismissals.push(dismissal); | 535 items.pendingDismissals.push(dismissal); |
528 storage.set({pendingDismissals: items.pendingDismissals}); | 536 storage.set({pendingDismissals: items.pendingDismissals}); |
529 processPendingDismissals(function(success) { callback(); }); | 537 processPendingDismissals(function(success) { callback(); }); |
530 }); | 538 }); |
531 }); | 539 }); |
532 } | 540 } |
533 | 541 |
534 /** | 542 /** |
535 * Initializes the event page on install or on browser startup. | 543 * Initializes the event page on install or on browser startup. |
536 */ | 544 */ |
537 function initialize() { | 545 function initialize() { |
538 // Create an update timer for a case when for some reason location request | 546 // Create an update timer for a case when for some reason location request |
539 // gets stuck. | 547 // gets stuck. |
540 updateCardsAttempts.start(MAXIMUM_POLLING_PERIOD_SECONDS); | 548 updateCardsAttempts.start(MAXIMUM_POLLING_PERIOD_SECONDS); |
541 | 549 |
542 var initialStorage = { | 550 var initialStorage = { |
543 activeNotifications: {}, | 551 activeNotifications: {} |
544 recentDismissals: {} | |
545 }; | 552 }; |
546 storage.set(initialStorage); | 553 storage.set(initialStorage); |
547 | 554 |
548 requestLocation(); | 555 requestLocation(); |
549 } | 556 } |
550 | 557 |
551 chrome.runtime.onInstalled.addListener(function(details) { | 558 chrome.runtime.onInstalled.addListener(function(details) { |
552 console.log('onInstalled ' + JSON.stringify(details)); | 559 console.log('onInstalled ' + JSON.stringify(details)); |
553 if (details.reason != 'chrome_update') { | 560 if (details.reason != 'chrome_update') { |
554 storage.set({pendingDismissals: []}); | |
555 initialize(); | 561 initialize(); |
556 } | 562 } |
557 }); | 563 }); |
558 | 564 |
559 chrome.runtime.onStartup.addListener(function() { | 565 chrome.runtime.onStartup.addListener(function() { |
560 console.log('onStartup'); | 566 console.log('onStartup'); |
561 initialize(); | 567 initialize(); |
562 }); | 568 }); |
563 | 569 |
564 chrome.notifications.onClicked.addListener( | 570 chrome.notifications.onClicked.addListener( |
(...skipping 12 matching lines...) Expand all Loading... | |
577 if (!Array.isArray(actionUrls.buttonUrls)) | 583 if (!Array.isArray(actionUrls.buttonUrls)) |
578 return undefined; | 584 return undefined; |
579 | 585 |
580 return actionUrls.buttonUrls[buttonIndex]; | 586 return actionUrls.buttonUrls[buttonIndex]; |
581 }); | 587 }); |
582 }); | 588 }); |
583 | 589 |
584 chrome.notifications.onClosed.addListener(onNotificationClosed); | 590 chrome.notifications.onClosed.addListener(onNotificationClosed); |
585 | 591 |
586 chrome.location.onLocationUpdate.addListener(updateNotificationsCards); | 592 chrome.location.onLocationUpdate.addListener(updateNotificationsCards); |
OLD | NEW |