Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(124)

Unified Diff: chrome/browser/resources/google_now/background.js

Issue 207243002: Google Now Card Processing Pipeline Refactor (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase Unit Tests Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | chrome/browser/resources/google_now/background_test_util.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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);
});
});
« no previous file with comments | « no previous file | chrome/browser/resources/google_now/background_test_util.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698