| 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 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 68 * Time we keep dismissals after successful server dismiss requests. | 68 * Time we keep dismissals after successful server dismiss requests. |
| 69 */ | 69 */ |
| 70 var DISMISS_RETENTION_TIME_MS = 20 * 60 * 1000; // 20 minutes | 70 var DISMISS_RETENTION_TIME_MS = 20 * 60 * 1000; // 20 minutes |
| 71 | 71 |
| 72 /** | 72 /** |
| 73 * Names for tasks that can be created by the extension. | 73 * Names for tasks that can be created by the extension. |
| 74 */ | 74 */ |
| 75 var UPDATE_CARDS_TASK_NAME = 'update-cards'; | 75 var UPDATE_CARDS_TASK_NAME = 'update-cards'; |
| 76 var DISMISS_CARD_TASK_NAME = 'dismiss-card'; | 76 var DISMISS_CARD_TASK_NAME = 'dismiss-card'; |
| 77 var RETRY_DISMISS_TASK_NAME = 'retry-dismiss'; | 77 var RETRY_DISMISS_TASK_NAME = 'retry-dismiss'; |
| 78 var STATE_CHANGED_TASK_NAME = 'state-changed'; |
| 78 | 79 |
| 79 var LOCATION_WATCH_NAME = 'location-watch'; | 80 var LOCATION_WATCH_NAME = 'location-watch'; |
| 80 | 81 |
| 81 var WELCOME_TOAST_NOTIFICATION_ID = 'enable-now-toast'; | 82 var WELCOME_TOAST_NOTIFICATION_ID = 'enable-now-toast'; |
| 82 | 83 |
| 83 /** | 84 /** |
| 84 * The indices of the buttons that are displayed on the welcome toast. | 85 * The indices of the buttons that are displayed on the welcome toast. |
| 85 * @enum {number} | 86 * @enum {number} |
| 86 */ | 87 */ |
| 87 var ToastButtonIndex = {YES: 0, NO: 1}; | 88 var ToastButtonIndex = {YES: 0, NO: 1}; |
| 88 | 89 |
| 89 /** | 90 /** |
| 90 * The action that the user performed on the welcome toast. | |
| 91 * @enum {number} | |
| 92 */ | |
| 93 var ToastOptionResponse = {CHOSE_YES: 1, CHOSE_NO: 2}; | |
| 94 | |
| 95 /** | |
| 96 * Checks if a new task can't be scheduled when another task is already | 91 * Checks if a new task can't be scheduled when another task is already |
| 97 * scheduled. | 92 * scheduled. |
| 98 * @param {string} newTaskName Name of the new task. | 93 * @param {string} newTaskName Name of the new task. |
| 99 * @param {string} scheduledTaskName Name of the scheduled task. | 94 * @param {string} scheduledTaskName Name of the scheduled task. |
| 100 * @return {boolean} Whether the new task conflicts with the existing task. | 95 * @return {boolean} Whether the new task conflicts with the existing task. |
| 101 */ | 96 */ |
| 102 function areTasksConflicting(newTaskName, scheduledTaskName) { | 97 function areTasksConflicting(newTaskName, scheduledTaskName) { |
| 103 if (newTaskName == UPDATE_CARDS_TASK_NAME && | 98 if (newTaskName == UPDATE_CARDS_TASK_NAME && |
| 104 scheduledTaskName == UPDATE_CARDS_TASK_NAME) { | 99 scheduledTaskName == UPDATE_CARDS_TASK_NAME) { |
| 105 // If a card update is requested while an old update is still scheduled, we | 100 // If a card update is requested while an old update is still scheduled, we |
| 106 // don't need the new update. | 101 // don't need the new update. |
| 107 return true; | 102 return true; |
| 108 } | 103 } |
| 109 | 104 |
| 110 if (newTaskName == RETRY_DISMISS_TASK_NAME && | 105 if (newTaskName == RETRY_DISMISS_TASK_NAME && |
| 111 (scheduledTaskName == UPDATE_CARDS_TASK_NAME || | 106 (scheduledTaskName == UPDATE_CARDS_TASK_NAME || |
| 112 scheduledTaskName == DISMISS_CARD_TASK_NAME || | 107 scheduledTaskName == DISMISS_CARD_TASK_NAME || |
| 113 scheduledTaskName == RETRY_DISMISS_TASK_NAME)) { | 108 scheduledTaskName == RETRY_DISMISS_TASK_NAME)) { |
| 114 // No need to schedule retry-dismiss action if another action that tries to | 109 // No need to schedule retry-dismiss action if another action that tries to |
| 115 // send dismissals is scheduled. | 110 // send dismissals is scheduled. |
| 116 return true; | 111 return true; |
| 117 } | 112 } |
| 118 | 113 |
| 119 return false; | 114 return false; |
| 120 } | 115 } |
| 121 | 116 |
| 117 var googleGeolocationAccessEnabledPref = |
| 118 chrome.preferencesPrivate.googleGeolocationAccessEnabled; |
| 119 |
| 122 var tasks = buildTaskManager(areTasksConflicting); | 120 var tasks = buildTaskManager(areTasksConflicting); |
| 123 | 121 |
| 124 // Add error processing to API calls. | 122 // Add error processing to API calls. |
| 125 tasks.instrumentApiFunction(chrome.identity, 'getAuthToken', 1); | 123 tasks.instrumentApiFunction(chrome.identity, 'getAuthToken', 1); |
| 126 tasks.instrumentApiFunction(chrome.identity, 'removeCachedAuthToken', 1); | 124 tasks.instrumentApiFunction(chrome.identity, 'removeCachedAuthToken', 1); |
| 127 tasks.instrumentApiFunction(chrome.location.onLocationUpdate, 'addListener', 0); | 125 tasks.instrumentApiFunction(chrome.location.onLocationUpdate, 'addListener', 0); |
| 128 tasks.instrumentApiFunction(chrome.notifications, 'create', 2); | 126 tasks.instrumentApiFunction(chrome.notifications, 'create', 2); |
| 129 tasks.instrumentApiFunction(chrome.notifications, 'update', 2); | 127 tasks.instrumentApiFunction(chrome.notifications, 'update', 2); |
| 130 tasks.instrumentApiFunction(chrome.notifications, 'getAll', 0); | 128 tasks.instrumentApiFunction(chrome.notifications, 'getAll', 0); |
| 131 tasks.instrumentApiFunction( | 129 tasks.instrumentApiFunction( |
| 132 chrome.notifications.onButtonClicked, 'addListener', 0); | 130 chrome.notifications.onButtonClicked, 'addListener', 0); |
| 133 tasks.instrumentApiFunction(chrome.notifications.onClicked, 'addListener', 0); | 131 tasks.instrumentApiFunction(chrome.notifications.onClicked, 'addListener', 0); |
| 134 tasks.instrumentApiFunction(chrome.notifications.onClosed, 'addListener', 0); | 132 tasks.instrumentApiFunction(chrome.notifications.onClosed, 'addListener', 0); |
| 133 tasks.instrumentApiFunction( |
| 134 googleGeolocationAccessEnabledPref.onChange, |
| 135 'addListener', |
| 136 0); |
| 135 tasks.instrumentApiFunction(chrome.runtime.onInstalled, 'addListener', 0); | 137 tasks.instrumentApiFunction(chrome.runtime.onInstalled, 'addListener', 0); |
| 136 tasks.instrumentApiFunction(chrome.runtime.onStartup, 'addListener', 0); | 138 tasks.instrumentApiFunction(chrome.runtime.onStartup, 'addListener', 0); |
| 137 tasks.instrumentApiFunction(chrome.tabs, 'create', 1); | 139 tasks.instrumentApiFunction(chrome.tabs, 'create', 1); |
| 138 tasks.instrumentApiFunction(storage, 'get', 1); | 140 tasks.instrumentApiFunction(storage, 'get', 1); |
| 139 | 141 |
| 140 var updateCardsAttempts = buildAttemptManager( | 142 var updateCardsAttempts = buildAttemptManager( |
| 141 'cards-update', | 143 'cards-update', |
| 142 requestLocation, | 144 requestLocation, |
| 143 INITIAL_POLLING_PERIOD_SECONDS, | 145 INITIAL_POLLING_PERIOD_SECONDS, |
| 144 MAXIMUM_POLLING_PERIOD_SECONDS); | 146 MAXIMUM_POLLING_PERIOD_SECONDS); |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 323 storage.set({ | 325 storage.set({ |
| 324 notificationsData: newNotificationsData, | 326 notificationsData: newNotificationsData, |
| 325 recentDismissals: updatedRecentDismissals | 327 recentDismissals: updatedRecentDismissals |
| 326 }); | 328 }); |
| 327 callback(); | 329 callback(); |
| 328 }); | 330 }); |
| 329 }); | 331 }); |
| 330 } | 332 } |
| 331 | 333 |
| 332 /** | 334 /** |
| 335 * Removes all cards and card state on Google Now close down. |
| 336 * For example, this occurs when the geolocation preference is unchecked in the |
| 337 * content settings. |
| 338 */ |
| 339 function removeAllCards() { |
| 340 console.log('removeAllCards'); |
| 341 |
| 342 // TODO(robliao): Once Google Now clears its own checkbox in the |
| 343 // notifications center and bug 260376 is fixed, the below clearing |
| 344 // code is no longer necessary. |
| 345 chrome.notifications.getAll(function(notifications) { |
| 346 for (var notificationId in notifications) { |
| 347 chrome.notifications.clear(notificationId, function() {}); |
| 348 } |
| 349 storage.set({notificationsData: {}}); |
| 350 }); |
| 351 } |
| 352 |
| 353 /** |
| 333 * Requests notification cards from the server. | 354 * Requests notification cards from the server. |
| 334 * @param {Location} position Location of this computer. | 355 * @param {Location} position Location of this computer. |
| 335 * @param {function()} callback Completion callback. | 356 * @param {function()} callback Completion callback. |
| 336 */ | 357 */ |
| 337 function requestNotificationCards(position, callback) { | 358 function requestNotificationCards(position, callback) { |
| 338 console.log('requestNotificationCards ' + JSON.stringify(position) + | 359 console.log('requestNotificationCards ' + JSON.stringify(position) + |
| 339 ' from ' + NOTIFICATION_CARDS_URL); | 360 ' from ' + NOTIFICATION_CARDS_URL); |
| 340 | 361 |
| 341 if (!NOTIFICATION_CARDS_URL) { | 362 if (!NOTIFICATION_CARDS_URL) { |
| 342 callback(); | 363 callback(); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 377 /** | 398 /** |
| 378 * Starts getting location for a cards update. | 399 * Starts getting location for a cards update. |
| 379 */ | 400 */ |
| 380 function requestLocation() { | 401 function requestLocation() { |
| 381 console.log('requestLocation'); | 402 console.log('requestLocation'); |
| 382 recordEvent(DiagnosticEvent.LOCATION_REQUEST); | 403 recordEvent(DiagnosticEvent.LOCATION_REQUEST); |
| 383 // TODO(vadimt): Figure out location request options. | 404 // TODO(vadimt): Figure out location request options. |
| 384 chrome.location.watchLocation(LOCATION_WATCH_NAME, {}); | 405 chrome.location.watchLocation(LOCATION_WATCH_NAME, {}); |
| 385 } | 406 } |
| 386 | 407 |
| 408 /** |
| 409 * Stops getting the location. |
| 410 */ |
| 411 function stopRequestLocation() { |
| 412 console.log('stopRequestLocation'); |
| 413 chrome.location.clearWatch(LOCATION_WATCH_NAME); |
| 414 } |
| 387 | 415 |
| 388 /** | 416 /** |
| 389 * Obtains new location; requests and shows notification cards based on this | 417 * Obtains new location; requests and shows notification cards based on this |
| 390 * location. | 418 * location. |
| 391 * @param {Location} position Location of this computer. | 419 * @param {Location} position Location of this computer. |
| 392 */ | 420 */ |
| 393 function updateNotificationsCards(position) { | 421 function updateNotificationsCards(position) { |
| 394 console.log('updateNotificationsCards ' + JSON.stringify(position) + | 422 console.log('updateNotificationsCards ' + JSON.stringify(position) + |
| 395 ' @' + new Date()); | 423 ' @' + new Date()); |
| 396 tasks.add(UPDATE_CARDS_TASK_NAME, function(callback) { | 424 tasks.add(UPDATE_CARDS_TASK_NAME, function(callback) { |
| 397 console.log('updateNotificationsCards-task-begin'); | 425 console.log('updateNotificationsCards-task-begin'); |
| 398 updateCardsAttempts.planForNext(function() { | 426 updateCardsAttempts.isRunning(function(running) { |
| 399 processPendingDismissals(function(success) { | 427 if (running) { |
| 400 if (success) { | 428 updateCardsAttempts.planForNext(function() { |
| 401 // The cards are requested only if there are no unsent dismissals. | 429 processPendingDismissals(function(success) { |
| 402 requestNotificationCards(position, callback); | 430 if (success) { |
| 403 } else { | 431 // The cards are requested only if there are no unsent dismissals. |
| 404 callback(); | 432 requestNotificationCards(position, callback); |
| 405 } | 433 } else { |
| 406 }); | 434 callback(); |
| 435 } |
| 436 }); |
| 437 }); |
| 438 } |
| 407 }); | 439 }); |
| 408 }); | 440 }); |
| 409 } | 441 } |
| 410 | 442 |
| 411 /** | 443 /** |
| 412 * Sends a server request to dismiss a card. | 444 * Sends a server request to dismiss a card. |
| 413 * @param {string} notificationId Unique identifier of the card. | 445 * @param {string} notificationId Unique identifier of the card. |
| 414 * @param {number} dismissalTimeMs Time of the user's dismissal of the card in | 446 * @param {number} dismissalTimeMs Time of the user's dismissal of the card in |
| 415 * milliseconds since epoch. | 447 * milliseconds since epoch. |
| 416 * @param {Object} dismissalParameters Dismissal parameters. | 448 * @param {Object} dismissalParameters Dismissal parameters. |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 559 chrome.windows.create({url: url}); | 591 chrome.windows.create({url: url}); |
| 560 }); | 592 }); |
| 561 }); | 593 }); |
| 562 } | 594 } |
| 563 | 595 |
| 564 /** | 596 /** |
| 565 * Responds to a click of one of the buttons on the welcome toast. | 597 * Responds to a click of one of the buttons on the welcome toast. |
| 566 * @param {number} buttonIndex The index of the button which was clicked. | 598 * @param {number} buttonIndex The index of the button which was clicked. |
| 567 */ | 599 */ |
| 568 function onToastNotificationClicked(buttonIndex) { | 600 function onToastNotificationClicked(buttonIndex) { |
| 601 storage.set({userRespondedToToast: true}); |
| 602 |
| 569 if (buttonIndex == ToastButtonIndex.YES) { | 603 if (buttonIndex == ToastButtonIndex.YES) { |
| 570 chrome.metricsPrivate.recordUserAction('GoogleNow.WelcomeToastClickedYes'); | 604 chrome.metricsPrivate.recordUserAction('GoogleNow.WelcomeToastClickedYes'); |
| 571 storage.set({toastState: ToastOptionResponse.CHOSE_YES}); | 605 googleGeolocationAccessEnabledPref.set({value: true}); |
| 572 | 606 // The googlegeolocationaccessenabled preference change callback |
| 573 // TODO(zturner): Update chrome geolocation setting once the settings | 607 // will take care of starting the poll for cards. |
| 574 // API is in place. | |
| 575 startPollingCards(); | |
| 576 } else { | 608 } else { |
| 577 chrome.metricsPrivate.recordUserAction('GoogleNow.WelcomeToastClickedNo'); | 609 chrome.metricsPrivate.recordUserAction('GoogleNow.WelcomeToastClickedNo'); |
| 578 storage.set({toastState: ToastOptionResponse.CHOSE_NO}); | 610 onStateChange(); |
| 579 } | 611 } |
| 580 | |
| 581 chrome.notifications.clear( | |
| 582 WELCOME_TOAST_NOTIFICATION_ID, | |
| 583 function(wasCleared) {}); | |
| 584 } | 612 } |
| 585 | 613 |
| 586 /** | 614 /** |
| 587 * Callback for chrome.notifications.onClosed event. | 615 * Callback for chrome.notifications.onClosed event. |
| 588 * @param {string} notificationId Unique identifier of the notification. | 616 * @param {string} notificationId Unique identifier of the notification. |
| 589 * @param {boolean} byUser Whether the notification was closed by the user. | 617 * @param {boolean} byUser Whether the notification was closed by the user. |
| 590 */ | 618 */ |
| 591 function onNotificationClosed(notificationId, byUser) { | 619 function onNotificationClosed(notificationId, byUser) { |
| 592 if (!byUser) | 620 if (!byUser) |
| 593 return; | 621 return; |
| 594 | 622 |
| 595 if (notificationId == WELCOME_TOAST_NOTIFICATION_ID) { | 623 if (notificationId == WELCOME_TOAST_NOTIFICATION_ID) { |
| 596 // Even though they only closed the notification without clicking no, treat | 624 // Even though they only closed the notification without clicking no, treat |
| 597 // it as though they clicked No anwyay, and don't show the toast again. | 625 // it as though they clicked No anwyay, and don't show the toast again. |
| 598 chrome.metricsPrivate.recordUserAction('GoogleNow.WelcomeToastDismissed'); | 626 chrome.metricsPrivate.recordUserAction('GoogleNow.WelcomeToastDismissed'); |
| 599 storage.set({toastState: ToastOptionResponse.CHOSE_NO}); | 627 storage.set({userRespondedToToast: true}); |
| 600 return; | 628 return; |
| 601 } | 629 } |
| 602 | 630 |
| 603 // At this point we are guaranteed that the notification is a now card. | 631 // At this point we are guaranteed that the notification is a now card. |
| 604 chrome.metricsPrivate.recordUserAction('GoogleNow.Dismissed'); | 632 chrome.metricsPrivate.recordUserAction('GoogleNow.Dismissed'); |
| 605 | 633 |
| 606 tasks.add(DISMISS_CARD_TASK_NAME, function(callback) { | 634 tasks.add(DISMISS_CARD_TASK_NAME, function(callback) { |
| 607 dismissalAttempts.start(); | 635 dismissalAttempts.start(); |
| 608 | 636 |
| 609 // Deleting the notification in case it was re-added while this task was | 637 // Deleting the notification in case it was re-added while this task was |
| (...skipping 25 matching lines...) Expand all Loading... |
| 635 */ | 663 */ |
| 636 function startPollingCards() { | 664 function startPollingCards() { |
| 637 // Create an update timer for a case when for some reason location request | 665 // Create an update timer for a case when for some reason location request |
| 638 // gets stuck. | 666 // gets stuck. |
| 639 updateCardsAttempts.start(MAXIMUM_POLLING_PERIOD_SECONDS); | 667 updateCardsAttempts.start(MAXIMUM_POLLING_PERIOD_SECONDS); |
| 640 | 668 |
| 641 requestLocation(); | 669 requestLocation(); |
| 642 } | 670 } |
| 643 | 671 |
| 644 /** | 672 /** |
| 673 * Stops all machinery in the polling system. |
| 674 */ |
| 675 function stopPollingCards() { |
| 676 stopRequestLocation(); |
| 677 |
| 678 updateCardsAttempts.stop(); |
| 679 |
| 680 removeAllCards(); |
| 681 } |
| 682 |
| 683 /** |
| 645 * Initializes the event page on install or on browser startup. | 684 * Initializes the event page on install or on browser startup. |
| 646 */ | 685 */ |
| 647 function initialize() { | 686 function initialize() { |
| 648 recordEvent(DiagnosticEvent.EXTENSION_START); | 687 recordEvent(DiagnosticEvent.EXTENSION_START); |
| 649 storage.get('toastState', function(items) { | |
| 650 // The toast state might be undefined (e.g. not in storage yet) if this is | |
| 651 // the first time ever being prompted. | |
| 652 | 688 |
| 653 // TODO(zturner): Get the value of isGeolocationEnabled from the settings | 689 // Alarms persist across chrome restarts. This is undesirable since it |
| 654 // api and additionally make sure it is true. | 690 // prevents us from starting up everything (alarms are a heuristic to |
| 655 if (!items.toastState) { | 691 // determine if we are already running). To mitigate this, we will |
| 656 if (NOTIFICATION_CARDS_URL) { | 692 // shut everything down on initialize before starting everything up. |
| 657 chrome.identity.getAuthToken({interactive: false}, function(token) { | 693 stopPollingCards(); |
| 658 if (!chrome.runtime.lastError && token) | 694 onStateChange(); |
| 659 showWelcomeToast(); | 695 } |
| 660 }); | 696 |
| 661 } | 697 /** |
| 662 } else if (items.toastState == ToastOptionResponse.CHOSE_YES) { | 698 * Starts or stops the polling of cards. |
| 663 startPollingCards(); | 699 * @param {boolean} shouldPollCardsRequest true to start and |
| 700 * false to stop polling cards. |
| 701 * @param {function} onSuccess Called on completion. |
| 702 */ |
| 703 function setShouldPollCards(shouldPollCardsRequest, onSuccess) { |
| 704 tasks.debugSetStepName( |
| 705 'setShouldRun-shouldRun-updateCardsAttemptsIsRunning'); |
| 706 updateCardsAttempts.isRunning(function(currentValue) { |
| 707 if (shouldPollCardsRequest != currentValue) { |
| 708 if (shouldPollCardsRequest) |
| 709 startPollingCards(); |
| 710 else |
| 711 stopPollingCards(); |
| 664 } | 712 } |
| 713 onSuccess(); |
| 665 }); | 714 }); |
| 666 } | 715 } |
| 667 | 716 |
| 717 /** |
| 718 * Shows or hides the toast. |
| 719 * @param {boolean} visibleRequest true to show the toast and |
| 720 * false to hide the toast. |
| 721 * @param {function} onSuccess Called on completion. |
| 722 */ |
| 723 function setToastVisible(visibleRequest, onSuccess) { |
| 724 tasks.debugSetStepName( |
| 725 'setToastVisible-shouldSetToastVisible-getAllNotifications'); |
| 726 chrome.notifications.getAll(function(notifications) { |
| 727 // TODO(vadimt): Figure out what to do when notifications are disabled for |
| 728 // our extension. |
| 729 notifications = notifications || {}; |
| 730 |
| 731 if (visibleRequest != !!notifications[WELCOME_TOAST_NOTIFICATION_ID]) { |
| 732 if (visibleRequest) |
| 733 showWelcomeToast(); |
| 734 else |
| 735 hideWelcomeToast(); |
| 736 } |
| 737 |
| 738 onSuccess(); |
| 739 }); |
| 740 } |
| 741 |
| 742 /** |
| 743 * Does the actual work of deciding what Google Now should do |
| 744 * based off of the current state of Chrome. |
| 745 * @param {boolean} signedIn true if the user is signed in. |
| 746 * @param {boolean} geolocationEnabled true if |
| 747 * the geolocation option is enabled. |
| 748 * @param {boolean} userRespondedToToast true if |
| 749 * the user has responded to the toast. |
| 750 * @param {function()} callback Call this function on completion. |
| 751 */ |
| 752 function updateRunningState( |
| 753 signedIn, |
| 754 geolocationEnabled, |
| 755 userRespondedToToast, |
| 756 callback) { |
| 757 |
| 758 var shouldSetToastVisible = false; |
| 759 var shouldPollCards = false; |
| 760 |
| 761 if (signedIn) { |
| 762 if (geolocationEnabled) { |
| 763 if (!userRespondedToToast) { |
| 764 // If the user enabled geolocation independently of Google Now, |
| 765 // the user has implicitly responded to the toast. |
| 766 // We do not want to show it again. |
| 767 storage.set({userRespondedToToast: true}); |
| 768 } |
| 769 |
| 770 shouldPollCards = true; |
| 771 } else { |
| 772 if (!userRespondedToToast) |
| 773 shouldSetToastVisible = true; |
| 774 } |
| 775 } |
| 776 |
| 777 setToastVisible(shouldSetToastVisible, function() { |
| 778 setShouldPollCards(shouldPollCards, callback); |
| 779 }); |
| 780 } |
| 781 |
| 782 /** |
| 783 * Coordinates the behavior of Google Now for Chrome depending on |
| 784 * Chrome and extension state. |
| 785 */ |
| 786 function onStateChange() { |
| 787 tasks.add(STATE_CHANGED_TASK_NAME, function(callback) { |
| 788 tasks.debugSetStepName('onStateChange-getAuthToken'); |
| 789 chrome.identity.getAuthToken({interactive: false}, function(token) { |
| 790 var signedIn = |
| 791 !chrome.runtime.lastError && |
| 792 token && |
| 793 !!NOTIFICATION_CARDS_URL; |
| 794 tasks.debugSetStepName( |
| 795 'onStateChange-get-googleGeolocationAccessEnabledPref'); |
| 796 googleGeolocationAccessEnabledPref.get({}, function(prefValue) { |
| 797 var geolocationEnabled = !!prefValue.value; |
| 798 tasks.debugSetStepName( |
| 799 'onStateChange-get-userRespondedToToast'); |
| 800 storage.get('userRespondedToToast', function(items) { |
| 801 var userRespondedToToast = !!items.userRespondedToToast; |
| 802 updateRunningState( |
| 803 signedIn, |
| 804 geolocationEnabled, |
| 805 userRespondedToToast, |
| 806 callback); |
| 807 }); |
| 808 }); |
| 809 }); |
| 810 }); |
| 811 } |
| 812 |
| 668 /** | 813 /** |
| 669 * Displays a toast to the user asking if they want to opt in to receiving | 814 * Displays a toast to the user asking if they want to opt in to receiving |
| 670 * Google Now cards. | 815 * Google Now cards. |
| 671 */ | 816 */ |
| 672 function showWelcomeToast() { | 817 function showWelcomeToast() { |
| 673 recordEvent(DiagnosticEvent.SHOW_WELCOME_TOAST); | 818 recordEvent(DiagnosticEvent.SHOW_WELCOME_TOAST); |
| 674 // TODO(zturner): Localize this once the component extension localization | 819 // TODO(zturner): Localize this once the component extension localization |
| 675 // api is complete. | 820 // api is complete. |
| 676 // TODO(zturner): Add icons. | 821 // TODO(zturner): Add icons. |
| 677 var buttons = [{title: 'Yes'}, {title: 'No'}]; | 822 var buttons = [{title: 'Yes'}, {title: 'No'}]; |
| 678 var options = { | 823 var options = { |
| 679 type: 'basic', | 824 type: 'basic', |
| 680 title: 'Enable Google Now Cards', | 825 title: 'Enable Google Now Cards', |
| 681 message: 'Would you like to be shown Google Now cards?', | 826 message: 'Would you like to be shown Google Now cards?', |
| 682 iconUrl: 'http://www.gstatic.com/googlenow/chrome/default.png', | 827 iconUrl: 'http://www.gstatic.com/googlenow/chrome/default.png', |
| 683 priority: 2, | 828 priority: 2, |
| 684 buttons: buttons | 829 buttons: buttons |
| 685 }; | 830 }; |
| 686 chrome.notifications.create(WELCOME_TOAST_NOTIFICATION_ID, options, | 831 chrome.notifications.create(WELCOME_TOAST_NOTIFICATION_ID, options, |
| 687 function(notificationId) {}); | 832 function(notificationId) {}); |
| 688 } | 833 } |
| 689 | 834 |
| 835 /** |
| 836 * Hides the welcome toast. |
| 837 */ |
| 838 function hideWelcomeToast() { |
| 839 chrome.notifications.clear( |
| 840 WELCOME_TOAST_NOTIFICATION_ID, |
| 841 function() {}); |
| 842 } |
| 843 |
| 690 chrome.runtime.onInstalled.addListener(function(details) { | 844 chrome.runtime.onInstalled.addListener(function(details) { |
| 691 console.log('onInstalled ' + JSON.stringify(details)); | 845 console.log('onInstalled ' + JSON.stringify(details)); |
| 692 if (details.reason != 'chrome_update') { | 846 if (details.reason != 'chrome_update') { |
| 693 initialize(); | 847 initialize(); |
| 694 } | 848 } |
| 695 }); | 849 }); |
| 696 | 850 |
| 697 chrome.runtime.onStartup.addListener(function() { | 851 chrome.runtime.onStartup.addListener(function() { |
| 698 console.log('onStartup'); | 852 console.log('onStartup'); |
| 699 initialize(); | 853 initialize(); |
| 700 }); | 854 }); |
| 701 | 855 |
| 856 googleGeolocationAccessEnabledPref.onChange.addListener(function(prefValue) { |
| 857 console.log('googleGeolocationAccessEnabledPref onChange ' + prefValue.value); |
| 858 onStateChange(); |
| 859 }); |
| 860 |
| 702 chrome.notifications.onClicked.addListener( | 861 chrome.notifications.onClicked.addListener( |
| 703 function(notificationId) { | 862 function(notificationId) { |
| 704 chrome.metricsPrivate.recordUserAction('GoogleNow.MessageClicked'); | 863 chrome.metricsPrivate.recordUserAction('GoogleNow.MessageClicked'); |
| 705 onNotificationClicked(notificationId, function(actionUrls) { | 864 onNotificationClicked(notificationId, function(actionUrls) { |
| 706 return actionUrls.messageUrl; | 865 return actionUrls.messageUrl; |
| 707 }); | 866 }); |
| 708 }); | 867 }); |
| 709 | 868 |
| 710 chrome.notifications.onButtonClicked.addListener( | 869 chrome.notifications.onButtonClicked.addListener( |
| 711 function(notificationId, buttonIndex) { | 870 function(notificationId, buttonIndex) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 727 | 886 |
| 728 chrome.location.onLocationUpdate.addListener(function(position) { | 887 chrome.location.onLocationUpdate.addListener(function(position) { |
| 729 recordEvent(DiagnosticEvent.LOCATION_UPDATE); | 888 recordEvent(DiagnosticEvent.LOCATION_UPDATE); |
| 730 updateNotificationsCards(position); | 889 updateNotificationsCards(position); |
| 731 }); | 890 }); |
| 732 | 891 |
| 733 chrome.omnibox.onInputEntered.addListener(function(text) { | 892 chrome.omnibox.onInputEntered.addListener(function(text) { |
| 734 localStorage['server_url'] = NOTIFICATION_CARDS_URL = text; | 893 localStorage['server_url'] = NOTIFICATION_CARDS_URL = text; |
| 735 initialize(); | 894 initialize(); |
| 736 }); | 895 }); |
| OLD | NEW |