Chromium Code Reviews| 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 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 630 }); | 626 }); |
| 631 } | 627 } |
| 632 | 628 |
| 633 /** | 629 /** |
| 634 * Requests notification cards from the server. | 630 * Requests notification cards from the server. |
| 635 * @param {Location=} position Location of this computer. | 631 * @param {Location=} position Location of this computer. |
| 636 */ | 632 */ |
| 637 function requestNotificationCards(position) { | 633 function requestNotificationCards(position) { |
| 638 console.log('requestNotificationCards ' + JSON.stringify(position)); | 634 console.log('requestNotificationCards ' + JSON.stringify(position)); |
| 639 | 635 |
| 640 instrumented.storage.local.get( | 636 fillFromChromeLocalStorage({ |
| 641 ['notificationGroups', 'googleNowEnabled'], function(items) { | |
| 642 console.log('requestNotificationCards-storage-get ' + | |
| 643 JSON.stringify(items)); | |
| 644 items = items || {}; | |
| 645 /** @type {Object.<string, StoredNotificationGroup>} */ | 637 /** @type {Object.<string, StoredNotificationGroup>} */ |
| 646 items.notificationGroups = items.notificationGroups || {}; | 638 notificationGroups: {}, |
| 639 googleNowEnabled: false | |
| 640 }).then(function(items) { | |
| 641 console.log( | |
| 642 'requestNotificationCards-storage-get ' + JSON.stringify(items)); | |
| 647 | 643 |
| 648 var groupsToRequest = []; | 644 var groupsToRequest = []; |
| 649 | 645 |
| 650 var now = Date.now(); | 646 var now = Date.now(); |
| 651 | 647 |
| 652 for (var groupName in items.notificationGroups) { | 648 for (var groupName in items.notificationGroups) { |
| 653 var group = items.notificationGroups[groupName]; | 649 var group = items.notificationGroups[groupName]; |
| 654 if (group.nextPollTime !== undefined && group.nextPollTime <= now) | 650 if (group.nextPollTime !== undefined && group.nextPollTime <= now) |
| 655 groupsToRequest.push(groupName); | 651 groupsToRequest.push(groupName); |
| 656 } | 652 } |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 782 callbackBoolean(false); | 778 callbackBoolean(false); |
| 783 }); | 779 }); |
| 784 } | 780 } |
| 785 | 781 |
| 786 /** | 782 /** |
| 787 * Tries to send dismiss requests for all pending dismissals. | 783 * Tries to send dismiss requests for all pending dismissals. |
| 788 * @param {function(boolean)} callbackBoolean Completion callback with 'success' | 784 * @param {function(boolean)} callbackBoolean Completion callback with 'success' |
| 789 * parameter. Success means that no pending dismissals are left. | 785 * parameter. Success means that no pending dismissals are left. |
| 790 */ | 786 */ |
| 791 function processPendingDismissals(callbackBoolean) { | 787 function processPendingDismissals(callbackBoolean) { |
| 792 instrumented.storage.local.get(['pendingDismissals', 'recentDismissals'], | 788 fillFromChromeLocalStorage({ |
| 793 function(items) { | 789 /** @type {Array.<PendingDismissal>} */ |
| 794 console.log('processPendingDismissals-storage-get ' + | 790 pendingDismissals: [], |
| 795 JSON.stringify(items)); | 791 /** @type {Object.<NotificationId, number>} */ |
| 796 items = items || {}; | 792 recentDismissals: {} |
| 797 /** @type {Array.<PendingDismissal>} */ | 793 }).then(function(items) { |
| 798 items.pendingDismissals = items.pendingDismissals || []; | 794 console.log( |
| 799 /** @type {Object.<NotificationId, number>} */ | 795 'processPendingDismissals-storage-get ' + JSON.stringify(items)); |
| 800 items.recentDismissals = items.recentDismissals || {}; | |
| 801 | 796 |
| 802 var dismissalsChanged = false; | 797 var dismissalsChanged = false; |
| 803 | 798 |
| 804 function onFinish(success) { | 799 function onFinish(success) { |
| 805 if (dismissalsChanged) { | 800 if (dismissalsChanged) { |
| 806 chrome.storage.local.set({ | 801 chrome.storage.local.set({ |
| 807 pendingDismissals: items.pendingDismissals, | 802 pendingDismissals: items.pendingDismissals, |
| 808 recentDismissals: items.recentDismissals | 803 recentDismissals: items.recentDismissals |
| 809 }); | 804 }); |
| 810 } | 805 } |
| 811 callbackBoolean(success); | 806 callbackBoolean(success); |
| 812 } | 807 } |
| 813 | 808 |
| 814 function doProcessDismissals() { | 809 function doProcessDismissals() { |
| 815 if (items.pendingDismissals.length == 0) { | 810 if (items.pendingDismissals.length == 0) { |
| 816 dismissalAttempts.stop(); | 811 dismissalAttempts.stop(); |
| 817 onFinish(true); | 812 onFinish(true); |
| 818 return; | 813 return; |
| 819 } | 814 } |
| 820 | 815 |
| 821 // Send dismissal for the first card, and if successful, repeat | 816 // Send dismissal for the first card, and if successful, repeat |
| 822 // recursively with the rest. | 817 // recursively with the rest. |
| 823 /** @type {PendingDismissal} */ | 818 /** @type {PendingDismissal} */ |
| 824 var dismissal = items.pendingDismissals[0]; | 819 var dismissal = items.pendingDismissals[0]; |
| 825 requestCardDismissal( | 820 requestCardDismissal( |
| 826 dismissal.chromeNotificationId, | 821 dismissal.chromeNotificationId, |
| 827 dismissal.time, | 822 dismissal.time, |
| 828 dismissal.dismissalData, | 823 dismissal.dismissalData, |
| 829 function(done) { | 824 function(done) { |
| 830 if (done) { | 825 if (done) { |
| 831 dismissalsChanged = true; | 826 dismissalsChanged = true; |
| 832 items.pendingDismissals.splice(0, 1); | 827 items.pendingDismissals.splice(0, 1); |
| 833 items.recentDismissals[ | 828 items.recentDismissals[ |
| 834 dismissal.dismissalData.notificationId] = | 829 dismissal.dismissalData.notificationId] = |
| 835 Date.now(); | 830 Date.now(); |
| 836 doProcessDismissals(); | 831 doProcessDismissals(); |
| 837 } else { | 832 } else { |
| 838 onFinish(false); | 833 onFinish(false); |
| 839 } | 834 } |
| 840 }); | 835 }); |
| 841 } | 836 } |
| 842 | 837 |
| 843 doProcessDismissals(); | 838 doProcessDismissals(); |
| 844 }); | 839 }); |
| 845 } | 840 } |
| 846 | 841 |
| 847 /** | 842 /** |
| 848 * Submits a task to send pending dismissals. | 843 * Submits a task to send pending dismissals. |
| 849 */ | 844 */ |
| 850 function retryPendingDismissals() { | 845 function retryPendingDismissals() { |
| 851 tasks.add(RETRY_DISMISS_TASK_NAME, function() { | 846 tasks.add(RETRY_DISMISS_TASK_NAME, function() { |
| 852 dismissalAttempts.planForNext(function() { | 847 dismissalAttempts.planForNext(function() { |
| 853 processPendingDismissals(function(success) {}); | 848 processPendingDismissals(function(success) {}); |
| 854 }); | 849 }); |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 870 | 865 |
| 871 /** | 866 /** |
| 872 * Opens URL corresponding to the clicked part of the notification. | 867 * Opens URL corresponding to the clicked part of the notification. |
| 873 * @param {ChromeNotificationId} chromeNotificationId chrome.notifications ID of | 868 * @param {ChromeNotificationId} chromeNotificationId chrome.notifications ID of |
| 874 * the card. | 869 * the card. |
| 875 * @param {function((ActionUrls|undefined)): (string|undefined)} selector | 870 * @param {function((ActionUrls|undefined)): (string|undefined)} selector |
| 876 * Function that extracts the url for the clicked area from the button | 871 * Function that extracts the url for the clicked area from the button |
| 877 * action URLs info. | 872 * action URLs info. |
| 878 */ | 873 */ |
| 879 function onNotificationClicked(chromeNotificationId, selector) { | 874 function onNotificationClicked(chromeNotificationId, selector) { |
| 880 instrumented.storage.local.get('notificationsData', function(items) { | 875 fillFromChromeLocalStorage({ |
| 881 /** @type {(NotificationDataEntry|undefined)} */ | 876 /** @type {NotificationDataEntry} */ |
| 882 var notificationData = items && | 877 notificationsData: {} |
| 883 items.notificationsData && | 878 }).then(function(items) { |
| 884 items.notificationsData[chromeNotificationId]; | 879 var notificationData = items.notificationsData[chromeNotificationId]; |
| 885 | |
| 886 if (!notificationData) | 880 if (!notificationData) |
| 887 return; | 881 return; |
| 888 | 882 |
| 889 var url = selector(notificationData.actionUrls); | 883 var url = selector(notificationData.actionUrls); |
| 890 if (!url) | 884 if (!url) |
| 891 return; | 885 return; |
| 892 | 886 |
| 893 openUrl(url); | 887 openUrl(url); |
| 894 }); | 888 }); |
| 895 } | 889 } |
| 896 | 890 |
| 897 /** | 891 /** |
| 898 * Callback for chrome.notifications.onClosed event. | 892 * Callback for chrome.notifications.onClosed event. |
| 899 * @param {ChromeNotificationId} chromeNotificationId chrome.notifications ID of | 893 * @param {ChromeNotificationId} chromeNotificationId chrome.notifications ID of |
| 900 * the card. | 894 * the card. |
| 901 * @param {boolean} byUser Whether the notification was closed by the user. | 895 * @param {boolean} byUser Whether the notification was closed by the user. |
| 902 */ | 896 */ |
| 903 function onNotificationClosed(chromeNotificationId, byUser) { | 897 function onNotificationClosed(chromeNotificationId, byUser) { |
| 904 if (!byUser) | 898 if (!byUser) |
| 905 return; | 899 return; |
| 906 | 900 |
| 907 // At this point we are guaranteed that the notification is a now card. | 901 // At this point we are guaranteed that the notification is a now card. |
| 908 chrome.metricsPrivate.recordUserAction('GoogleNow.Dismissed'); | 902 chrome.metricsPrivate.recordUserAction('GoogleNow.Dismissed'); |
| 909 | 903 |
| 910 tasks.add(DISMISS_CARD_TASK_NAME, function() { | 904 tasks.add(DISMISS_CARD_TASK_NAME, function() { |
| 911 dismissalAttempts.start(); | 905 dismissalAttempts.start(); |
| 912 | 906 |
| 913 instrumented.storage.local.get( | 907 fillFromChromeLocalStorage({ |
| 914 ['pendingDismissals', 'notificationsData', 'notificationGroups'], | 908 /** @type {Array.<PendingDismissal>} */ |
| 915 function(items) { | 909 pendingDismissals: [], |
| 916 items = items || {}; | 910 /** @type {Object.<string, NotificationDataEntry>} */ |
| 917 /** @type {Array.<PendingDismissal>} */ | 911 notificationsData: {}, |
| 918 items.pendingDismissals = items.pendingDismissals || []; | 912 /** @type {Object.<string, StoredNotificationGroup>} */ |
| 919 /** @type {Object.<string, NotificationDataEntry>} */ | 913 notificationGroups: {} |
| 920 items.notificationsData = items.notificationsData || {}; | 914 }).then(function(items) { |
| 921 /** @type {Object.<string, StoredNotificationGroup>} */ | 915 /** @type {NotificationDataEntry} */ |
| 922 items.notificationGroups = items.notificationGroups || {}; | 916 var notificationData = |
| 917 items.notificationsData[chromeNotificationId] || | |
| 918 { | |
| 919 timestamp: Date.now(), | |
| 920 combinedCard: [] | |
| 921 }; | |
| 923 | 922 |
| 924 /** @type {NotificationDataEntry} */ | 923 var dismissalResult = |
| 925 var notificationData = | 924 cardSet.onDismissal( |
| 926 items.notificationsData[chromeNotificationId] || | 925 chromeNotificationId, |
| 927 { | 926 notificationData, |
| 928 timestamp: Date.now(), | 927 items.notificationGroups); |
| 929 combinedCard: [] | |
| 930 }; | |
| 931 | 928 |
| 932 var dismissalResult = | 929 for (var i = 0; i < dismissalResult.dismissals.length; i++) { |
| 933 cardSet.onDismissal( | 930 /** @type {PendingDismissal} */ |
| 934 chromeNotificationId, | 931 var dismissal = { |
| 935 notificationData, | 932 chromeNotificationId: chromeNotificationId, |
| 936 items.notificationGroups); | 933 time: Date.now(), |
| 934 dismissalData: dismissalResult.dismissals[i] | |
| 935 }; | |
| 936 items.pendingDismissals.push(dismissal); | |
| 937 } | |
| 937 | 938 |
| 938 for (var i = 0; i < dismissalResult.dismissals.length; i++) { | 939 items.notificationsData[chromeNotificationId] = |
| 939 /** @type {PendingDismissal} */ | 940 dismissalResult.notificationData; |
| 940 var dismissal = { | |
| 941 chromeNotificationId: chromeNotificationId, | |
| 942 time: Date.now(), | |
| 943 dismissalData: dismissalResult.dismissals[i] | |
| 944 }; | |
| 945 items.pendingDismissals.push(dismissal); | |
| 946 } | |
| 947 | 941 |
| 948 items.notificationsData[chromeNotificationId] = | 942 chrome.storage.local.set(items); |
| 949 dismissalResult.notificationData; | |
| 950 | 943 |
| 951 chrome.storage.local.set(items); | 944 processPendingDismissals(function(success) {}); |
| 952 | 945 }); |
| 953 processPendingDismissals(function(success) {}); | |
| 954 }); | |
| 955 }); | 946 }); |
| 956 } | 947 } |
| 957 | 948 |
| 958 /** | 949 /** |
| 959 * Initializes the polling system to start monitoring location and fetching | 950 * Initializes the polling system to start monitoring location and fetching |
| 960 * cards. | 951 * cards. |
| 961 */ | 952 */ |
| 962 function startPollingCards() { | 953 function startPollingCards() { |
| 963 // Create an update timer for a case when for some reason location request | 954 // Create an update timer for a case when for some reason location request |
| 964 // gets stuck. | 955 // gets stuck. |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1084 */ | 1075 */ |
| 1085 function onStateChange() { | 1076 function onStateChange() { |
| 1086 tasks.add(STATE_CHANGED_TASK_NAME, function() { | 1077 tasks.add(STATE_CHANGED_TASK_NAME, function() { |
| 1087 Promise.all([ | 1078 Promise.all([ |
| 1088 authenticationManager.isSignedIn(), | 1079 authenticationManager.isSignedIn(), |
| 1089 isGeolocationEnabled(), | 1080 isGeolocationEnabled(), |
| 1090 canEnableBackground(), | 1081 canEnableBackground(), |
| 1091 isNotificationsEnabled(), | 1082 isNotificationsEnabled(), |
| 1092 isGoogleNowEnabled()]) | 1083 isGoogleNowEnabled()]) |
| 1093 .then(function(results) { | 1084 .then(function(results) { |
| 1085 console.log(results); | |
|
skare_
2014/02/20 00:17:12
temporary?
robliao
2014/02/21 21:25:45
Yup! Done.
On 2014/02/20 00:17:12, Travis Skare wr
| |
| 1094 updateRunningState.apply(null, results); | 1086 updateRunningState.apply(null, results); |
| 1095 }); | 1087 }); |
| 1096 }); | 1088 }); |
| 1097 } | 1089 } |
| 1098 | 1090 |
| 1099 /** | 1091 /** |
| 1100 * Gets the geolocation enabled preference. | 1092 * Gets the geolocation enabled preference. |
| 1101 * @return {Promise} A promise to get the geolocation enabled preference. | 1093 * @return {Promise} A promise to get the geolocation enabled preference. |
| 1102 */ | 1094 */ |
| 1103 function isGeolocationEnabled() { | 1095 function isGeolocationEnabled() { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1136 }); | 1128 }); |
| 1137 }); | 1129 }); |
| 1138 } | 1130 } |
| 1139 | 1131 |
| 1140 /** | 1132 /** |
| 1141 * Gets the previous Google Now opt-in state. | 1133 * Gets the previous Google Now opt-in state. |
| 1142 * @return {Promise} A promise to determine the previous Google Now | 1134 * @return {Promise} A promise to determine the previous Google Now |
| 1143 * opt-in state. | 1135 * opt-in state. |
| 1144 */ | 1136 */ |
| 1145 function isGoogleNowEnabled() { | 1137 function isGoogleNowEnabled() { |
| 1146 return new Promise(function(resolve) { | 1138 return fillFromChromeLocalStorage({googleNowEnabled: false}) |
| 1147 instrumented.storage.local.get('googleNowEnabled', function(items) { | 1139 .then(function(items) { |
| 1148 resolve(items && !!items.googleNowEnabled); | 1140 return items.googleNowEnabled; |
| 1149 }); | 1141 }); |
| 1150 }); | |
| 1151 } | 1142 } |
| 1152 | 1143 |
| 1153 instrumented.runtime.onInstalled.addListener(function(details) { | 1144 instrumented.runtime.onInstalled.addListener(function(details) { |
| 1154 console.log('onInstalled ' + JSON.stringify(details)); | 1145 console.log('onInstalled ' + JSON.stringify(details)); |
| 1155 if (details.reason != 'chrome_update') { | 1146 if (details.reason != 'chrome_update') { |
| 1156 initialize(); | 1147 initialize(); |
| 1157 } | 1148 } |
| 1158 }); | 1149 }); |
| 1159 | 1150 |
| 1160 instrumented.runtime.onStartup.addListener(function() { | 1151 instrumented.runtime.onStartup.addListener(function() { |
| 1161 console.log('onStartup'); | 1152 console.log('onStartup'); |
| 1162 | 1153 |
| 1163 // Show notifications received by earlier polls. Doing this as early as | 1154 // Show notifications received by earlier polls. Doing this as early as |
| 1164 // possible to reduce latency of showing first notifications. This mimics how | 1155 // possible to reduce latency of showing first notifications. This mimics how |
| 1165 // persistent notifications will work. | 1156 // persistent notifications will work. |
| 1166 tasks.add(SHOW_ON_START_TASK_NAME, function() { | 1157 tasks.add(SHOW_ON_START_TASK_NAME, function() { |
| 1167 instrumented.storage.local.get('notificationGroups', function(items) { | 1158 fillFromChromeLocalStorage({ |
| 1159 /** @type {Object.<string, StoredNotificationGroup>} */ | |
| 1160 notificationGroups: {} | |
| 1161 }).then(function(items) { | |
| 1168 console.log('onStartup-get ' + JSON.stringify(items)); | 1162 console.log('onStartup-get ' + JSON.stringify(items)); |
| 1169 items = items || {}; | |
| 1170 /** @type {Object.<string, StoredNotificationGroup>} */ | |
| 1171 items.notificationGroups = items.notificationGroups || {}; | |
| 1172 | 1163 |
| 1173 combineAndShowNotificationCards(items.notificationGroups, function() { | 1164 combineAndShowNotificationCards(items.notificationGroups, function() { |
| 1174 chrome.storage.local.set(items); | 1165 chrome.storage.local.set(items); |
| 1175 }); | 1166 }); |
| 1176 }); | 1167 }); |
| 1177 }); | 1168 }); |
| 1178 | 1169 |
| 1179 initialize(); | 1170 initialize(); |
| 1180 }); | 1171 }); |
| 1181 | 1172 |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1231 }); | 1222 }); |
| 1232 | 1223 |
| 1233 instrumented.pushMessaging.onMessage.addListener(function(message) { | 1224 instrumented.pushMessaging.onMessage.addListener(function(message) { |
| 1234 // message.payload will be '' when the extension first starts. | 1225 // message.payload will be '' when the extension first starts. |
| 1235 // Each time after signing in, we'll get latest payload for all channels. | 1226 // Each time after signing in, we'll get latest payload for all channels. |
| 1236 // So, we need to poll the server only when the payload is non-empty and has | 1227 // So, we need to poll the server only when the payload is non-empty and has |
| 1237 // changed. | 1228 // changed. |
| 1238 console.log('pushMessaging.onMessage ' + JSON.stringify(message)); | 1229 console.log('pushMessaging.onMessage ' + JSON.stringify(message)); |
| 1239 if (message.payload.indexOf('REQUEST_CARDS') == 0) { | 1230 if (message.payload.indexOf('REQUEST_CARDS') == 0) { |
| 1240 tasks.add(ON_PUSH_MESSAGE_START_TASK_NAME, function() { | 1231 tasks.add(ON_PUSH_MESSAGE_START_TASK_NAME, function() { |
| 1241 instrumented.storage.local.get( | 1232 // Accept promise rejection on failure since it's safer to do nothing, |
| 1242 ['lastPollNowPayloads', 'notificationGroups'], function(items) { | 1233 // preventing polling the server when the payload really didn't change. |
| 1243 // If storage.get fails, it's safer to do nothing, preventing polling | 1234 fillFromChromeLocalStorage({ |
| 1244 // the server when the payload really didn't change. | 1235 lastPollNowPayloads: {}, |
| 1245 if (!items) | 1236 /** @type {Object.<string, StoredNotificationGroup>} */ |
| 1246 return; | 1237 notificationGroups: {} |
| 1247 | 1238 }, ALLOW_PROMISE_REJECTION).then(function(items) { |
| 1248 // If this is the first time we get lastPollNowPayloads, initialize it. | |
| 1249 items.lastPollNowPayloads = items.lastPollNowPayloads || {}; | |
| 1250 | |
| 1251 if (items.lastPollNowPayloads[message.subchannelId] != | 1239 if (items.lastPollNowPayloads[message.subchannelId] != |
| 1252 message.payload) { | 1240 message.payload) { |
| 1253 items.lastPollNowPayloads[message.subchannelId] = message.payload; | 1241 items.lastPollNowPayloads[message.subchannelId] = message.payload; |
| 1254 | 1242 |
| 1255 /** @type {Object.<string, StoredNotificationGroup>} */ | |
| 1256 items.notificationGroups = items.notificationGroups || {}; | |
| 1257 items.notificationGroups['PUSH' + message.subchannelId] = { | 1243 items.notificationGroups['PUSH' + message.subchannelId] = { |
| 1258 cards: [], | 1244 cards: [], |
| 1259 nextPollTime: Date.now() | 1245 nextPollTime: Date.now() |
| 1260 }; | 1246 }; |
| 1261 | 1247 |
| 1262 chrome.storage.local.set({ | 1248 chrome.storage.local.set({ |
| 1263 lastPollNowPayloads: items.lastPollNowPayloads, | 1249 lastPollNowPayloads: items.lastPollNowPayloads, |
| 1264 notificationGroups: items.notificationGroups | 1250 notificationGroups: items.notificationGroups |
| 1265 }); | 1251 }); |
| 1266 | 1252 |
| 1267 updateNotificationsCards(); | 1253 updateNotificationsCards(); |
| 1268 } | 1254 } |
| 1269 }); | 1255 }); |
| 1270 }); | 1256 }); |
| 1271 } | 1257 } |
| 1272 }); | 1258 }); |
| OLD | NEW |