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 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
199 'preferencesPrivate.googleGeolocationAccessEnabled.get', | 199 'preferencesPrivate.googleGeolocationAccessEnabled.get', |
200 1); | 200 1); |
201 wrapper.instrumentChromeApiFunction( | 201 wrapper.instrumentChromeApiFunction( |
202 'preferencesPrivate.googleGeolocationAccessEnabled.onChange.addListener', | 202 'preferencesPrivate.googleGeolocationAccessEnabled.onChange.addListener', |
203 0); | 203 0); |
204 wrapper.instrumentChromeApiFunction('permissions.contains', 1); | 204 wrapper.instrumentChromeApiFunction('permissions.contains', 1); |
205 wrapper.instrumentChromeApiFunction('pushMessaging.onMessage.addListener', 0); | 205 wrapper.instrumentChromeApiFunction('pushMessaging.onMessage.addListener', 0); |
206 wrapper.instrumentChromeApiFunction('runtime.onInstalled.addListener', 0); | 206 wrapper.instrumentChromeApiFunction('runtime.onInstalled.addListener', 0); |
207 wrapper.instrumentChromeApiFunction('runtime.onStartup.addListener', 0); | 207 wrapper.instrumentChromeApiFunction('runtime.onStartup.addListener', 0); |
208 wrapper.instrumentChromeApiFunction('tabs.create', 1); | 208 wrapper.instrumentChromeApiFunction('tabs.create', 1); |
209 wrapper.instrumentChromeApiFunction('storage.local.get', 1); | |
210 | 209 |
211 var updateCardsAttempts = buildAttemptManager( | 210 var updateCardsAttempts = buildAttemptManager( |
212 'cards-update', | 211 'cards-update', |
213 requestLocation, | 212 requestLocation, |
214 INITIAL_POLLING_PERIOD_SECONDS, | 213 INITIAL_POLLING_PERIOD_SECONDS, |
215 MAXIMUM_POLLING_PERIOD_SECONDS); | 214 MAXIMUM_POLLING_PERIOD_SECONDS); |
216 var dismissalAttempts = buildAttemptManager( | 215 var dismissalAttempts = buildAttemptManager( |
217 'dismiss', | 216 'dismiss', |
218 retryPendingDismissals, | 217 retryPendingDismissals, |
219 INITIAL_RETRY_DISMISS_PERIOD_SECONDS, | 218 INITIAL_RETRY_DISMISS_PERIOD_SECONDS, |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
451 chrome.storage.local.set({googleNowEnabled: false}); | 450 chrome.storage.local.set({googleNowEnabled: false}); |
452 // TODO(vadimt): Remove the line below once the server stops sending groups | 451 // TODO(vadimt): Remove the line below once the server stops sending groups |
453 // with 'googleNowDisabled' responses. | 452 // with 'googleNowDisabled' responses. |
454 response.groups = {}; | 453 response.groups = {}; |
455 // Google Now was enabled; now it's disabled. This is a state change. | 454 // Google Now was enabled; now it's disabled. This is a state change. |
456 onStateChange(); | 455 onStateChange(); |
457 } | 456 } |
458 | 457 |
459 var receivedGroups = response.groups; | 458 var receivedGroups = response.groups; |
460 | 459 |
461 instrumented.storage.local.get( | 460 fillFromChromeLocalStorage({ |
462 ['notificationGroups', 'recentDismissals'], | 461 /** @type {Object.<string, StoredNotificationGroup>} */ |
463 function(items) { | 462 notificationGroups: {}, |
464 console.log( | 463 /** @type {Object.<NotificationId, number>} */ |
465 'processServerResponse-get ' + JSON.stringify(items)); | 464 recentDismissals: {} |
466 items = items || {}; | 465 }).then(function(items) { |
467 /** @type {Object.<string, StoredNotificationGroup>} */ | 466 console.log('processServerResponse-get ' + JSON.stringify(items)); |
468 items.notificationGroups = items.notificationGroups || {}; | |
469 /** @type {Object.<NotificationId, number>} */ | |
470 items.recentDismissals = items.recentDismissals || {}; | |
471 | 467 |
472 // Build a set of non-expired recent dismissals. It will be used for | 468 // Build a set of non-expired recent dismissals. It will be used for |
473 // client-side filtering of cards. | 469 // client-side filtering of cards. |
474 /** @type {Object.<NotificationId, number>} */ | 470 /** @type {Object.<NotificationId, number>} */ |
475 var updatedRecentDismissals = {}; | 471 var updatedRecentDismissals = {}; |
476 var now = Date.now(); | 472 var now = Date.now(); |
477 for (var notificationId in items.recentDismissals) { | 473 for (var notificationId in items.recentDismissals) { |
478 var dismissalAge = now - items.recentDismissals[notificationId]; | 474 var dismissalAge = now - items.recentDismissals[notificationId]; |
479 if (dismissalAge < DISMISS_RETENTION_TIME_MS) { | 475 if (dismissalAge < DISMISS_RETENTION_TIME_MS) { |
480 updatedRecentDismissals[notificationId] = | 476 updatedRecentDismissals[notificationId] = |
481 items.recentDismissals[notificationId]; | 477 items.recentDismissals[notificationId]; |
482 } | 478 } |
479 } | |
480 | |
481 // Populate groups with corresponding cards. | |
482 if (response.notifications) { | |
483 for (var i = 0; i < response.notifications.length; ++i) { | |
484 /** @type {ReceivedNotification} */ | |
485 var card = response.notifications[i]; | |
486 if (!(card.notificationId in updatedRecentDismissals)) { | |
487 var group = receivedGroups[card.groupName]; | |
488 group.cards = group.cards || []; | |
489 group.cards.push(card); | |
483 } | 490 } |
491 } | |
492 } | |
484 | 493 |
485 // Populate groups with corresponding cards. | 494 // Build updated set of groups. |
486 if (response.notifications) { | 495 var updatedGroups = {}; |
487 for (var i = 0; i < response.notifications.length; ++i) { | |
488 /** @type {ReceivedNotification} */ | |
489 var card = response.notifications[i]; | |
490 if (!(card.notificationId in updatedRecentDismissals)) { | |
491 var group = receivedGroups[card.groupName]; | |
492 group.cards = group.cards || []; | |
493 group.cards.push(card); | |
494 } | |
495 } | |
496 } | |
497 | 496 |
498 // Build updated set of groups. | 497 for (var groupName in receivedGroups) { |
499 var updatedGroups = {}; | 498 var receivedGroup = receivedGroups[groupName]; |
499 var storedGroup = items.notificationGroups[groupName] || { | |
500 cards: [], | |
501 cardsTimestamp: undefined, | |
502 nextPollTime: undefined, | |
503 rank: undefined | |
504 }; | |
500 | 505 |
501 for (var groupName in receivedGroups) { | 506 if (receivedGroup.requested) |
502 var receivedGroup = receivedGroups[groupName]; | 507 receivedGroup.cards = receivedGroup.cards || []; |
503 var storedGroup = items.notificationGroups[groupName] || { | |
504 cards: [], | |
505 cardsTimestamp: undefined, | |
506 nextPollTime: undefined, | |
507 rank: undefined | |
508 }; | |
509 | 508 |
510 if (receivedGroup.requested) | 509 if (receivedGroup.cards) { |
511 receivedGroup.cards = receivedGroup.cards || []; | 510 // If the group contains a cards update, all its fields will get new |
511 // values. | |
512 storedGroup.cards = receivedGroup.cards; | |
513 storedGroup.cardsTimestamp = now; | |
514 storedGroup.rank = receivedGroup.rank; | |
515 storedGroup.nextPollTime = undefined; | |
516 // The code below assigns nextPollTime a defined value if | |
517 // nextPollSeconds is specified in the received group. | |
518 // If the group's cards are not updated, and nextPollSeconds is | |
519 // unspecified, this method doesn't change group's nextPollTime. | |
520 } | |
512 | 521 |
513 if (receivedGroup.cards) { | 522 // 'nextPollSeconds' may be sent even for groups that don't contain |
514 // If the group contains a cards update, all its fields will get new | 523 // cards updates. |
515 // values. | 524 if (receivedGroup.nextPollSeconds !== undefined) { |
516 storedGroup.cards = receivedGroup.cards; | 525 storedGroup.nextPollTime = |
517 storedGroup.cardsTimestamp = now; | 526 now + receivedGroup.nextPollSeconds * MS_IN_SECOND; |
518 storedGroup.rank = receivedGroup.rank; | 527 } |
519 storedGroup.nextPollTime = undefined; | |
520 // The code below assigns nextPollTime a defined value if | |
521 // nextPollSeconds is specified in the received group. | |
522 // If the group's cards are not updated, and nextPollSeconds is | |
523 // unspecified, this method doesn't change group's nextPollTime. | |
524 } | |
525 | 528 |
526 // 'nextPollSeconds' may be sent even for groups that don't contain | 529 updatedGroups[groupName] = storedGroup; |
527 // cards updates. | 530 } |
528 if (receivedGroup.nextPollSeconds !== undefined) { | |
529 storedGroup.nextPollTime = | |
530 now + receivedGroup.nextPollSeconds * MS_IN_SECOND; | |
531 } | |
532 | 531 |
533 updatedGroups[groupName] = storedGroup; | 532 scheduleNextPoll(updatedGroups, !response.googleNowDisabled); |
534 } | 533 combineAndShowNotificationCards( |
535 | 534 updatedGroups, |
536 scheduleNextPoll(updatedGroups, !response.googleNowDisabled); | 535 function() { |
537 combineAndShowNotificationCards( | 536 chrome.storage.local.set({ |
538 updatedGroups, | 537 notificationGroups: updatedGroups, |
539 function() { | 538 recentDismissals: updatedRecentDismissals |
540 chrome.storage.local.set({ | 539 }); |
541 notificationGroups: updatedGroups, | 540 recordEvent(GoogleNowEvent.CARDS_PARSE_SUCCESS); |
542 recentDismissals: updatedRecentDismissals | 541 }, |
543 }); | 542 onCardShown); |
544 recordEvent(GoogleNowEvent.CARDS_PARSE_SUCCESS); | 543 }); |
545 }, | |
546 onCardShown); | |
547 }); | |
548 } | 544 } |
549 | 545 |
550 /** | 546 /** |
551 * Update the Explanatory Total Cards Shown Count. | 547 * Update the Explanatory Total Cards Shown Count. |
552 */ | 548 */ |
553 function countExplanatoryCard() { | 549 function countExplanatoryCard() { |
554 localStorage['explanatoryCardsShown']++; | 550 localStorage['explanatoryCardsShown']++; |
555 } | 551 } |
556 | 552 |
557 /** | 553 /** |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
632 }); | 628 }); |
633 } | 629 } |
634 | 630 |
635 /** | 631 /** |
636 * Requests notification cards from the server. | 632 * Requests notification cards from the server. |
637 * @param {Location=} position Location of this computer. | 633 * @param {Location=} position Location of this computer. |
638 */ | 634 */ |
639 function requestNotificationCards(position) { | 635 function requestNotificationCards(position) { |
640 console.log('requestNotificationCards ' + JSON.stringify(position)); | 636 console.log('requestNotificationCards ' + JSON.stringify(position)); |
641 | 637 |
642 instrumented.storage.local.get( | 638 fillFromChromeLocalStorage({ |
643 ['notificationGroups', 'googleNowEnabled'], function(items) { | |
644 console.log('requestNotificationCards-storage-get ' + | |
645 JSON.stringify(items)); | |
646 items = items || {}; | |
647 /** @type {Object.<string, StoredNotificationGroup>} */ | 639 /** @type {Object.<string, StoredNotificationGroup>} */ |
648 items.notificationGroups = items.notificationGroups || {}; | 640 notificationGroups: {}, |
641 googleNowEnabled: false | |
642 }).then(function(items) { | |
643 console.log( | |
644 'requestNotificationCards-storage-get ' + JSON.stringify(items)); | |
649 | 645 |
650 var groupsToRequest = []; | 646 var groupsToRequest = []; |
651 | 647 |
652 var now = Date.now(); | 648 var now = Date.now(); |
653 | 649 |
654 for (var groupName in items.notificationGroups) { | 650 for (var groupName in items.notificationGroups) { |
655 var group = items.notificationGroups[groupName]; | 651 var group = items.notificationGroups[groupName]; |
656 if (group.nextPollTime !== undefined && group.nextPollTime <= now) | 652 if (group.nextPollTime !== undefined && group.nextPollTime <= now) |
657 groupsToRequest.push(groupName); | 653 groupsToRequest.push(groupName); |
658 } | 654 } |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
784 callbackBoolean(false); | 780 callbackBoolean(false); |
785 }); | 781 }); |
786 } | 782 } |
787 | 783 |
788 /** | 784 /** |
789 * Tries to send dismiss requests for all pending dismissals. | 785 * Tries to send dismiss requests for all pending dismissals. |
790 * @param {function(boolean)} callbackBoolean Completion callback with 'success' | 786 * @param {function(boolean)} callbackBoolean Completion callback with 'success' |
791 * parameter. Success means that no pending dismissals are left. | 787 * parameter. Success means that no pending dismissals are left. |
792 */ | 788 */ |
793 function processPendingDismissals(callbackBoolean) { | 789 function processPendingDismissals(callbackBoolean) { |
794 instrumented.storage.local.get(['pendingDismissals', 'recentDismissals'], | 790 fillFromChromeLocalStorage({ |
795 function(items) { | 791 /** @type {Array.<PendingDismissal>} */ |
796 console.log('processPendingDismissals-storage-get ' + | 792 pendingDismissals: [], |
797 JSON.stringify(items)); | 793 /** @type {Object.<NotificationId, number>} */ |
798 items = items || {}; | 794 recentDismissals: {} |
799 /** @type {Array.<PendingDismissal>} */ | 795 }).then(function(items) { |
800 items.pendingDismissals = items.pendingDismissals || []; | 796 console.log( |
801 /** @type {Object.<NotificationId, number>} */ | 797 'processPendingDismissals-storage-get ' + JSON.stringify(items)); |
802 items.recentDismissals = items.recentDismissals || {}; | |
803 | 798 |
804 var dismissalsChanged = false; | 799 var dismissalsChanged = false; |
805 | 800 |
806 function onFinish(success) { | 801 function onFinish(success) { |
807 if (dismissalsChanged) { | 802 if (dismissalsChanged) { |
808 chrome.storage.local.set({ | 803 chrome.storage.local.set({ |
809 pendingDismissals: items.pendingDismissals, | 804 pendingDismissals: items.pendingDismissals, |
810 recentDismissals: items.recentDismissals | 805 recentDismissals: items.recentDismissals |
811 }); | 806 }); |
812 } | 807 } |
813 callbackBoolean(success); | 808 callbackBoolean(success); |
814 } | 809 } |
815 | 810 |
816 function doProcessDismissals() { | 811 function doProcessDismissals() { |
817 if (items.pendingDismissals.length == 0) { | 812 if (items.pendingDismissals.length == 0) { |
818 dismissalAttempts.stop(); | 813 dismissalAttempts.stop(); |
819 onFinish(true); | 814 onFinish(true); |
820 return; | 815 return; |
821 } | 816 } |
822 | 817 |
823 // Send dismissal for the first card, and if successful, repeat | 818 // Send dismissal for the first card, and if successful, repeat |
824 // recursively with the rest. | 819 // recursively with the rest. |
825 /** @type {PendingDismissal} */ | 820 /** @type {PendingDismissal} */ |
826 var dismissal = items.pendingDismissals[0]; | 821 var dismissal = items.pendingDismissals[0]; |
827 requestCardDismissal( | 822 requestCardDismissal( |
828 dismissal.chromeNotificationId, | 823 dismissal.chromeNotificationId, |
829 dismissal.time, | 824 dismissal.time, |
830 dismissal.dismissalData, | 825 dismissal.dismissalData, |
831 function(done) { | 826 function(done) { |
832 if (done) { | 827 if (done) { |
833 dismissalsChanged = true; | 828 dismissalsChanged = true; |
834 items.pendingDismissals.splice(0, 1); | 829 items.pendingDismissals.splice(0, 1); |
835 items.recentDismissals[ | 830 items.recentDismissals[ |
836 dismissal.dismissalData.notificationId] = | 831 dismissal.dismissalData.notificationId] = |
837 Date.now(); | 832 Date.now(); |
838 doProcessDismissals(); | 833 doProcessDismissals(); |
839 } else { | 834 } else { |
840 onFinish(false); | 835 onFinish(false); |
841 } | 836 } |
842 }); | 837 }); |
843 } | 838 } |
844 | 839 |
845 doProcessDismissals(); | 840 doProcessDismissals(); |
846 }); | 841 }); |
847 } | 842 } |
848 | 843 |
849 /** | 844 /** |
850 * Submits a task to send pending dismissals. | 845 * Submits a task to send pending dismissals. |
851 */ | 846 */ |
852 function retryPendingDismissals() { | 847 function retryPendingDismissals() { |
853 tasks.add(RETRY_DISMISS_TASK_NAME, function() { | 848 tasks.add(RETRY_DISMISS_TASK_NAME, function() { |
854 dismissalAttempts.planForNext(function() { | 849 dismissalAttempts.planForNext(function() { |
855 processPendingDismissals(function(success) {}); | 850 processPendingDismissals(function(success) {}); |
856 }); | 851 }); |
(...skipping 15 matching lines...) Expand all Loading... | |
872 | 867 |
873 /** | 868 /** |
874 * Opens URL corresponding to the clicked part of the notification. | 869 * Opens URL corresponding to the clicked part of the notification. |
875 * @param {ChromeNotificationId} chromeNotificationId chrome.notifications ID of | 870 * @param {ChromeNotificationId} chromeNotificationId chrome.notifications ID of |
876 * the card. | 871 * the card. |
877 * @param {function((ActionUrls|undefined)): (string|undefined)} selector | 872 * @param {function((ActionUrls|undefined)): (string|undefined)} selector |
878 * Function that extracts the url for the clicked area from the button | 873 * Function that extracts the url for the clicked area from the button |
879 * action URLs info. | 874 * action URLs info. |
880 */ | 875 */ |
881 function onNotificationClicked(chromeNotificationId, selector) { | 876 function onNotificationClicked(chromeNotificationId, selector) { |
882 instrumented.storage.local.get('notificationsData', function(items) { | 877 fillFromChromeLocalStorage({ |
883 /** @type {(NotificationDataEntry|undefined)} */ | 878 /** @type {NotificationDataEntry} */ |
rgustafson
2014/02/27 21:32:09
Object.<ChromeNotificationId or string,Notificatio
robliao
2014/02/27 23:52:36
Noted, and that clarification should really be don
| |
884 var notificationData = items && | 879 notificationsData: {} |
885 items.notificationsData && | 880 }).then(function(items) { |
886 items.notificationsData[chromeNotificationId]; | 881 var notificationData = items.notificationsData[chromeNotificationId]; |
887 | |
888 if (!notificationData) | 882 if (!notificationData) |
889 return; | 883 return; |
890 | 884 |
891 var url = selector(notificationData.actionUrls); | 885 var url = selector(notificationData.actionUrls); |
892 if (!url) | 886 if (!url) |
893 return; | 887 return; |
894 | 888 |
895 openUrl(url); | 889 openUrl(url); |
896 }); | 890 }); |
897 } | 891 } |
898 | 892 |
899 /** | 893 /** |
900 * Callback for chrome.notifications.onClosed event. | 894 * Callback for chrome.notifications.onClosed event. |
901 * @param {ChromeNotificationId} chromeNotificationId chrome.notifications ID of | 895 * @param {ChromeNotificationId} chromeNotificationId chrome.notifications ID of |
902 * the card. | 896 * the card. |
903 * @param {boolean} byUser Whether the notification was closed by the user. | 897 * @param {boolean} byUser Whether the notification was closed by the user. |
904 */ | 898 */ |
905 function onNotificationClosed(chromeNotificationId, byUser) { | 899 function onNotificationClosed(chromeNotificationId, byUser) { |
906 if (!byUser) | 900 if (!byUser) |
907 return; | 901 return; |
908 | 902 |
909 // At this point we are guaranteed that the notification is a now card. | 903 // At this point we are guaranteed that the notification is a now card. |
910 chrome.metricsPrivate.recordUserAction('GoogleNow.Dismissed'); | 904 chrome.metricsPrivate.recordUserAction('GoogleNow.Dismissed'); |
911 | 905 |
912 tasks.add(DISMISS_CARD_TASK_NAME, function() { | 906 tasks.add(DISMISS_CARD_TASK_NAME, function() { |
913 dismissalAttempts.start(); | 907 dismissalAttempts.start(); |
914 | 908 |
915 instrumented.storage.local.get( | 909 fillFromChromeLocalStorage({ |
916 ['pendingDismissals', 'notificationsData', 'notificationGroups'], | 910 /** @type {Array.<PendingDismissal>} */ |
917 function(items) { | 911 pendingDismissals: [], |
918 items = items || {}; | 912 /** @type {Object.<string, NotificationDataEntry>} */ |
919 /** @type {Array.<PendingDismissal>} */ | 913 notificationsData: {}, |
920 items.pendingDismissals = items.pendingDismissals || []; | 914 /** @type {Object.<string, StoredNotificationGroup>} */ |
921 /** @type {Object.<string, NotificationDataEntry>} */ | 915 notificationGroups: {} |
922 items.notificationsData = items.notificationsData || {}; | 916 }).then(function(items) { |
923 /** @type {Object.<string, StoredNotificationGroup>} */ | 917 /** @type {NotificationDataEntry} */ |
924 items.notificationGroups = items.notificationGroups || {}; | 918 var notificationData = |
919 items.notificationsData[chromeNotificationId] || | |
920 { | |
921 timestamp: Date.now(), | |
922 combinedCard: [] | |
923 }; | |
925 | 924 |
926 /** @type {NotificationDataEntry} */ | 925 var dismissalResult = |
927 var notificationData = | 926 cardSet.onDismissal( |
928 items.notificationsData[chromeNotificationId] || | 927 chromeNotificationId, |
929 { | 928 notificationData, |
930 timestamp: Date.now(), | 929 items.notificationGroups); |
931 combinedCard: [] | |
932 }; | |
933 | 930 |
934 var dismissalResult = | 931 for (var i = 0; i < dismissalResult.dismissals.length; i++) { |
935 cardSet.onDismissal( | 932 /** @type {PendingDismissal} */ |
936 chromeNotificationId, | 933 var dismissal = { |
937 notificationData, | 934 chromeNotificationId: chromeNotificationId, |
938 items.notificationGroups); | 935 time: Date.now(), |
936 dismissalData: dismissalResult.dismissals[i] | |
937 }; | |
938 items.pendingDismissals.push(dismissal); | |
939 } | |
939 | 940 |
940 for (var i = 0; i < dismissalResult.dismissals.length; i++) { | 941 items.notificationsData[chromeNotificationId] = |
941 /** @type {PendingDismissal} */ | 942 dismissalResult.notificationData; |
942 var dismissal = { | |
943 chromeNotificationId: chromeNotificationId, | |
944 time: Date.now(), | |
945 dismissalData: dismissalResult.dismissals[i] | |
946 }; | |
947 items.pendingDismissals.push(dismissal); | |
948 } | |
949 | 943 |
950 items.notificationsData[chromeNotificationId] = | 944 chrome.storage.local.set(items); |
951 dismissalResult.notificationData; | |
952 | 945 |
953 chrome.storage.local.set(items); | 946 processPendingDismissals(function(success) {}); |
954 | 947 }); |
955 processPendingDismissals(function(success) {}); | |
956 }); | |
957 }); | 948 }); |
958 } | 949 } |
959 | 950 |
960 /** | 951 /** |
961 * Initializes the polling system to start monitoring location and fetching | 952 * Initializes the polling system to start monitoring location and fetching |
962 * cards. | 953 * cards. |
963 */ | 954 */ |
964 function startPollingCards() { | 955 function startPollingCards() { |
965 // Create an update timer for a case when for some reason location request | 956 // Create an update timer for a case when for some reason location request |
966 // gets stuck. | 957 // gets stuck. |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1138 }); | 1129 }); |
1139 }); | 1130 }); |
1140 } | 1131 } |
1141 | 1132 |
1142 /** | 1133 /** |
1143 * Gets the previous Google Now opt-in state. | 1134 * Gets the previous Google Now opt-in state. |
1144 * @return {Promise} A promise to determine the previous Google Now | 1135 * @return {Promise} A promise to determine the previous Google Now |
1145 * opt-in state. | 1136 * opt-in state. |
1146 */ | 1137 */ |
1147 function isGoogleNowEnabled() { | 1138 function isGoogleNowEnabled() { |
1148 return new Promise(function(resolve) { | 1139 return fillFromChromeLocalStorage({googleNowEnabled: false}) |
1149 instrumented.storage.local.get('googleNowEnabled', function(items) { | 1140 .then(function(items) { |
1150 resolve(items && !!items.googleNowEnabled); | 1141 return items.googleNowEnabled; |
1151 }); | 1142 }); |
1152 }); | |
1153 } | 1143 } |
1154 | 1144 |
1155 instrumented.runtime.onInstalled.addListener(function(details) { | 1145 instrumented.runtime.onInstalled.addListener(function(details) { |
1156 console.log('onInstalled ' + JSON.stringify(details)); | 1146 console.log('onInstalled ' + JSON.stringify(details)); |
1157 if (details.reason != 'chrome_update') { | 1147 if (details.reason != 'chrome_update') { |
1158 initialize(); | 1148 initialize(); |
1159 } | 1149 } |
1160 }); | 1150 }); |
1161 | 1151 |
1162 instrumented.runtime.onStartup.addListener(function() { | 1152 instrumented.runtime.onStartup.addListener(function() { |
1163 console.log('onStartup'); | 1153 console.log('onStartup'); |
1164 | 1154 |
1165 // Show notifications received by earlier polls. Doing this as early as | 1155 // Show notifications received by earlier polls. Doing this as early as |
1166 // possible to reduce latency of showing first notifications. This mimics how | 1156 // possible to reduce latency of showing first notifications. This mimics how |
1167 // persistent notifications will work. | 1157 // persistent notifications will work. |
1168 tasks.add(SHOW_ON_START_TASK_NAME, function() { | 1158 tasks.add(SHOW_ON_START_TASK_NAME, function() { |
1169 instrumented.storage.local.get('notificationGroups', function(items) { | 1159 fillFromChromeLocalStorage({ |
1160 /** @type {Object.<string, StoredNotificationGroup>} */ | |
1161 notificationGroups: {} | |
1162 }).then(function(items) { | |
1170 console.log('onStartup-get ' + JSON.stringify(items)); | 1163 console.log('onStartup-get ' + JSON.stringify(items)); |
1171 items = items || {}; | |
1172 /** @type {Object.<string, StoredNotificationGroup>} */ | |
1173 items.notificationGroups = items.notificationGroups || {}; | |
1174 | 1164 |
1175 combineAndShowNotificationCards(items.notificationGroups, function() { | 1165 combineAndShowNotificationCards(items.notificationGroups, function() { |
1176 chrome.storage.local.set(items); | 1166 chrome.storage.local.set(items); |
1177 }); | 1167 }); |
1178 }); | 1168 }); |
1179 }); | 1169 }); |
1180 | 1170 |
1181 initialize(); | 1171 initialize(); |
1182 }); | 1172 }); |
1183 | 1173 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1233 }); | 1223 }); |
1234 | 1224 |
1235 instrumented.pushMessaging.onMessage.addListener(function(message) { | 1225 instrumented.pushMessaging.onMessage.addListener(function(message) { |
1236 // message.payload will be '' when the extension first starts. | 1226 // message.payload will be '' when the extension first starts. |
1237 // Each time after signing in, we'll get latest payload for all channels. | 1227 // Each time after signing in, we'll get latest payload for all channels. |
1238 // So, we need to poll the server only when the payload is non-empty and has | 1228 // So, we need to poll the server only when the payload is non-empty and has |
1239 // changed. | 1229 // changed. |
1240 console.log('pushMessaging.onMessage ' + JSON.stringify(message)); | 1230 console.log('pushMessaging.onMessage ' + JSON.stringify(message)); |
1241 if (message.payload.indexOf('REQUEST_CARDS') == 0) { | 1231 if (message.payload.indexOf('REQUEST_CARDS') == 0) { |
1242 tasks.add(ON_PUSH_MESSAGE_START_TASK_NAME, function() { | 1232 tasks.add(ON_PUSH_MESSAGE_START_TASK_NAME, function() { |
1243 instrumented.storage.local.get( | 1233 // Accept promise rejection on failure since it's safer to do nothing, |
1244 ['lastPollNowPayloads', 'notificationGroups'], function(items) { | 1234 // preventing polling the server when the payload really didn't change. |
1245 // If storage.get fails, it's safer to do nothing, preventing polling | 1235 fillFromChromeLocalStorage({ |
1246 // the server when the payload really didn't change. | 1236 lastPollNowPayloads: {}, |
1247 if (!items) | 1237 /** @type {Object.<string, StoredNotificationGroup>} */ |
1248 return; | 1238 notificationGroups: {} |
1249 | 1239 }, PromiseRejection.ALLOW).then(function(items) { |
1250 // If this is the first time we get lastPollNowPayloads, initialize it. | |
1251 items.lastPollNowPayloads = items.lastPollNowPayloads || {}; | |
1252 | |
1253 if (items.lastPollNowPayloads[message.subchannelId] != | 1240 if (items.lastPollNowPayloads[message.subchannelId] != |
1254 message.payload) { | 1241 message.payload) { |
1255 items.lastPollNowPayloads[message.subchannelId] = message.payload; | 1242 items.lastPollNowPayloads[message.subchannelId] = message.payload; |
1256 | 1243 |
1257 /** @type {Object.<string, StoredNotificationGroup>} */ | |
1258 items.notificationGroups = items.notificationGroups || {}; | |
1259 items.notificationGroups['PUSH' + message.subchannelId] = { | 1244 items.notificationGroups['PUSH' + message.subchannelId] = { |
1260 cards: [], | 1245 cards: [], |
1261 nextPollTime: Date.now() | 1246 nextPollTime: Date.now() |
1262 }; | 1247 }; |
1263 | 1248 |
1264 chrome.storage.local.set({ | 1249 chrome.storage.local.set({ |
1265 lastPollNowPayloads: items.lastPollNowPayloads, | 1250 lastPollNowPayloads: items.lastPollNowPayloads, |
1266 notificationGroups: items.notificationGroups | 1251 notificationGroups: items.notificationGroups |
1267 }); | 1252 }); |
1268 | 1253 |
1269 updateNotificationsCards(); | 1254 updateNotificationsCards(); |
1270 } | 1255 } |
1271 }); | 1256 }); |
1272 }); | 1257 }); |
1273 } | 1258 } |
1274 }); | 1259 }); |
OLD | NEW |