| 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 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 118 * requested: (boolean|undefined) | 118 * requested: (boolean|undefined) |
| 119 * }} | 119 * }} |
| 120 */ | 120 */ |
| 121 var ReceivedGroup; | 121 var ReceivedGroup; |
| 122 | 122 |
| 123 /** | 123 /** |
| 124 * Server response with notifications and groups. | 124 * Server response with notifications and groups. |
| 125 * | 125 * |
| 126 * @typedef {{ | 126 * @typedef {{ |
| 127 * googleNowDisabled: (boolean|undefined), | 127 * googleNowDisabled: (boolean|undefined), |
| 128 * groups: Object.<string, ReceivedGroup>, | 128 * groups: Object<string, ReceivedGroup>, |
| 129 * notifications: Array.<ReceivedNotification> | 129 * notifications: Array<ReceivedNotification> |
| 130 * }} | 130 * }} |
| 131 */ | 131 */ |
| 132 var ServerResponse; | 132 var ServerResponse; |
| 133 | 133 |
| 134 /** | 134 /** |
| 135 * Notification group as the client stores it. |cardsTimestamp| and |rank| are | 135 * Notification group as the client stores it. |cardsTimestamp| and |rank| are |
| 136 * defined if |cards| is non-empty. |nextPollTime| is undefined if the server | 136 * defined if |cards| is non-empty. |nextPollTime| is undefined if the server |
| 137 * (1) never sent 'nextPollSeconds' for the group or | 137 * (1) never sent 'nextPollSeconds' for the group or |
| 138 * (2) didn't send 'nextPollSeconds' with the last group update containing a | 138 * (2) didn't send 'nextPollSeconds' with the last group update containing a |
| 139 * cards update and all the times after that. | 139 * cards update and all the times after that. |
| 140 * | 140 * |
| 141 * @typedef {{ | 141 * @typedef {{ |
| 142 * cards: Array.<ReceivedNotification>, | 142 * cards: Array<ReceivedNotification>, |
| 143 * cardsTimestamp: (number|undefined), | 143 * cardsTimestamp: (number|undefined), |
| 144 * nextPollTime: (number|undefined), | 144 * nextPollTime: (number|undefined), |
| 145 * rank: (number|undefined) | 145 * rank: (number|undefined) |
| 146 * }} | 146 * }} |
| 147 */ | 147 */ |
| 148 var StoredNotificationGroup; | 148 var StoredNotificationGroup; |
| 149 | 149 |
| 150 /** | 150 /** |
| 151 * Pending (not yet successfully sent) dismissal for a received notification. | 151 * Pending (not yet successfully sent) dismissal for a received notification. |
| 152 * |time| is the moment when the user requested dismissal. | 152 * |time| is the moment when the user requested dismissal. |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 335 }, false); | 335 }, false); |
| 336 request.send(); | 336 request.send(); |
| 337 }); | 337 }); |
| 338 requestPromise.catch(checkAuthenticationStatus(token)); | 338 requestPromise.catch(checkAuthenticationStatus(token)); |
| 339 return requestPromise; | 339 return requestPromise; |
| 340 }); | 340 }); |
| 341 } | 341 } |
| 342 | 342 |
| 343 /** | 343 /** |
| 344 * Shows the notification groups as notification cards. | 344 * Shows the notification groups as notification cards. |
| 345 * @param {Object.<string, StoredNotificationGroup>} notificationGroups Map from | 345 * @param {Object<string, StoredNotificationGroup>} notificationGroups Map from |
| 346 * group name to group information. | 346 * group name to group information. |
| 347 * @param {function(ReceivedNotification)=} opt_onCardShown Optional parameter | 347 * @param {function(ReceivedNotification)=} opt_onCardShown Optional parameter |
| 348 * called when each card is shown. | 348 * called when each card is shown. |
| 349 * @return {Promise} A promise to show the notification groups as cards. | 349 * @return {Promise} A promise to show the notification groups as cards. |
| 350 */ | 350 */ |
| 351 function showNotificationGroups(notificationGroups, opt_onCardShown) { | 351 function showNotificationGroups(notificationGroups, opt_onCardShown) { |
| 352 /** @type {Object.<ChromeNotificationId, CombinedCard>} */ | 352 /** @type {Object<ChromeNotificationId, CombinedCard>} */ |
| 353 var cards = combineCardsFromGroups(notificationGroups); | 353 var cards = combineCardsFromGroups(notificationGroups); |
| 354 console.log('showNotificationGroups ' + JSON.stringify(cards)); | 354 console.log('showNotificationGroups ' + JSON.stringify(cards)); |
| 355 | 355 |
| 356 return new Promise(function(resolve) { | 356 return new Promise(function(resolve) { |
| 357 instrumented.notifications.getAll(function(notifications) { | 357 instrumented.notifications.getAll(function(notifications) { |
| 358 console.log('showNotificationGroups-getAll ' + | 358 console.log('showNotificationGroups-getAll ' + |
| 359 JSON.stringify(notifications)); | 359 JSON.stringify(notifications)); |
| 360 notifications = notifications || {}; | 360 notifications = notifications || {}; |
| 361 | 361 |
| 362 // Mark notifications that didn't receive an update as having received | 362 // Mark notifications that didn't receive an update as having received |
| 363 // an empty update. | 363 // an empty update. |
| 364 for (var chromeNotificationId in notifications) { | 364 for (var chromeNotificationId in notifications) { |
| 365 cards[chromeNotificationId] = cards[chromeNotificationId] || []; | 365 cards[chromeNotificationId] = cards[chromeNotificationId] || []; |
| 366 } | 366 } |
| 367 | 367 |
| 368 /** @type {Object.<ChromeNotificationId, NotificationDataEntry>} */ | 368 /** @type {Object<ChromeNotificationId, NotificationDataEntry>} */ |
| 369 var notificationsData = {}; | 369 var notificationsData = {}; |
| 370 | 370 |
| 371 // Create/update/delete notifications. | 371 // Create/update/delete notifications. |
| 372 for (var chromeNotificationId in cards) { | 372 for (var chromeNotificationId in cards) { |
| 373 notificationsData[chromeNotificationId] = cardSet.update( | 373 notificationsData[chromeNotificationId] = cardSet.update( |
| 374 chromeNotificationId, | 374 chromeNotificationId, |
| 375 cards[chromeNotificationId], | 375 cards[chromeNotificationId], |
| 376 notificationGroups, | 376 notificationGroups, |
| 377 opt_onCardShown); | 377 opt_onCardShown); |
| 378 } | 378 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 395 notifications = notifications || {}; | 395 notifications = notifications || {}; |
| 396 for (var chromeNotificationId in notifications) { | 396 for (var chromeNotificationId in notifications) { |
| 397 instrumented.notifications.clear(chromeNotificationId, function() {}); | 397 instrumented.notifications.clear(chromeNotificationId, function() {}); |
| 398 } | 398 } |
| 399 chrome.storage.local.remove(['notificationsData', 'notificationGroups']); | 399 chrome.storage.local.remove(['notificationsData', 'notificationGroups']); |
| 400 }); | 400 }); |
| 401 } | 401 } |
| 402 | 402 |
| 403 /** | 403 /** |
| 404 * Adds a card group into a set of combined cards. | 404 * Adds a card group into a set of combined cards. |
| 405 * @param {Object.<ChromeNotificationId, CombinedCard>} combinedCards Map from | 405 * @param {Object<ChromeNotificationId, CombinedCard>} combinedCards Map from |
| 406 * chromeNotificationId to a combined card. | 406 * chromeNotificationId to a combined card. |
| 407 * This is an input/output parameter. | 407 * This is an input/output parameter. |
| 408 * @param {StoredNotificationGroup} storedGroup Group to combine into the | 408 * @param {StoredNotificationGroup} storedGroup Group to combine into the |
| 409 * combined card set. | 409 * combined card set. |
| 410 */ | 410 */ |
| 411 function combineGroup(combinedCards, storedGroup) { | 411 function combineGroup(combinedCards, storedGroup) { |
| 412 for (var i = 0; i < storedGroup.cards.length; i++) { | 412 for (var i = 0; i < storedGroup.cards.length; i++) { |
| 413 /** @type {ReceivedNotification} */ | 413 /** @type {ReceivedNotification} */ |
| 414 var receivedNotification = storedGroup.cards[i]; | 414 var receivedNotification = storedGroup.cards[i]; |
| 415 | 415 |
| 416 /** @type {UncombinedNotification} */ | 416 /** @type {UncombinedNotification} */ |
| 417 var uncombinedNotification = { | 417 var uncombinedNotification = { |
| 418 receivedNotification: receivedNotification, | 418 receivedNotification: receivedNotification, |
| 419 showTime: receivedNotification.trigger.showTimeSec && | 419 showTime: receivedNotification.trigger.showTimeSec && |
| 420 (storedGroup.cardsTimestamp + | 420 (storedGroup.cardsTimestamp + |
| 421 receivedNotification.trigger.showTimeSec * MS_IN_SECOND), | 421 receivedNotification.trigger.showTimeSec * MS_IN_SECOND), |
| 422 hideTime: storedGroup.cardsTimestamp + | 422 hideTime: storedGroup.cardsTimestamp + |
| 423 receivedNotification.trigger.hideTimeSec * MS_IN_SECOND | 423 receivedNotification.trigger.hideTimeSec * MS_IN_SECOND |
| 424 }; | 424 }; |
| 425 | 425 |
| 426 var combinedCard = | 426 var combinedCard = |
| 427 combinedCards[receivedNotification.chromeNotificationId] || []; | 427 combinedCards[receivedNotification.chromeNotificationId] || []; |
| 428 combinedCard.push(uncombinedNotification); | 428 combinedCard.push(uncombinedNotification); |
| 429 combinedCards[receivedNotification.chromeNotificationId] = combinedCard; | 429 combinedCards[receivedNotification.chromeNotificationId] = combinedCard; |
| 430 } | 430 } |
| 431 } | 431 } |
| 432 | 432 |
| 433 /** | 433 /** |
| 434 * Calculates the soonest poll time from a map of groups as an absolute time. | 434 * Calculates the soonest poll time from a map of groups as an absolute time. |
| 435 * @param {Object.<string, StoredNotificationGroup>} groups Map from group name | 435 * @param {Object<string, StoredNotificationGroup>} groups Map from group name |
| 436 * to group information. | 436 * to group information. |
| 437 * @return {number} The next poll time based off of the groups. | 437 * @return {number} The next poll time based off of the groups. |
| 438 */ | 438 */ |
| 439 function calculateNextPollTimeMilliseconds(groups) { | 439 function calculateNextPollTimeMilliseconds(groups) { |
| 440 var nextPollTime = null; | 440 var nextPollTime = null; |
| 441 | 441 |
| 442 for (var groupName in groups) { | 442 for (var groupName in groups) { |
| 443 var group = groups[groupName]; | 443 var group = groups[groupName]; |
| 444 if (group.nextPollTime !== undefined) { | 444 if (group.nextPollTime !== undefined) { |
| 445 nextPollTime = nextPollTime == null ? | 445 nextPollTime = nextPollTime == null ? |
| 446 group.nextPollTime : Math.min(group.nextPollTime, nextPollTime); | 446 group.nextPollTime : Math.min(group.nextPollTime, nextPollTime); |
| 447 } | 447 } |
| 448 } | 448 } |
| 449 | 449 |
| 450 // At least one of the groups must have nextPollTime. | 450 // At least one of the groups must have nextPollTime. |
| 451 verify(nextPollTime != null, 'calculateNextPollTime: nextPollTime is null'); | 451 verify(nextPollTime != null, 'calculateNextPollTime: nextPollTime is null'); |
| 452 return nextPollTime; | 452 return nextPollTime; |
| 453 } | 453 } |
| 454 | 454 |
| 455 /** | 455 /** |
| 456 * Schedules next cards poll. | 456 * Schedules next cards poll. |
| 457 * @param {Object.<string, StoredNotificationGroup>} groups Map from group name | 457 * @param {Object<string, StoredNotificationGroup>} groups Map from group name |
| 458 * to group information. | 458 * to group information. |
| 459 */ | 459 */ |
| 460 function scheduleNextCardsPoll(groups) { | 460 function scheduleNextCardsPoll(groups) { |
| 461 var nextPollTimeMs = calculateNextPollTimeMilliseconds(groups); | 461 var nextPollTimeMs = calculateNextPollTimeMilliseconds(groups); |
| 462 | 462 |
| 463 var nextPollDelaySeconds = Math.max( | 463 var nextPollDelaySeconds = Math.max( |
| 464 (nextPollTimeMs - Date.now()) / MS_IN_SECOND, | 464 (nextPollTimeMs - Date.now()) / MS_IN_SECOND, |
| 465 MINIMUM_POLLING_PERIOD_SECONDS); | 465 MINIMUM_POLLING_PERIOD_SECONDS); |
| 466 updateCardsAttempts.start(nextPollDelaySeconds); | 466 updateCardsAttempts.start(nextPollDelaySeconds); |
| 467 } | 467 } |
| 468 | 468 |
| 469 /** | 469 /** |
| 470 * Schedules the next opt-in check poll. | 470 * Schedules the next opt-in check poll. |
| 471 */ | 471 */ |
| 472 function scheduleOptInCheckPoll() { | 472 function scheduleOptInCheckPoll() { |
| 473 instrumented.metricsPrivate.getVariationParams( | 473 instrumented.metricsPrivate.getVariationParams( |
| 474 'GoogleNow', function(params) { | 474 'GoogleNow', function(params) { |
| 475 var optinPollPeriodSeconds = | 475 var optinPollPeriodSeconds = |
| 476 parseInt(params && params.optinPollPeriodSeconds, 10) || | 476 parseInt(params && params.optinPollPeriodSeconds, 10) || |
| 477 DEFAULT_OPTIN_CHECK_PERIOD_SECONDS; | 477 DEFAULT_OPTIN_CHECK_PERIOD_SECONDS; |
| 478 optInPollAttempts.start(optinPollPeriodSeconds); | 478 optInPollAttempts.start(optinPollPeriodSeconds); |
| 479 }); | 479 }); |
| 480 } | 480 } |
| 481 | 481 |
| 482 /** | 482 /** |
| 483 * Combines notification groups into a set of Chrome notifications. | 483 * Combines notification groups into a set of Chrome notifications. |
| 484 * @param {Object.<string, StoredNotificationGroup>} notificationGroups Map from | 484 * @param {Object<string, StoredNotificationGroup>} notificationGroups Map from |
| 485 * group name to group information. | 485 * group name to group information. |
| 486 * @return {Object.<ChromeNotificationId, CombinedCard>} Cards to show. | 486 * @return {Object<ChromeNotificationId, CombinedCard>} Cards to show. |
| 487 */ | 487 */ |
| 488 function combineCardsFromGroups(notificationGroups) { | 488 function combineCardsFromGroups(notificationGroups) { |
| 489 console.log('combineCardsFromGroups ' + JSON.stringify(notificationGroups)); | 489 console.log('combineCardsFromGroups ' + JSON.stringify(notificationGroups)); |
| 490 /** @type {Object.<ChromeNotificationId, CombinedCard>} */ | 490 /** @type {Object<ChromeNotificationId, CombinedCard>} */ |
| 491 var combinedCards = {}; | 491 var combinedCards = {}; |
| 492 | 492 |
| 493 for (var groupName in notificationGroups) | 493 for (var groupName in notificationGroups) |
| 494 combineGroup(combinedCards, notificationGroups[groupName]); | 494 combineGroup(combinedCards, notificationGroups[groupName]); |
| 495 | 495 |
| 496 return combinedCards; | 496 return combinedCards; |
| 497 } | 497 } |
| 498 | 498 |
| 499 /** | 499 /** |
| 500 * Processes a server response for consumption by showNotificationGroups. | 500 * Processes a server response for consumption by showNotificationGroups. |
| 501 * @param {ServerResponse} response Server response. | 501 * @param {ServerResponse} response Server response. |
| 502 * @return {Promise} A promise to process the server response and provide | 502 * @return {Promise} A promise to process the server response and provide |
| 503 * updated groups. Rejects if the server response shouldn't be processed. | 503 * updated groups. Rejects if the server response shouldn't be processed. |
| 504 */ | 504 */ |
| 505 function processServerResponse(response) { | 505 function processServerResponse(response) { |
| 506 console.log('processServerResponse ' + JSON.stringify(response)); | 506 console.log('processServerResponse ' + JSON.stringify(response)); |
| 507 | 507 |
| 508 if (response.googleNowDisabled) { | 508 if (response.googleNowDisabled) { |
| 509 chrome.storage.local.set({googleNowEnabled: false}); | 509 chrome.storage.local.set({googleNowEnabled: false}); |
| 510 // Stop processing now. The state change will clear the cards. | 510 // Stop processing now. The state change will clear the cards. |
| 511 return Promise.reject(); | 511 return Promise.reject(); |
| 512 } | 512 } |
| 513 | 513 |
| 514 var receivedGroups = response.groups; | 514 var receivedGroups = response.groups; |
| 515 | 515 |
| 516 return fillFromChromeLocalStorage({ | 516 return fillFromChromeLocalStorage({ |
| 517 /** @type {Object.<string, StoredNotificationGroup>} */ | 517 /** @type {Object<string, StoredNotificationGroup>} */ |
| 518 notificationGroups: {}, | 518 notificationGroups: {}, |
| 519 /** @type {Object.<ServerNotificationId, number>} */ | 519 /** @type {Object<ServerNotificationId, number>} */ |
| 520 recentDismissals: {} | 520 recentDismissals: {} |
| 521 }).then(function(items) { | 521 }).then(function(items) { |
| 522 console.log('processServerResponse-get ' + JSON.stringify(items)); | 522 console.log('processServerResponse-get ' + JSON.stringify(items)); |
| 523 | 523 |
| 524 // Build a set of non-expired recent dismissals. It will be used for | 524 // Build a set of non-expired recent dismissals. It will be used for |
| 525 // client-side filtering of cards. | 525 // client-side filtering of cards. |
| 526 /** @type {Object.<ServerNotificationId, number>} */ | 526 /** @type {Object<ServerNotificationId, number>} */ |
| 527 var updatedRecentDismissals = {}; | 527 var updatedRecentDismissals = {}; |
| 528 var now = Date.now(); | 528 var now = Date.now(); |
| 529 for (var serverNotificationId in items.recentDismissals) { | 529 for (var serverNotificationId in items.recentDismissals) { |
| 530 var dismissalAge = now - items.recentDismissals[serverNotificationId]; | 530 var dismissalAge = now - items.recentDismissals[serverNotificationId]; |
| 531 if (dismissalAge < DISMISS_RETENTION_TIME_MS) { | 531 if (dismissalAge < DISMISS_RETENTION_TIME_MS) { |
| 532 updatedRecentDismissals[serverNotificationId] = | 532 updatedRecentDismissals[serverNotificationId] = |
| 533 items.recentDismissals[serverNotificationId]; | 533 items.recentDismissals[serverNotificationId]; |
| 534 } | 534 } |
| 535 } | 535 } |
| 536 | 536 |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 605 * @return {boolean} true if an explanatory card should be shown. | 605 * @return {boolean} true if an explanatory card should be shown. |
| 606 */ | 606 */ |
| 607 function shouldShowExplanatoryCard() { | 607 function shouldShowExplanatoryCard() { |
| 608 var isBelowThreshold = | 608 var isBelowThreshold = |
| 609 localStorage['explanatoryCardsShown'] < EXPLANATORY_CARDS_LINK_THRESHOLD; | 609 localStorage['explanatoryCardsShown'] < EXPLANATORY_CARDS_LINK_THRESHOLD; |
| 610 return isBelowThreshold; | 610 return isBelowThreshold; |
| 611 } | 611 } |
| 612 | 612 |
| 613 /** | 613 /** |
| 614 * Requests notification cards from the server for specified groups. | 614 * Requests notification cards from the server for specified groups. |
| 615 * @param {Array.<string>} groupNames Names of groups that need to be refreshed. | 615 * @param {Array<string>} groupNames Names of groups that need to be refreshed. |
| 616 * @return {Promise} A promise to request the specified notification groups. | 616 * @return {Promise} A promise to request the specified notification groups. |
| 617 */ | 617 */ |
| 618 function requestNotificationGroupsFromServer(groupNames) { | 618 function requestNotificationGroupsFromServer(groupNames) { |
| 619 console.log( | 619 console.log( |
| 620 'requestNotificationGroupsFromServer from ' + NOTIFICATION_CARDS_URL + | 620 'requestNotificationGroupsFromServer from ' + NOTIFICATION_CARDS_URL + |
| 621 ', groupNames=' + JSON.stringify(groupNames)); | 621 ', groupNames=' + JSON.stringify(groupNames)); |
| 622 | 622 |
| 623 recordEvent(GoogleNowEvent.REQUEST_FOR_CARDS_TOTAL); | 623 recordEvent(GoogleNowEvent.REQUEST_FOR_CARDS_TOTAL); |
| 624 | 624 |
| 625 var requestParameters = '?timeZoneOffsetMs=' + | 625 var requestParameters = '?timeZoneOffsetMs=' + |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 687 return optedIn; | 687 return optedIn; |
| 688 }); | 688 }); |
| 689 } | 689 } |
| 690 | 690 |
| 691 /** | 691 /** |
| 692 * Determines the groups that need to be requested right now. | 692 * Determines the groups that need to be requested right now. |
| 693 * @return {Promise} A promise to determine the groups to request. | 693 * @return {Promise} A promise to determine the groups to request. |
| 694 */ | 694 */ |
| 695 function getGroupsToRequest() { | 695 function getGroupsToRequest() { |
| 696 return fillFromChromeLocalStorage({ | 696 return fillFromChromeLocalStorage({ |
| 697 /** @type {Object.<string, StoredNotificationGroup>} */ | 697 /** @type {Object<string, StoredNotificationGroup>} */ |
| 698 notificationGroups: {} | 698 notificationGroups: {} |
| 699 }).then(function(items) { | 699 }).then(function(items) { |
| 700 console.log('getGroupsToRequest-storage-get ' + JSON.stringify(items)); | 700 console.log('getGroupsToRequest-storage-get ' + JSON.stringify(items)); |
| 701 var groupsToRequest = []; | 701 var groupsToRequest = []; |
| 702 var now = Date.now(); | 702 var now = Date.now(); |
| 703 | 703 |
| 704 for (var groupName in items.notificationGroups) { | 704 for (var groupName in items.notificationGroups) { |
| 705 var group = items.notificationGroups[groupName]; | 705 var group = items.notificationGroups[groupName]; |
| 706 if (group.nextPollTime !== undefined && group.nextPollTime <= now) | 706 if (group.nextPollTime !== undefined && group.nextPollTime <= now) |
| 707 groupsToRequest.push(groupName); | 707 groupsToRequest.push(groupName); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 732 recordEvent(GoogleNowEvent.CARDS_PARSE_SUCCESS); | 732 recordEvent(GoogleNowEvent.CARDS_PARSE_SUCCESS); |
| 733 } | 733 } |
| 734 ); | 734 ); |
| 735 }); | 735 }); |
| 736 } | 736 } |
| 737 | 737 |
| 738 /** | 738 /** |
| 739 * Determines if an immediate retry should occur based off of the given groups. | 739 * Determines if an immediate retry should occur based off of the given groups. |
| 740 * The NOR group is expected most often and less latency sensitive, so we will | 740 * The NOR group is expected most often and less latency sensitive, so we will |
| 741 * simply wait MAXIMUM_POLLING_PERIOD_SECONDS before trying again. | 741 * simply wait MAXIMUM_POLLING_PERIOD_SECONDS before trying again. |
| 742 * @param {Array.<string>} groupNames Names of groups that need to be refreshed. | 742 * @param {Array<string>} groupNames Names of groups that need to be refreshed. |
| 743 * @return {boolean} Whether a retry should occur. | 743 * @return {boolean} Whether a retry should occur. |
| 744 */ | 744 */ |
| 745 function shouldScheduleRetryFromGroupList(groupNames) { | 745 function shouldScheduleRetryFromGroupList(groupNames) { |
| 746 return (groupNames.length != 1) || (groupNames[0] !== 'NOR'); | 746 return (groupNames.length != 1) || (groupNames[0] !== 'NOR'); |
| 747 } | 747 } |
| 748 | 748 |
| 749 /** | 749 /** |
| 750 * Requests and shows notification cards. | 750 * Requests and shows notification cards. |
| 751 */ | 751 */ |
| 752 function requestCards() { | 752 function requestCards() { |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 826 }); | 826 }); |
| 827 } | 827 } |
| 828 | 828 |
| 829 /** | 829 /** |
| 830 * Tries to send dismiss requests for all pending dismissals. | 830 * Tries to send dismiss requests for all pending dismissals. |
| 831 * @return {Promise} A promise to process the pending dismissals. | 831 * @return {Promise} A promise to process the pending dismissals. |
| 832 * The promise is rejected if a problem was encountered. | 832 * The promise is rejected if a problem was encountered. |
| 833 */ | 833 */ |
| 834 function processPendingDismissals() { | 834 function processPendingDismissals() { |
| 835 return fillFromChromeLocalStorage({ | 835 return fillFromChromeLocalStorage({ |
| 836 /** @type {Array.<PendingDismissal>} */ | 836 /** @type {Array<PendingDismissal>} */ |
| 837 pendingDismissals: [], | 837 pendingDismissals: [], |
| 838 /** @type {Object.<ServerNotificationId, number>} */ | 838 /** @type {Object<ServerNotificationId, number>} */ |
| 839 recentDismissals: {} | 839 recentDismissals: {} |
| 840 }).then(function(items) { | 840 }).then(function(items) { |
| 841 console.log( | 841 console.log( |
| 842 'processPendingDismissals-storage-get ' + JSON.stringify(items)); | 842 'processPendingDismissals-storage-get ' + JSON.stringify(items)); |
| 843 | 843 |
| 844 var dismissalsChanged = false; | 844 var dismissalsChanged = false; |
| 845 | 845 |
| 846 function onFinish(success) { | 846 function onFinish(success) { |
| 847 if (dismissalsChanged) { | 847 if (dismissalsChanged) { |
| 848 chrome.storage.local.set({ | 848 chrome.storage.local.set({ |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 906 /** | 906 /** |
| 907 * Opens URL corresponding to the clicked part of the notification. | 907 * Opens URL corresponding to the clicked part of the notification. |
| 908 * @param {ChromeNotificationId} chromeNotificationId chrome.notifications ID of | 908 * @param {ChromeNotificationId} chromeNotificationId chrome.notifications ID of |
| 909 * the card. | 909 * the card. |
| 910 * @param {function(NotificationDataEntry): (string|undefined)} selector | 910 * @param {function(NotificationDataEntry): (string|undefined)} selector |
| 911 * Function that extracts the url for the clicked area from the | 911 * Function that extracts the url for the clicked area from the |
| 912 * notification data entry. | 912 * notification data entry. |
| 913 */ | 913 */ |
| 914 function onNotificationClicked(chromeNotificationId, selector) { | 914 function onNotificationClicked(chromeNotificationId, selector) { |
| 915 fillFromChromeLocalStorage({ | 915 fillFromChromeLocalStorage({ |
| 916 /** @type {Object.<ChromeNotificationId, NotificationDataEntry>} */ | 916 /** @type {Object<ChromeNotificationId, NotificationDataEntry>} */ |
| 917 notificationsData: {} | 917 notificationsData: {} |
| 918 }).then(function(items) { | 918 }).then(function(items) { |
| 919 /** @type {(NotificationDataEntry|undefined)} */ | 919 /** @type {(NotificationDataEntry|undefined)} */ |
| 920 var notificationDataEntry = items.notificationsData[chromeNotificationId]; | 920 var notificationDataEntry = items.notificationsData[chromeNotificationId]; |
| 921 if (!notificationDataEntry) | 921 if (!notificationDataEntry) |
| 922 return; | 922 return; |
| 923 | 923 |
| 924 var url = selector(notificationDataEntry); | 924 var url = selector(notificationDataEntry); |
| 925 if (!url) | 925 if (!url) |
| 926 return; | 926 return; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 939 if (!byUser) | 939 if (!byUser) |
| 940 return; | 940 return; |
| 941 | 941 |
| 942 // At this point we are guaranteed that the notification is a now card. | 942 // At this point we are guaranteed that the notification is a now card. |
| 943 chrome.metricsPrivate.recordUserAction('GoogleNow.Dismissed'); | 943 chrome.metricsPrivate.recordUserAction('GoogleNow.Dismissed'); |
| 944 | 944 |
| 945 tasks.add(DISMISS_CARD_TASK_NAME, function() { | 945 tasks.add(DISMISS_CARD_TASK_NAME, function() { |
| 946 dismissalAttempts.start(); | 946 dismissalAttempts.start(); |
| 947 | 947 |
| 948 fillFromChromeLocalStorage({ | 948 fillFromChromeLocalStorage({ |
| 949 /** @type {Array.<PendingDismissal>} */ | 949 /** @type {Array<PendingDismissal>} */ |
| 950 pendingDismissals: [], | 950 pendingDismissals: [], |
| 951 /** @type {Object.<ChromeNotificationId, NotificationDataEntry>} */ | 951 /** @type {Object<ChromeNotificationId, NotificationDataEntry>} */ |
| 952 notificationsData: {}, | 952 notificationsData: {}, |
| 953 /** @type {Object.<string, StoredNotificationGroup>} */ | 953 /** @type {Object<string, StoredNotificationGroup>} */ |
| 954 notificationGroups: {} | 954 notificationGroups: {} |
| 955 }).then(function(items) { | 955 }).then(function(items) { |
| 956 /** @type {NotificationDataEntry} */ | 956 /** @type {NotificationDataEntry} */ |
| 957 var notificationData = | 957 var notificationData = |
| 958 items.notificationsData[chromeNotificationId] || | 958 items.notificationsData[chromeNotificationId] || |
| 959 { | 959 { |
| 960 timestamp: Date.now(), | 960 timestamp: Date.now(), |
| 961 combinedCard: [] | 961 combinedCard: [] |
| 962 }; | 962 }; |
| 963 | 963 |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1251 }); | 1251 }); |
| 1252 | 1252 |
| 1253 instrumented.runtime.onStartup.addListener(function() { | 1253 instrumented.runtime.onStartup.addListener(function() { |
| 1254 console.log('onStartup'); | 1254 console.log('onStartup'); |
| 1255 | 1255 |
| 1256 // Show notifications received by earlier polls. Doing this as early as | 1256 // Show notifications received by earlier polls. Doing this as early as |
| 1257 // possible to reduce latency of showing first notifications. This mimics how | 1257 // possible to reduce latency of showing first notifications. This mimics how |
| 1258 // persistent notifications will work. | 1258 // persistent notifications will work. |
| 1259 tasks.add(SHOW_ON_START_TASK_NAME, function() { | 1259 tasks.add(SHOW_ON_START_TASK_NAME, function() { |
| 1260 fillFromChromeLocalStorage({ | 1260 fillFromChromeLocalStorage({ |
| 1261 /** @type {Object.<string, StoredNotificationGroup>} */ | 1261 /** @type {Object<string, StoredNotificationGroup>} */ |
| 1262 notificationGroups: {} | 1262 notificationGroups: {} |
| 1263 }).then(function(items) { | 1263 }).then(function(items) { |
| 1264 console.log('onStartup-get ' + JSON.stringify(items)); | 1264 console.log('onStartup-get ' + JSON.stringify(items)); |
| 1265 | 1265 |
| 1266 showNotificationGroups(items.notificationGroups).then(function() { | 1266 showNotificationGroups(items.notificationGroups).then(function() { |
| 1267 chrome.storage.local.set(items); | 1267 chrome.storage.local.set(items); |
| 1268 }); | 1268 }); |
| 1269 }); | 1269 }); |
| 1270 }); | 1270 }); |
| 1271 | 1271 |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1339 // Each time after signing in, we'll get latest payload for all channels. | 1339 // Each time after signing in, we'll get latest payload for all channels. |
| 1340 // So, we need to poll the server only when the payload is non-empty and has | 1340 // So, we need to poll the server only when the payload is non-empty and has |
| 1341 // changed. | 1341 // changed. |
| 1342 console.log('pushMessaging.onMessage ' + JSON.stringify(message)); | 1342 console.log('pushMessaging.onMessage ' + JSON.stringify(message)); |
| 1343 if (message.payload.indexOf('REQUEST_CARDS') == 0) { | 1343 if (message.payload.indexOf('REQUEST_CARDS') == 0) { |
| 1344 tasks.add(ON_PUSH_MESSAGE_START_TASK_NAME, function() { | 1344 tasks.add(ON_PUSH_MESSAGE_START_TASK_NAME, function() { |
| 1345 // Accept promise rejection on failure since it's safer to do nothing, | 1345 // Accept promise rejection on failure since it's safer to do nothing, |
| 1346 // preventing polling the server when the payload really didn't change. | 1346 // preventing polling the server when the payload really didn't change. |
| 1347 fillFromChromeLocalStorage({ | 1347 fillFromChromeLocalStorage({ |
| 1348 lastPollNowPayloads: {}, | 1348 lastPollNowPayloads: {}, |
| 1349 /** @type {Object.<string, StoredNotificationGroup>} */ | 1349 /** @type {Object<string, StoredNotificationGroup>} */ |
| 1350 notificationGroups: {} | 1350 notificationGroups: {} |
| 1351 }, PromiseRejection.ALLOW).then(function(items) { | 1351 }, PromiseRejection.ALLOW).then(function(items) { |
| 1352 if (items.lastPollNowPayloads[message.subchannelId] != | 1352 if (items.lastPollNowPayloads[message.subchannelId] != |
| 1353 message.payload) { | 1353 message.payload) { |
| 1354 items.lastPollNowPayloads[message.subchannelId] = message.payload; | 1354 items.lastPollNowPayloads[message.subchannelId] = message.payload; |
| 1355 | 1355 |
| 1356 items.notificationGroups['PUSH' + message.subchannelId] = { | 1356 items.notificationGroups['PUSH' + message.subchannelId] = { |
| 1357 cards: [], | 1357 cards: [], |
| 1358 nextPollTime: Date.now() | 1358 nextPollTime: Date.now() |
| 1359 }; | 1359 }; |
| 1360 | 1360 |
| 1361 chrome.storage.local.set({ | 1361 chrome.storage.local.set({ |
| 1362 lastPollNowPayloads: items.lastPollNowPayloads, | 1362 lastPollNowPayloads: items.lastPollNowPayloads, |
| 1363 notificationGroups: items.notificationGroups | 1363 notificationGroups: items.notificationGroups |
| 1364 }); | 1364 }); |
| 1365 | 1365 |
| 1366 pollOptedInWithRecheck(); | 1366 pollOptedInWithRecheck(); |
| 1367 } | 1367 } |
| 1368 }); | 1368 }); |
| 1369 }); | 1369 }); |
| 1370 } | 1370 } |
| 1371 }); | 1371 }); |
| OLD | NEW |