| Index: chrome/browser/resources/google_now/background.js
|
| diff --git a/chrome/browser/resources/google_now/background.js b/chrome/browser/resources/google_now/background.js
|
| index de130965c1d1b0add55994bff434856e53d56b65..9d2d5f95cad83fe957ca958c2f72f57a37fab24e 100644
|
| --- a/chrome/browser/resources/google_now/background.js
|
| +++ b/chrome/browser/resources/google_now/background.js
|
| @@ -16,8 +16,7 @@
|
| * 3. Showing the received cards as notifications.
|
| */
|
|
|
| -// TODO(vadimt): Decide what to do in incognito mode.
|
| -// TODO(vadimt): Figure out the final values of the constants.
|
| +// TODO(robliao): Decide what to do in incognito mode.
|
|
|
| /**
|
| * Standard response code for successful HTTP requests. This is the only success
|
| @@ -332,43 +331,43 @@ function requestFromServer(method, handlerName, opt_contentType) {
|
| }
|
|
|
| /**
|
| - * Shows parsed and combined cards as notifications.
|
| + * Shows the notification groups as notification cards.
|
| * @param {Object.<string, StoredNotificationGroup>} notificationGroups Map from
|
| * group name to group information.
|
| - * @param {Object.<ChromeNotificationId, CombinedCard>} cards Map from
|
| - * chromeNotificationId to the combined card, containing cards to show.
|
| - * @param {function()} onSuccess Called on success.
|
| - * @param {function(ReceivedNotification)=} onCardShown Optional parameter
|
| + * @param {function(ReceivedNotification)=} opt_onCardShown Optional parameter
|
| * called when each card is shown.
|
| + * @return {Promise} A promise to show the notification groups as cards.
|
| */
|
| -function showNotificationCards(
|
| - notificationGroups, cards, onSuccess, onCardShown) {
|
| - console.log('showNotificationCards ' + JSON.stringify(cards));
|
| +function showNotificationGroups(notificationGroups, opt_onCardShown) {
|
| + var cards = combineCardsFromGroups(notificationGroups);
|
| + console.log('showNotificationGroups ' + JSON.stringify(cards));
|
|
|
| - instrumented.notifications.getAll(function(notifications) {
|
| - console.log('showNotificationCards-getAll ' +
|
| - JSON.stringify(notifications));
|
| - notifications = notifications || {};
|
| -
|
| - // Mark notifications that didn't receive an update as having received
|
| - // an empty update.
|
| - for (var chromeNotificationId in notifications) {
|
| - cards[chromeNotificationId] = cards[chromeNotificationId] || [];
|
| - }
|
| + return new Promise(function(resolve) {
|
| + instrumented.notifications.getAll(function(notifications) {
|
| + console.log('showNotificationGroups-getAll ' +
|
| + JSON.stringify(notifications));
|
| + notifications = notifications || {};
|
| +
|
| + // Mark notifications that didn't receive an update as having received
|
| + // an empty update.
|
| + for (var chromeNotificationId in notifications) {
|
| + cards[chromeNotificationId] = cards[chromeNotificationId] || [];
|
| + }
|
|
|
| - /** @type {Object.<string, NotificationDataEntry>} */
|
| - var notificationsData = {};
|
| -
|
| - // Create/update/delete notifications.
|
| - for (var chromeNotificationId in cards) {
|
| - notificationsData[chromeNotificationId] = cardSet.update(
|
| - chromeNotificationId,
|
| - cards[chromeNotificationId],
|
| - notificationGroups,
|
| - onCardShown);
|
| - }
|
| - chrome.storage.local.set({notificationsData: notificationsData});
|
| - onSuccess();
|
| + /** @type {Object.<string, NotificationDataEntry>} */
|
| + var notificationsData = {};
|
| +
|
| + // Create/update/delete notifications.
|
| + for (var chromeNotificationId in cards) {
|
| + notificationsData[chromeNotificationId] = cardSet.update(
|
| + chromeNotificationId,
|
| + cards[chromeNotificationId],
|
| + notificationGroups,
|
| + opt_onCardShown);
|
| + }
|
| + chrome.storage.local.set({notificationsData: notificationsData});
|
| + resolve();
|
| + });
|
| });
|
| }
|
|
|
| @@ -457,50 +456,45 @@ function scheduleNextPoll(groups, isOptedIn) {
|
| }
|
|
|
| /**
|
| - * Combines notification groups into a set of Chrome notifications and shows
|
| - * them.
|
| + * Combines notification groups into a set of Chrome notifications.
|
| * @param {Object.<string, StoredNotificationGroup>} notificationGroups Map from
|
| * group name to group information.
|
| - * @param {function()} onSuccess Called on success.
|
| - * @param {function(ReceivedNotification)=} onCardShown Optional parameter
|
| - * called when each card is shown.
|
| + * @return {Object.<ChromeNotificationId, CombinedCard>} Cards to show.
|
| */
|
| -function combineAndShowNotificationCards(
|
| - notificationGroups, onSuccess, onCardShown) {
|
| - console.log('combineAndShowNotificationCards ' +
|
| - JSON.stringify(notificationGroups));
|
| +function combineCardsFromGroups(notificationGroups) {
|
| + console.log('combineCardsFromGroups ' + JSON.stringify(notificationGroups));
|
| /** @type {Object.<ChromeNotificationId, CombinedCard>} */
|
| var combinedCards = {};
|
|
|
| for (var groupName in notificationGroups)
|
| combineGroup(combinedCards, notificationGroups[groupName]);
|
|
|
| - showNotificationCards(
|
| - notificationGroups, combinedCards, onSuccess, onCardShown);
|
| + return combinedCards;
|
| }
|
|
|
| /**
|
| - * Based on a response from the notification server, shows notifications and
|
| - * schedules next update.
|
| + * Processes a server response for consumption by showNotificationGroups.
|
| * @param {ServerResponse} response Server response.
|
| - * @param {function(ReceivedNotification)=} onCardShown Optional parameter
|
| - * called when each card is shown.
|
| + * @return {Promise} A promise to process the server response and provide
|
| + * updated groups. Rejects if the server response shouldn't be processed.
|
| */
|
| -function processServerResponse(response, onCardShown) {
|
| +function processServerResponse(response) {
|
| console.log('processServerResponse ' + JSON.stringify(response));
|
|
|
| if (response.googleNowDisabled) {
|
| chrome.storage.local.set({googleNowEnabled: false});
|
| - // TODO(vadimt): Remove the line below once the server stops sending groups
|
| + // TODO(robliao): Remove the line below once the server stops sending groups
|
| // with 'googleNowDisabled' responses.
|
| response.groups = {};
|
| // Google Now was enabled; now it's disabled. This is a state change.
|
| onStateChange();
|
| + // Allow this to continue. We still need to do work here to clear
|
| + // the cards and schedule the next opt-in poll.
|
| }
|
|
|
| var receivedGroups = response.groups;
|
|
|
| - fillFromChromeLocalStorage({
|
| + return fillFromChromeLocalStorage({
|
| /** @type {Object.<string, StoredNotificationGroup>} */
|
| notificationGroups: {},
|
| /** @type {Object.<NotificationId, number>} */
|
| @@ -573,16 +567,10 @@ function processServerResponse(response, onCardShown) {
|
| }
|
|
|
| scheduleNextPoll(updatedGroups, !response.googleNowDisabled);
|
| - combineAndShowNotificationCards(
|
| - updatedGroups,
|
| - function() {
|
| - chrome.storage.local.set({
|
| - notificationGroups: updatedGroups,
|
| - recentDismissals: updatedRecentDismissals
|
| - });
|
| - recordEvent(GoogleNowEvent.CARDS_PARSE_SUCCESS);
|
| - },
|
| - onCardShown);
|
| + return {
|
| + updatedGroups: updatedGroups,
|
| + recentDismissals: updatedRecentDismissals
|
| + };
|
| });
|
| }
|
|
|
| @@ -594,11 +582,23 @@ function countExplanatoryCard() {
|
| }
|
|
|
| /**
|
| + * Determines if cards should have an explanation link.
|
| + * @return {boolean} true if an explanatory card should be shown.
|
| + */
|
| +function shouldShowExplanatoryCard() {
|
| + var isBelowThreshold =
|
| + localStorage['explanatoryCardsShown'] < EXPLANATORY_CARDS_LINK_THRESHOLD;
|
| + return isBelowThreshold;
|
| +}
|
| +
|
| +/**
|
| * Requests notification cards from the server for specified groups.
|
| * @param {Array.<string>} groupNames Names of groups that need to be refreshed.
|
| + * @return {Promise} A promise to request the specified notification groups.
|
| */
|
| -function requestNotificationGroups(groupNames) {
|
| - console.log('requestNotificationGroups from ' + NOTIFICATION_CARDS_URL +
|
| +function requestNotificationGroupsFromServer(groupNames) {
|
| + console.log(
|
| + 'requestNotificationGroupsFromServer from ' + NOTIFICATION_CARDS_URL +
|
| ', groupNames=' + JSON.stringify(groupNames));
|
|
|
| recordEvent(GoogleNowEvent.REQUEST_FOR_CARDS_TOTAL);
|
| @@ -606,12 +606,8 @@ function requestNotificationGroups(groupNames) {
|
| var requestParameters = '?timeZoneOffsetMs=' +
|
| (-new Date().getTimezoneOffset() * MS_IN_MINUTE);
|
|
|
| - var cardShownCallback = undefined;
|
| - var belowExplanatoryThreshold =
|
| - localStorage['explanatoryCardsShown'] < EXPLANATORY_CARDS_LINK_THRESHOLD;
|
| - if (belowExplanatoryThreshold) {
|
| + if (shouldShowExplanatoryCard()) {
|
| requestParameters += '&cardExplanation=true';
|
| - cardShownCallback = countExplanatoryCard;
|
| }
|
|
|
| groupNames.forEach(function(groupName) {
|
| @@ -620,60 +616,62 @@ function requestNotificationGroups(groupNames) {
|
|
|
| requestParameters += '&uiLocale=' + navigator.language;
|
|
|
| - console.log('requestNotificationGroups: request=' + requestParameters);
|
| + console.log(
|
| + 'requestNotificationGroupsFromServer: request=' + requestParameters);
|
|
|
| - requestFromServer('GET', 'notifications' + requestParameters).then(
|
| + return requestFromServer('GET', 'notifications' + requestParameters).then(
|
| function(request) {
|
| - console.log('requestNotificationGroups-received ' + request.status);
|
| + console.log(
|
| + 'requestNotificationGroupsFromServer-received ' + request.status);
|
| if (request.status == HTTP_OK) {
|
| recordEvent(GoogleNowEvent.REQUEST_FOR_CARDS_SUCCESS);
|
| - processServerResponse(
|
| - JSON.parse(request.responseText), cardShownCallback);
|
| + return JSON.parse(request.responseText);
|
| }
|
| });
|
| }
|
|
|
| /**
|
| - * Requests the account opted-in state from the server.
|
| - * @param {function()} optedInCallback Function that will be called if
|
| - * opted-in state is 'true'.
|
| + * Requests the account opted-in state from the server and updates any
|
| + * state as necessary.
|
| + * @return {Promise} A promise to request and update the opted-in state.
|
| + * The promise resolves if the opt-in state is true.
|
| */
|
| -function requestOptedIn(optedInCallback) {
|
| +function requestAndUpdateOptedIn() {
|
| console.log('requestOptedIn from ' + NOTIFICATION_CARDS_URL);
|
|
|
| - requestFromServer('GET', 'settings/optin').then(function(request) {
|
| + return requestFromServer('GET', 'settings/optin').then(function(request) {
|
| console.log(
|
| 'requestOptedIn-received ' + request.status + ' ' + request.response);
|
| if (request.status == HTTP_OK) {
|
| var parsedResponse = JSON.parse(request.responseText);
|
| - if (parsedResponse.value) {
|
| - chrome.storage.local.set({googleNowEnabled: true});
|
| - optedInCallback();
|
| - // Google Now was disabled, now it's enabled. This is a state change.
|
| - onStateChange();
|
| - } else {
|
| - scheduleNextPoll({}, false);
|
| - }
|
| + return parsedResponse.value;
|
| + } else {
|
| + return Promise.reject();
|
| + }
|
| + }).then(function(optedIn) {
|
| + if (optedIn) {
|
| + chrome.storage.local.set({googleNowEnabled: true});
|
| + // Google Now was disabled, now it's enabled. This is a state change.
|
| + onStateChange();
|
| + return Promise.resolve();
|
| + } else {
|
| + scheduleNextPoll({}, false);
|
| + return Promise.reject();
|
| }
|
| });
|
| }
|
|
|
| /**
|
| - * Requests notification cards from the server.
|
| + * Determines the groups that need to be requested right now.
|
| + * @return {Promise} A promise to determine the groups to request.
|
| */
|
| -function requestNotificationCards() {
|
| - console.log('requestNotificationCards');
|
| -
|
| - fillFromChromeLocalStorage({
|
| +function getGroupsToRequest() {
|
| + return fillFromChromeLocalStorage({
|
| /** @type {Object.<string, StoredNotificationGroup>} */
|
| - notificationGroups: {},
|
| - googleNowEnabled: false
|
| + notificationGroups: {}
|
| }).then(function(items) {
|
| - console.log(
|
| - 'requestNotificationCards-storage-get ' + JSON.stringify(items));
|
| -
|
| + console.log('getGroupsToRequest-storage-get ' + JSON.stringify(items));
|
| var groupsToRequest = [];
|
| -
|
| var now = Date.now();
|
|
|
| for (var groupName in items.notificationGroups) {
|
| @@ -681,15 +679,38 @@ function requestNotificationCards() {
|
| if (group.nextPollTime !== undefined && group.nextPollTime <= now)
|
| groupsToRequest.push(groupName);
|
| }
|
| + return groupsToRequest;
|
| + });
|
| +}
|
|
|
| - if (items.googleNowEnabled) {
|
| - requestNotificationGroups(groupsToRequest);
|
| - } else {
|
| - requestOptedIn(function() {
|
| - requestNotificationGroups(groupsToRequest);
|
| +/**
|
| + * Requests notification cards from the server.
|
| + * @return {Promise} A promise to request the notification cards.
|
| + * Rejects if the cards won't be requested.
|
| + */
|
| +function requestNotificationCards() {
|
| + console.log('requestNotificationCards');
|
| +
|
| + return isGoogleNowEnabled()
|
| + .then(function(googleNowEnabled) {
|
| + return googleNowEnabled ? Promise.resolve() : requestAndUpdateOptedIn();
|
| + })
|
| + .then(getGroupsToRequest)
|
| + .then(requestNotificationGroupsFromServer)
|
| + .then(processServerResponse)
|
| + .then(function(processedResponse) {
|
| + var onCardShown =
|
| + shouldShowExplanatoryCard() ? countExplanatoryCard : undefined;
|
| + return showNotificationGroups(
|
| + processedResponse.updatedGroups, onCardShown).then(function() {
|
| + chrome.storage.local.set({
|
| + notificationGroups: processedResponse.updatedGroups,
|
| + recentDismissals: processedResponse.updatedRecentDismissals
|
| + });
|
| + recordEvent(GoogleNowEvent.CARDS_PARSE_SUCCESS);
|
| + }
|
| + );
|
| });
|
| - }
|
| - });
|
| }
|
|
|
| /**
|
| @@ -932,7 +953,6 @@ function startPollingCards() {
|
| // Create an update timer for a case when for some reason requesting
|
| // cards gets stuck.
|
| updateCardsAttempts.start(MAXIMUM_POLLING_PERIOD_SECONDS);
|
| -
|
| requestCards();
|
| }
|
|
|
| @@ -943,9 +963,10 @@ function stopPollingCards() {
|
| console.log('stopPollingCards');
|
| updateCardsAttempts.stop();
|
| removeAllCards();
|
| - // Mark the Google Now as disabled to start with checking the opt-in state
|
| - // next time startPollingCards() is called.
|
| - chrome.storage.local.set({googleNowEnabled: false});
|
| + // Since we're stopping everything, clear all runtime storage too.
|
| + // We don't clear localStorage since those values are still relevant
|
| + // across Google Now start-stop events.
|
| + chrome.storage.local.clear();
|
| }
|
|
|
| /**
|
| @@ -1128,32 +1149,25 @@ function pollOptedIn() {
|
| optInCheckAttempts.stop();
|
| }
|
|
|
| - /**
|
| - * Performs the actual work for checking the opt-in state and requesting cards
|
| - * on opted-in.
|
| - */
|
| - function checkOptedIn() {
|
| - // Limit retries to 5.
|
| + if (localStorage.optedInCheckCount === undefined) {
|
| + localStorage.optedInCheckCount = 0;
|
| + optInCheckAttempts.start();
|
| + }
|
| +
|
| + console.log(new Date() +
|
| + ' checkOptedIn Attempt ' + localStorage.optedInCheckCount);
|
| +
|
| + requestAndUpdateOptedIn().then(function() {
|
| + clearPollingState();
|
| + requestCards();
|
| + }).catch(function() {
|
| if (localStorage.optedInCheckCount < 5) {
|
| - console.log(new Date() +
|
| - ' checkOptedIn Attempt ' + localStorage.optedInCheckCount);
|
| localStorage.optedInCheckCount++;
|
| - requestOptedIn(function() {
|
| - clearPollingState();
|
| - requestCards();
|
| - });
|
| + optInCheckAttempts.planForNext(function() {});
|
| } else {
|
| clearPollingState();
|
| }
|
| - }
|
| -
|
| - if (localStorage.optedInCheckCount === undefined) {
|
| - localStorage.optedInCheckCount = 0;
|
| - optInCheckAttempts.start();
|
| - checkOptedIn();
|
| - } else {
|
| - optInCheckAttempts.planForNext(checkOptedIn);
|
| - }
|
| + });
|
| }
|
|
|
| instrumented.runtime.onInstalled.addListener(function(details) {
|
| @@ -1176,7 +1190,7 @@ instrumented.runtime.onStartup.addListener(function() {
|
| }).then(function(items) {
|
| console.log('onStartup-get ' + JSON.stringify(items));
|
|
|
| - combineAndShowNotificationCards(items.notificationGroups, function() {
|
| + showNotificationGroups(items.notificationGroups).then(function() {
|
| chrome.storage.local.set(items);
|
| });
|
| });
|
|
|