| 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 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 74 var DISMISS_RETENTION_TIME_MS = 20 * 60 * 1000; // 20 minutes | 74 var DISMISS_RETENTION_TIME_MS = 20 * 60 * 1000; // 20 minutes |
| 75 | 75 |
| 76 /** | 76 /** |
| 77 * Names for tasks that can be created by the extension. | 77 * Names for tasks that can be created by the extension. |
| 78 */ | 78 */ |
| 79 var UPDATE_CARDS_TASK_NAME = 'update-cards'; | 79 var UPDATE_CARDS_TASK_NAME = 'update-cards'; |
| 80 var DISMISS_CARD_TASK_NAME = 'dismiss-card'; | 80 var DISMISS_CARD_TASK_NAME = 'dismiss-card'; |
| 81 var RETRY_DISMISS_TASK_NAME = 'retry-dismiss'; | 81 var RETRY_DISMISS_TASK_NAME = 'retry-dismiss'; |
| 82 var STATE_CHANGED_TASK_NAME = 'state-changed'; | 82 var STATE_CHANGED_TASK_NAME = 'state-changed'; |
| 83 var SHOW_ON_START_TASK_NAME = 'show-cards-on-start'; | 83 var SHOW_ON_START_TASK_NAME = 'show-cards-on-start'; |
| 84 var ON_PUSH_MESSAGE_START_TASK_NAME = 'on-push-message'; |
| 84 | 85 |
| 85 var LOCATION_WATCH_NAME = 'location-watch'; | 86 var LOCATION_WATCH_NAME = 'location-watch'; |
| 86 | 87 |
| 87 /** | 88 /** |
| 89 * Chrome push messaging subchannel for messages causing an immediate poll. |
| 90 */ |
| 91 var SUBCHANNEL_ID_POLL_NOW = 0; |
| 92 |
| 93 /** |
| 94 /** |
| 88 * Notification as it's sent by the server. | 95 * Notification as it's sent by the server. |
| 89 * | 96 * |
| 90 * @typedef {{ | 97 * @typedef {{ |
| 91 * notificationId: string, | 98 * notificationId: string, |
| 92 * chromeNotificationId: string, | 99 * chromeNotificationId: string, |
| 93 * trigger: Object=, | 100 * trigger: Object=, |
| 94 * version: number, | 101 * version: number, |
| 95 * chromeNotificationOptions: Object, | 102 * chromeNotificationOptions: Object, |
| 96 * actionUrls: Object=, | 103 * actionUrls: Object=, |
| 97 * dismissal: Object | 104 * dismissal: Object |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 153 wrapper.instrumentChromeApiFunction('notifications.onClicked.addListener', 0); | 160 wrapper.instrumentChromeApiFunction('notifications.onClicked.addListener', 0); |
| 154 wrapper.instrumentChromeApiFunction('notifications.onClosed.addListener', 0); | 161 wrapper.instrumentChromeApiFunction('notifications.onClosed.addListener', 0); |
| 155 wrapper.instrumentChromeApiFunction('omnibox.onInputEntered.addListener', 0); | 162 wrapper.instrumentChromeApiFunction('omnibox.onInputEntered.addListener', 0); |
| 156 wrapper.instrumentChromeApiFunction( | 163 wrapper.instrumentChromeApiFunction( |
| 157 'preferencesPrivate.googleGeolocationAccessEnabled.get', | 164 'preferencesPrivate.googleGeolocationAccessEnabled.get', |
| 158 1); | 165 1); |
| 159 wrapper.instrumentChromeApiFunction( | 166 wrapper.instrumentChromeApiFunction( |
| 160 'preferencesPrivate.googleGeolocationAccessEnabled.onChange.addListener', | 167 'preferencesPrivate.googleGeolocationAccessEnabled.onChange.addListener', |
| 161 0); | 168 0); |
| 162 wrapper.instrumentChromeApiFunction('permissions.contains', 1); | 169 wrapper.instrumentChromeApiFunction('permissions.contains', 1); |
| 170 wrapper.instrumentChromeApiFunction('pushMessaging.onMessage.addListener', 0); |
| 163 wrapper.instrumentChromeApiFunction('runtime.onInstalled.addListener', 0); | 171 wrapper.instrumentChromeApiFunction('runtime.onInstalled.addListener', 0); |
| 164 wrapper.instrumentChromeApiFunction('runtime.onStartup.addListener', 0); | 172 wrapper.instrumentChromeApiFunction('runtime.onStartup.addListener', 0); |
| 165 wrapper.instrumentChromeApiFunction('tabs.create', 1); | 173 wrapper.instrumentChromeApiFunction('tabs.create', 1); |
| 166 wrapper.instrumentChromeApiFunction('storage.local.get', 1); | 174 wrapper.instrumentChromeApiFunction('storage.local.get', 1); |
| 167 | 175 |
| 168 var updateCardsAttempts = buildAttemptManager( | 176 var updateCardsAttempts = buildAttemptManager( |
| 169 'cards-update', | 177 'cards-update', |
| 170 requestLocation, | 178 requestLocation, |
| 171 INITIAL_POLLING_PERIOD_SECONDS, | 179 INITIAL_POLLING_PERIOD_SECONDS, |
| 172 MAXIMUM_POLLING_PERIOD_SECONDS); | 180 MAXIMUM_POLLING_PERIOD_SECONDS); |
| (...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 508 } | 516 } |
| 509 | 517 |
| 510 scheduleNextPoll(updatedGroups); | 518 scheduleNextPoll(updatedGroups); |
| 511 chrome.storage.local.set({notificationGroups: updatedGroups}); | 519 chrome.storage.local.set({notificationGroups: updatedGroups}); |
| 512 mergeAndShowNotificationCards(updatedGroups); | 520 mergeAndShowNotificationCards(updatedGroups); |
| 513 recordEvent(GoogleNowEvent.CARDS_PARSE_SUCCESS); | 521 recordEvent(GoogleNowEvent.CARDS_PARSE_SUCCESS); |
| 514 }); | 522 }); |
| 515 } | 523 } |
| 516 | 524 |
| 517 /** | 525 /** |
| 526 * Requests notification cards from the server for specified groups. |
| 527 * @param {Array.<string>} groupNames Names of groups that need to be refreshed. |
| 528 */ |
| 529 function requestNotificationGroups(groupNames) { |
| 530 console.log('requestNotificationGroups from ' + NOTIFICATION_CARDS_URL + |
| 531 ', groupNames=' + JSON.stringify(groupNames)); |
| 532 |
| 533 if (!NOTIFICATION_CARDS_URL) |
| 534 return; |
| 535 |
| 536 recordEvent(GoogleNowEvent.REQUEST_FOR_CARDS_TOTAL); |
| 537 |
| 538 var requestParameters = '?timeZoneOffsetMs=' + |
| 539 (-new Date().getTimezoneOffset() * MS_IN_MINUTE); |
| 540 |
| 541 groupNames.forEach(function(groupName) { |
| 542 requestParameters += ('&requestTypes=' + groupName); |
| 543 }); |
| 544 |
| 545 console.log('requestNotificationGroups: request=' + requestParameters); |
| 546 |
| 547 var request = buildServerRequest('GET', 'notifications' + requestParameters); |
| 548 |
| 549 request.onloadend = function(event) { |
| 550 console.log('requestNotificationGroups-onloadend ' + request.status); |
| 551 if (request.status == HTTP_OK) { |
| 552 recordEvent(GoogleNowEvent.REQUEST_FOR_CARDS_SUCCESS); |
| 553 parseAndShowNotificationCards(request.response); |
| 554 } |
| 555 }; |
| 556 |
| 557 setAuthorization(request, function(success) { |
| 558 if (success) |
| 559 request.send(); |
| 560 }); |
| 561 } |
| 562 |
| 563 /** |
| 518 * Requests notification cards from the server. | 564 * Requests notification cards from the server. |
| 519 * @param {Location} position Location of this computer. | 565 * @param {Location} position Location of this computer. |
| 520 */ | 566 */ |
| 521 function requestNotificationCards(position) { | 567 function requestNotificationCards(position) { |
| 522 console.log('requestNotificationCards ' + JSON.stringify(position) + | 568 console.log('requestNotificationCards ' + JSON.stringify(position)); |
| 523 ' from ' + NOTIFICATION_CARDS_URL); | |
| 524 | |
| 525 if (!NOTIFICATION_CARDS_URL) | |
| 526 return; | |
| 527 | |
| 528 recordEvent(GoogleNowEvent.REQUEST_FOR_CARDS_TOTAL); | |
| 529 | 569 |
| 530 instrumented.storage.local.get('notificationGroups', function(items) { | 570 instrumented.storage.local.get('notificationGroups', function(items) { |
| 531 console.log('requestNotificationCards-storage-get ' + | 571 console.log('requestNotificationCards-storage-get ' + |
| 532 JSON.stringify(items)); | 572 JSON.stringify(items)); |
| 533 items = items || {}; | 573 items = items || {}; |
| 534 | 574 |
| 535 var requestParameters = '?timeZoneOffsetMs=' + | 575 var groupsToRequest = []; |
| 536 (-new Date().getTimezoneOffset() * MS_IN_MINUTE); | |
| 537 | 576 |
| 538 if (items.notificationGroups) { | 577 if (items.notificationGroups) { |
| 539 var now = Date.now(); | 578 var now = Date.now(); |
| 540 | 579 |
| 541 for (var groupName in items.notificationGroups) { | 580 for (var groupName in items.notificationGroups) { |
| 542 var group = items.notificationGroups[groupName]; | 581 var group = items.notificationGroups[groupName]; |
| 543 if (group.nextPollTime <= now) | 582 if (group.nextPollTime <= now) |
| 544 requestParameters += ('&requestTypes=' + groupName); | 583 groupsToRequest.push(groupName); |
| 545 } | 584 } |
| 546 } | 585 } |
| 547 | 586 |
| 548 console.log('requestNotificationCards: request=' + requestParameters); | 587 requestNotificationGroups(groupsToRequest); |
| 549 | |
| 550 var request = buildServerRequest('GET', | |
| 551 'notifications' + requestParameters); | |
| 552 | |
| 553 request.onloadend = function(event) { | |
| 554 console.log('requestNotificationCards-onloadend ' + request.status); | |
| 555 if (request.status == HTTP_OK) { | |
| 556 recordEvent(GoogleNowEvent.REQUEST_FOR_CARDS_SUCCESS); | |
| 557 parseAndShowNotificationCards(request.response); | |
| 558 } | |
| 559 }; | |
| 560 | |
| 561 setAuthorization(request, function(success) { | |
| 562 if (success) | |
| 563 request.send(); | |
| 564 }); | |
| 565 }); | 588 }); |
| 566 } | 589 } |
| 567 | 590 |
| 568 /** | 591 /** |
| 569 * Starts getting location for a cards update. | 592 * Starts getting location for a cards update. |
| 570 */ | 593 */ |
| 571 function requestLocation() { | 594 function requestLocation() { |
| 572 console.log('requestLocation'); | 595 console.log('requestLocation'); |
| 573 recordEvent(GoogleNowEvent.LOCATION_REQUEST); | 596 recordEvent(GoogleNowEvent.LOCATION_REQUEST); |
| 574 // TODO(vadimt): Figure out location request options. | 597 // TODO(vadimt): Figure out location request options. |
| (...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1027 | 1050 |
| 1028 instrumented.location.onLocationUpdate.addListener(function(position) { | 1051 instrumented.location.onLocationUpdate.addListener(function(position) { |
| 1029 recordEvent(GoogleNowEvent.LOCATION_UPDATE); | 1052 recordEvent(GoogleNowEvent.LOCATION_UPDATE); |
| 1030 updateNotificationsCards(position); | 1053 updateNotificationsCards(position); |
| 1031 }); | 1054 }); |
| 1032 | 1055 |
| 1033 instrumented.omnibox.onInputEntered.addListener(function(text) { | 1056 instrumented.omnibox.onInputEntered.addListener(function(text) { |
| 1034 localStorage['server_url'] = NOTIFICATION_CARDS_URL = text; | 1057 localStorage['server_url'] = NOTIFICATION_CARDS_URL = text; |
| 1035 initialize(); | 1058 initialize(); |
| 1036 }); | 1059 }); |
| 1060 |
| 1061 instrumented.pushMessaging.onMessage.addListener(function(message) { |
| 1062 // message.payload will be '' when the extension first starts. |
| 1063 // Each time after signing in, we'll get latest payload for all channels. |
| 1064 // So, we need to poll the server only when the payload is non-empty and has |
| 1065 // changed. |
| 1066 console.log('pushMessaging.onMessage ' + JSON.stringify(message)); |
| 1067 if (message.subchannelId == SUBCHANNEL_ID_POLL_NOW && message.payload) { |
| 1068 tasks.add(ON_PUSH_MESSAGE_START_TASK_NAME, function() { |
| 1069 instrumented.storage.local.get('lastPollNowPayload', function(items) { |
| 1070 if (items && items.lastPollNowPayload != message.payload) { |
| 1071 chrome.storage.local.set({lastPollNowPayload: message.payload}); |
| 1072 |
| 1073 updateCardsAttempts.isRunning(function(running) { |
| 1074 if (running) |
| 1075 requestNotificationGroups([]); |
| 1076 }); |
| 1077 } |
| 1078 }); |
| 1079 }); |
| 1080 } |
| 1081 }); |
| OLD | NEW |