Commit d377e991 authored by robliao@chromium.org's avatar robliao@chromium.org

Add Optin Retry Logic to Google Now

Bonus Fix:
fillFromChromeLocalStorage now handles undefined defaults correctly.

BUG=353703
R=rgustafson@chromium.org, skare@chromium.org, xiyuan@chromium.org

Review URL: https://codereview.chromium.org/217263005

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@260294 0039d316-1c4b-4281-b951-d872f2087c98
parent 17ea0ae2
...@@ -51,6 +51,19 @@ var MINIMUM_POLLING_PERIOD_SECONDS = 5 * 60; // 5 minutes ...@@ -51,6 +51,19 @@ var MINIMUM_POLLING_PERIOD_SECONDS = 5 * 60; // 5 minutes
*/ */
var MAXIMUM_POLLING_PERIOD_SECONDS = 60 * 60; // 1 hour var MAXIMUM_POLLING_PERIOD_SECONDS = 60 * 60; // 1 hour
/**
* Initial period for polling for Google Now optin notification after push
* messaging indicates Google Now is enabled.
*/
var INITIAL_OPTIN_POLLING_PERIOD_SECONDS = 60; // 1 minute
/**
* Maximum period for polling for Google Now optin notification after push
* messaging indicates Google Now is enabled. It is expected that the alarm
* will be stopped after this.
*/
var MAXIMUM_OPTIN_POLLING_PERIOD_SECONDS = 16 * 60; // 16 minutes
/** /**
* Initial period for retrying the server request for dismissing cards. * Initial period for retrying the server request for dismissing cards.
*/ */
...@@ -202,6 +215,11 @@ var updateCardsAttempts = buildAttemptManager( ...@@ -202,6 +215,11 @@ var updateCardsAttempts = buildAttemptManager(
requestCards, requestCards,
INITIAL_POLLING_PERIOD_SECONDS, INITIAL_POLLING_PERIOD_SECONDS,
MAXIMUM_POLLING_PERIOD_SECONDS); MAXIMUM_POLLING_PERIOD_SECONDS);
var optInCheckAttempts = buildAttemptManager(
'optin',
pollOptedIn,
INITIAL_OPTIN_POLLING_PERIOD_SECONDS,
MAXIMUM_OPTIN_POLLING_PERIOD_SECONDS);
var dismissalAttempts = buildAttemptManager( var dismissalAttempts = buildAttemptManager(
'dismiss', 'dismiss',
retryPendingDismissals, retryPendingDismissals,
...@@ -1096,6 +1114,48 @@ function isGoogleNowEnabled() { ...@@ -1096,6 +1114,48 @@ function isGoogleNowEnabled() {
}); });
} }
/**
* Polls the optin state.
* Sometimes we get the response to the opted in result too soon during
* push messaging. We'll recheck the optin state a few times before giving up.
*/
function pollOptedIn() {
/**
* Cleans up any state used to recheck the opt-in poll.
*/
function clearPollingState() {
localStorage.removeItem('optedInCheckCount');
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 < 5) {
console.log(new Date() +
' checkOptedIn Attempt ' + localStorage.optedInCheckCount);
localStorage.optedInCheckCount++;
requestOptedIn(function() {
clearPollingState();
requestCards();
});
} else {
clearPollingState();
}
}
if (localStorage.optedInCheckCount === undefined) {
localStorage.optedInCheckCount = 0;
optInCheckAttempts.start();
checkOptedIn();
} else {
optInCheckAttempts.planForNext(checkOptedIn);
}
}
instrumented.runtime.onInstalled.addListener(function(details) { instrumented.runtime.onInstalled.addListener(function(details) {
console.log('onInstalled ' + JSON.stringify(details)); console.log('onInstalled ' + JSON.stringify(details));
if (details.reason != 'chrome_update') { if (details.reason != 'chrome_update') {
...@@ -1202,7 +1262,7 @@ instrumented.pushMessaging.onMessage.addListener(function(message) { ...@@ -1202,7 +1262,7 @@ instrumented.pushMessaging.onMessage.addListener(function(message) {
notificationGroups: items.notificationGroups notificationGroups: items.notificationGroups
}); });
requestCards(); pollOptedIn();
} }
}); });
}); });
......
...@@ -648,9 +648,22 @@ function fillFromChromeLocalStorage( ...@@ -648,9 +648,22 @@ function fillFromChromeLocalStorage(
defaultStorageObject, defaultStorageObject,
opt_allowPromiseRejection) { opt_allowPromiseRejection) {
return new Promise(function(resolve, reject) { return new Promise(function(resolve, reject) {
instrumented.storage.local.get(defaultStorageObject, function(items) { // We have to create a keys array because keys with a default value
// of undefined will cause that key to not be looked up!
var keysToGet = [];
for (var key in defaultStorageObject) {
keysToGet.push(key);
}
instrumented.storage.local.get(keysToGet, function(items) {
if (items) { if (items) {
resolve(items); // Merge the result with the default storage object to ensure all keys
// requested have either the default value or the retrieved storage
// value.
var result = {};
for (var key in defaultStorageObject) {
result[key] = (key in items) ? items[key] : defaultStorageObject[key];
}
resolve(result);
} else if (opt_allowPromiseRejection === PromiseRejection.ALLOW) { } else if (opt_allowPromiseRejection === PromiseRejection.ALLOW) {
reject(); reject();
} else { } else {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment