| 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 534ff651b1b81b3c267085967a7630fc0b3692e2..c737168ef029501fb90b77df2b4d3191d096a4e5 100644
|
| --- a/chrome/browser/resources/google_now/background.js
|
| +++ b/chrome/browser/resources/google_now/background.js
|
| @@ -75,6 +75,7 @@ var DISMISS_RETENTION_TIME_MS = 20 * 60 * 1000; // 20 minutes
|
| var UPDATE_CARDS_TASK_NAME = 'update-cards';
|
| var DISMISS_CARD_TASK_NAME = 'dismiss-card';
|
| var RETRY_DISMISS_TASK_NAME = 'retry-dismiss';
|
| +var STATE_CHANGED_TASK_NAME = 'state-changed';
|
|
|
| var LOCATION_WATCH_NAME = 'location-watch';
|
|
|
| @@ -87,12 +88,6 @@ var WELCOME_TOAST_NOTIFICATION_ID = 'enable-now-toast';
|
| var ToastButtonIndex = {YES: 0, NO: 1};
|
|
|
| /**
|
| - * The action that the user performed on the welcome toast.
|
| - * @enum {number}
|
| - */
|
| -var ToastOptionResponse = {CHOSE_YES: 1, CHOSE_NO: 2};
|
| -
|
| -/**
|
| * Checks if a new task can't be scheduled when another task is already
|
| * scheduled.
|
| * @param {string} newTaskName Name of the new task.
|
| @@ -119,6 +114,9 @@ function areTasksConflicting(newTaskName, scheduledTaskName) {
|
| return false;
|
| }
|
|
|
| +var googleGeolocationAccessEnabledPref =
|
| + chrome.preferencesPrivate.googleGeolocationAccessEnabled;
|
| +
|
| var tasks = buildTaskManager(areTasksConflicting);
|
|
|
| // Add error processing to API calls.
|
| @@ -132,6 +130,10 @@ tasks.instrumentApiFunction(
|
| chrome.notifications.onButtonClicked, 'addListener', 0);
|
| tasks.instrumentApiFunction(chrome.notifications.onClicked, 'addListener', 0);
|
| tasks.instrumentApiFunction(chrome.notifications.onClosed, 'addListener', 0);
|
| +tasks.instrumentApiFunction(
|
| + googleGeolocationAccessEnabledPref.onChange,
|
| + 'addListener',
|
| + 0);
|
| tasks.instrumentApiFunction(chrome.runtime.onInstalled, 'addListener', 0);
|
| tasks.instrumentApiFunction(chrome.runtime.onStartup, 'addListener', 0);
|
| tasks.instrumentApiFunction(chrome.tabs, 'create', 1);
|
| @@ -392,6 +394,25 @@ function parseAndShowNotificationCards(response, callback) {
|
| }
|
|
|
| /**
|
| + * Removes all cards and card state on Google Now close down.
|
| + * For example, this occurs when the geolocation preference is unchecked in the
|
| + * content settings.
|
| + */
|
| +function removeAllCards() {
|
| + console.log('removeAllCards');
|
| +
|
| + // TODO(robliao): Once Google Now clears its own checkbox in the
|
| + // notifications center and bug 260376 is fixed, the below clearing
|
| + // code is no longer necessary.
|
| + chrome.notifications.getAll(function(notifications) {
|
| + for (var notificationId in notifications) {
|
| + chrome.notifications.clear(notificationId, function() {});
|
| + }
|
| + storage.set({notificationsData: {}});
|
| + });
|
| +}
|
| +
|
| +/**
|
| * Requests notification cards from the server.
|
| * @param {Location} position Location of this computer.
|
| * @param {function()} callback Completion callback.
|
| @@ -446,6 +467,13 @@ function requestLocation() {
|
| chrome.location.watchLocation(LOCATION_WATCH_NAME, {});
|
| }
|
|
|
| +/**
|
| + * Stops getting the location.
|
| + */
|
| +function stopRequestLocation() {
|
| + console.log('stopRequestLocation');
|
| + chrome.location.clearWatch(LOCATION_WATCH_NAME);
|
| +}
|
|
|
| /**
|
| * Obtains new location; requests and shows notification cards based on this
|
| @@ -457,15 +485,19 @@ function updateNotificationsCards(position) {
|
| ' @' + new Date());
|
| tasks.add(UPDATE_CARDS_TASK_NAME, function(callback) {
|
| console.log('updateNotificationsCards-task-begin');
|
| - updateCardsAttempts.planForNext(function() {
|
| - processPendingDismissals(function(success) {
|
| - if (success) {
|
| - // The cards are requested only if there are no unsent dismissals.
|
| - requestNotificationCards(position, callback);
|
| - } else {
|
| - callback();
|
| - }
|
| - });
|
| + updateCardsAttempts.isRunning(function(running) {
|
| + if (running) {
|
| + updateCardsAttempts.planForNext(function() {
|
| + processPendingDismissals(function(success) {
|
| + if (success) {
|
| + // The cards are requested only if there are no unsent dismissals.
|
| + requestNotificationCards(position, callback);
|
| + } else {
|
| + callback();
|
| + }
|
| + });
|
| + });
|
| + }
|
| });
|
| });
|
| }
|
| @@ -628,21 +660,17 @@ function onNotificationClicked(notificationId, selector) {
|
| * @param {number} buttonIndex The index of the button which was clicked.
|
| */
|
| function onToastNotificationClicked(buttonIndex) {
|
| + storage.set({userRespondedToToast: true});
|
| +
|
| if (buttonIndex == ToastButtonIndex.YES) {
|
| chrome.metricsPrivate.recordUserAction('GoogleNow.WelcomeToastClickedYes');
|
| - storage.set({toastState: ToastOptionResponse.CHOSE_YES});
|
| -
|
| - // TODO(zturner): Update chrome geolocation setting once the settings
|
| - // API is in place.
|
| - startPollingCards();
|
| + googleGeolocationAccessEnabledPref.set({value: true});
|
| + // The googlegeolocationaccessenabled preference change callback
|
| + // will take care of starting the poll for cards.
|
| } else {
|
| chrome.metricsPrivate.recordUserAction('GoogleNow.WelcomeToastClickedNo');
|
| - storage.set({toastState: ToastOptionResponse.CHOSE_NO});
|
| + onStateChange();
|
| }
|
| -
|
| - chrome.notifications.clear(
|
| - WELCOME_TOAST_NOTIFICATION_ID,
|
| - function(wasCleared) {});
|
| }
|
|
|
| /**
|
| @@ -658,7 +686,7 @@ function onNotificationClosed(notificationId, byUser) {
|
| // Even though they only closed the notification without clicking no, treat
|
| // it as though they clicked No anwyay, and don't show the toast again.
|
| chrome.metricsPrivate.recordUserAction('GoogleNow.WelcomeToastDismissed');
|
| - storage.set({toastState: ToastOptionResponse.CHOSE_NO});
|
| + storage.set({userRespondedToToast: true});
|
| return;
|
| }
|
|
|
| @@ -706,26 +734,143 @@ function startPollingCards() {
|
| }
|
|
|
| /**
|
| + * Stops all machinery in the polling system.
|
| + */
|
| +function stopPollingCards() {
|
| + stopRequestLocation();
|
| +
|
| + updateCardsAttempts.stop();
|
| +
|
| + removeAllCards();
|
| +}
|
| +
|
| +/**
|
| * Initializes the event page on install or on browser startup.
|
| */
|
| function initialize() {
|
| recordEvent(DiagnosticEvent.EXTENSION_START);
|
| - storage.get('toastState', function(items) {
|
| - // The toast state might be undefined (e.g. not in storage yet) if this is
|
| - // the first time ever being prompted.
|
| -
|
| - // TODO(zturner): Get the value of isGeolocationEnabled from the settings
|
| - // api and additionally make sure it is true.
|
| - if (!items.toastState) {
|
| - if (NOTIFICATION_CARDS_URL) {
|
| - chrome.identity.getAuthToken({interactive: false}, function(token) {
|
| - if (!chrome.runtime.lastError && token)
|
| - showWelcomeToast();
|
| - });
|
| +
|
| + // Alarms persist across chrome restarts. This is undesirable since it
|
| + // prevents us from starting up everything (alarms are a heuristic to
|
| + // determine if we are already running). To mitigate this, we will
|
| + // shut everything down on initialize before starting everything up.
|
| + stopPollingCards();
|
| + onStateChange();
|
| +}
|
| +
|
| +/**
|
| + * Starts or stops the polling of cards.
|
| + * @param {boolean} shouldPollCardsRequest true to start and
|
| + * false to stop polling cards.
|
| + * @param {function} onSuccess Called on completion.
|
| + */
|
| +function setShouldPollCards(shouldPollCardsRequest, onSuccess) {
|
| + tasks.debugSetStepName(
|
| + 'setShouldRun-shouldRun-updateCardsAttemptsIsRunning');
|
| + updateCardsAttempts.isRunning(function(currentValue) {
|
| + if (shouldPollCardsRequest != currentValue) {
|
| + if (shouldPollCardsRequest)
|
| + startPollingCards();
|
| + else
|
| + stopPollingCards();
|
| + }
|
| + onSuccess();
|
| + });
|
| +}
|
| +
|
| +/**
|
| + * Shows or hides the toast.
|
| + * @param {boolean} visibleRequest true to show the toast and
|
| + * false to hide the toast.
|
| + * @param {function} onSuccess Called on completion.
|
| + */
|
| +function setToastVisible(visibleRequest, onSuccess) {
|
| + tasks.debugSetStepName(
|
| + 'setToastVisible-shouldSetToastVisible-getAllNotifications');
|
| + chrome.notifications.getAll(function(notifications) {
|
| + // TODO(vadimt): Figure out what to do when notifications are disabled for
|
| + // our extension.
|
| + notifications = notifications || {};
|
| +
|
| + if (visibleRequest != !!notifications[WELCOME_TOAST_NOTIFICATION_ID]) {
|
| + if (visibleRequest)
|
| + showWelcomeToast();
|
| + else
|
| + hideWelcomeToast();
|
| + }
|
| +
|
| + onSuccess();
|
| + });
|
| +}
|
| +
|
| +/**
|
| + * Does the actual work of deciding what Google Now should do
|
| + * based off of the current state of Chrome.
|
| + * @param {boolean} signedIn true if the user is signed in.
|
| + * @param {boolean} geolocationEnabled true if
|
| + * the geolocation option is enabled.
|
| + * @param {boolean} userRespondedToToast true if
|
| + * the user has responded to the toast.
|
| + * @param {function()} callback Call this function on completion.
|
| + */
|
| +function updateRunningState(
|
| + signedIn,
|
| + geolocationEnabled,
|
| + userRespondedToToast,
|
| + callback) {
|
| +
|
| + var shouldSetToastVisible = false;
|
| + var shouldPollCards = false;
|
| +
|
| + if (signedIn) {
|
| + if (geolocationEnabled) {
|
| + if (!userRespondedToToast) {
|
| + // If the user enabled geolocation independently of Google Now,
|
| + // the user has implicitly responded to the toast.
|
| + // We do not want to show it again.
|
| + storage.set({userRespondedToToast: true});
|
| }
|
| - } else if (items.toastState == ToastOptionResponse.CHOSE_YES) {
|
| - startPollingCards();
|
| +
|
| + shouldPollCards = true;
|
| + } else {
|
| + if (!userRespondedToToast)
|
| + shouldSetToastVisible = true;
|
| }
|
| + }
|
| +
|
| + setToastVisible(shouldSetToastVisible, function() {
|
| + setShouldPollCards(shouldPollCards, callback);
|
| + });
|
| +}
|
| +
|
| +/**
|
| + * Coordinates the behavior of Google Now for Chrome depending on
|
| + * Chrome and extension state.
|
| + */
|
| +function onStateChange() {
|
| + tasks.add(STATE_CHANGED_TASK_NAME, function(callback) {
|
| + tasks.debugSetStepName('onStateChange-getAuthToken');
|
| + chrome.identity.getAuthToken({interactive: false}, function(token) {
|
| + var signedIn =
|
| + !chrome.runtime.lastError &&
|
| + token &&
|
| + !!NOTIFICATION_CARDS_URL;
|
| + tasks.debugSetStepName(
|
| + 'onStateChange-get-googleGeolocationAccessEnabledPref');
|
| + googleGeolocationAccessEnabledPref.get({}, function(prefValue) {
|
| + var geolocationEnabled = !!prefValue.value;
|
| + tasks.debugSetStepName(
|
| + 'onStateChange-get-userRespondedToToast');
|
| + storage.get('userRespondedToToast', function(items) {
|
| + var userRespondedToToast = !!items.userRespondedToToast;
|
| + updateRunningState(
|
| + signedIn,
|
| + geolocationEnabled,
|
| + userRespondedToToast,
|
| + callback);
|
| + });
|
| + });
|
| + });
|
| });
|
| }
|
|
|
| @@ -751,6 +896,15 @@ function showWelcomeToast() {
|
| function(notificationId) {});
|
| }
|
|
|
| +/**
|
| + * Hides the welcome toast.
|
| + */
|
| +function hideWelcomeToast() {
|
| + chrome.notifications.clear(
|
| + WELCOME_TOAST_NOTIFICATION_ID,
|
| + function() {});
|
| +}
|
| +
|
| chrome.runtime.onInstalled.addListener(function(details) {
|
| console.log('onInstalled ' + JSON.stringify(details));
|
| if (details.reason != 'chrome_update') {
|
| @@ -763,6 +917,11 @@ chrome.runtime.onStartup.addListener(function() {
|
| initialize();
|
| });
|
|
|
| +googleGeolocationAccessEnabledPref.onChange.addListener(function(prefValue) {
|
| + console.log('googleGeolocationAccessEnabledPref onChange ' + prefValue.value);
|
| + onStateChange();
|
| +});
|
| +
|
| chrome.notifications.onClicked.addListener(
|
| function(notificationId) {
|
| chrome.metricsPrivate.recordUserAction('GoogleNow.MessageClicked');
|
|
|