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 |