Chromium Code Reviews| Index: chrome/browser/resources/google_now/background.js |
| diff --git a/chrome/browser/resources/google_now/background.js b/chrome/browser/resources/google_now/background.js |
| index 1441dc5d0b6e2a8219c4a77552532e49427ce0ef..82263a8790ba82ea5698b5df178dc096860e538f 100644 |
| --- a/chrome/browser/resources/google_now/background.js |
| +++ b/chrome/browser/resources/google_now/background.js |
| @@ -102,19 +102,26 @@ var ON_PUSH_MESSAGE_START_TASK_NAME = 'on-push-message'; |
| var LOCATION_WATCH_NAME = 'location-watch'; |
| /** |
| - * Notification as it's sent by the server. |
| + * Group as received from the server. |
| * |
| * @typedef {{ |
| - * notificationId: string, |
| - * chromeNotificationId: string, |
| - * trigger: Object=, |
| - * version: number, |
| - * chromeNotificationOptions: Object, |
| - * actionUrls: Object=, |
| - * dismissal: Object |
| + * nextPollSeconds: (string|undefined), |
| + * rank: (number|undefined), |
| + * requested: (boolean|undefined) |
| * }} |
| */ |
| -var UnmergedNotification; |
| +var ReceivedGroup; |
| + |
| +/** |
| + * Server response with notifications and groups. |
| + * |
| + * @typedef {{ |
| + * googleNowDisabled: (boolean|undefined), |
| + * groups: Object.<string, ReceivedGroup>, |
| + * notifications: Array.<ReceivedNotification> |
| + * }} |
| + */ |
| +var ServerResponse; |
| /** |
| * Notification group as the client stores it. |cardsTimestamp| and |rank| are |
| @@ -124,13 +131,25 @@ var UnmergedNotification; |
| * cards update and all the times after that. |
| * |
| * @typedef {{ |
| - * cards: Array.<UnmergedNotification>, |
| - * cardsTimestamp: number=, |
| - * nextPollTime: number=, |
| - * rank: number= |
| + * cards: Array.<ReceivedNotification>, |
| + * cardsTimestamp: (number|undefined), |
| + * nextPollTime: (number|undefined), |
| + * rank: (number|undefined) |
| * }} |
| */ |
| -var StorageGroup; |
| +var StoredNotificationGroup; |
| + |
| +/** |
| + * Pending (not yet successfully sent) dismissal for a received notification. |
| + * |time| is the moment when the user requested dismissal. |
| + * |
| + * @typedef {{ |
| + * chromeNotificationId: ChromeNotificationId, |
| + * time: number, |
| + * dismissalData: DismissalData |
| + * }} |
| + */ |
| +var PendingDismissal; |
| /** |
| * Checks if a new task can't be scheduled when another task is already |
| @@ -273,74 +292,38 @@ function setAuthorization(request, callbackBoolean) { |
| } |
| /** |
| - * Shows parsed and merged cards as notifications. |
| - * @param {Object.<string, MergedCard>} cards Map from chromeNotificationId to |
| - * the merged card, containing cards to show. |
| - * @param {function(CardCreateInfo)=} onCardShown Optional parameter called when |
| - * each card is shown. |
| + * Shows parsed and combined cards as notifications. |
| + * @param {Object.<ChromeNotificationId, CombinedCard>} cards Map from |
| + * chromeNotificationId to the combined card, containing cards to show. |
| + * @param {function(ReceivedNotification)=} onCardShown Optional parameter |
| + * called when each card is shown. |
| */ |
| function showNotificationCards(cards, onCardShown) { |
| console.log('showNotificationCards ' + JSON.stringify(cards)); |
| - instrumented.storage.local.get(['notificationsData', 'recentDismissals'], |
| - function(items) { |
| - console.log('showNotificationCards-get ' + |
| - JSON.stringify(items)); |
| - items = items || {}; |
| - items.notificationsData = items.notificationsData || {}; |
| - items.recentDismissals = items.recentDismissals || {}; |
| - |
| - instrumented.notifications.getAll(function(notifications) { |
| - console.log('showNotificationCards-getAll ' + |
| - JSON.stringify(notifications)); |
| - notifications = notifications || {}; |
| - |
| - // Build a set of non-expired recent dismissals. It will be used for |
| - // client-side filtering of cards. |
| - var updatedRecentDismissals = {}; |
| - var currentTimeMs = Date.now(); |
| - for (var chromeNotificationId in items.recentDismissals) { |
| - if (currentTimeMs - items.recentDismissals[chromeNotificationId] < |
| - DISMISS_RETENTION_TIME_MS) { |
| - updatedRecentDismissals[chromeNotificationId] = |
| - items.recentDismissals[chromeNotificationId]; |
| - delete cards[chromeNotificationId]; |
| - } |
| - } |
| + instrumented.notifications.getAll(function(notifications) { |
| + console.log('showNotificationCards-getAll ' + |
| + JSON.stringify(notifications)); |
| + notifications = notifications || {}; |
| - // Delete notifications that didn't receive an update. |
| - for (var chromeNotificationId in notifications) { |
| - console.log('showNotificationCards-delete-check ' + |
| - chromeNotificationId); |
| - if (!(chromeNotificationId in cards)) { |
| - console.log( |
| - 'showNotificationCards-delete ' + chromeNotificationId); |
| - cardSet.clear(chromeNotificationId, false); |
| - } |
| - } |
| + // Mark notifications that didn't receive an update as having received |
| + // an empty update. |
| + for (var chromeNotificationId in notifications) { |
| + cards[chromeNotificationId] = cards[chromeNotificationId] || []; |
| + } |
| - // Create/update notifications and store their new properties. |
| - var newNotificationsData = {}; |
| - for (var chromeNotificationId in cards) { |
| - var notificationData = |
| - items.notificationsData[chromeNotificationId]; |
| - var previousVersion = notifications[chromeNotificationId] && |
| - notificationData && |
| - notificationData.cardCreateInfo && |
| - notificationData.cardCreateInfo.version; |
| - newNotificationsData[chromeNotificationId] = cardSet.update( |
| - chromeNotificationId, |
| - cards[chromeNotificationId], |
| - previousVersion, |
| - onCardShown); |
| - } |
| + /** @type {Object.<string, NotificationDataEntry>} */ |
| + var notificationsData = {}; |
| - chrome.storage.local.set({ |
| - notificationsData: newNotificationsData, |
| - recentDismissals: updatedRecentDismissals |
| - }); |
| - }); |
| - }); |
| + // Create/update/delete notifications. |
| + for (var chromeNotificationId in cards) { |
| + notificationsData[chromeNotificationId] = cardSet.update( |
| + chromeNotificationId, |
| + cards[chromeNotificationId], |
| + onCardShown); |
| + } |
| + chrome.storage.local.set({notificationsData: notificationsData}); |
| + }); |
| } |
| /** |
| @@ -364,89 +347,39 @@ function removeAllCards() { |
| } |
| /** |
| - * Merges an unmerged notification into a merged card with same ID. |
| - * @param {MergedCard=} mergedCard Existing merged card or undefined if a merged |
| - * card doesn't exist (i.e. we see this ID for the first time while |
| - * merging). |
| - * @param {UnmergedNotification} unmergedNotification Notification as it was |
| - * received from the server. |
| - * @param {number} notificationTimestamp The moment the unmerged card was |
| - * received. |
| - * @param {number} notificationGroupRank Rank of the group of the unmerged card. |
| - * @return {MergedCard} Result of merging |unmergedNotification| into |
| - * |mergedCard|. |
| + * Adds a card group into a set of combined cards. |
| + * @param {Object.<ChromeNotificationId, CombinedCard>} combinedCards Map from |
| + * chromeNotificationId to a combined card. |
| + * This is an input/output parameter. |
| + * @param {StoredNotificationGroup} storedGroup Group to combine into the |
| + * combined card set. |
| */ |
| -function mergeCards( |
| - mergedCard, |
| - unmergedNotification, |
| - notificationTimestamp, |
| - notificationGroupRank) { |
| - var result = mergedCard || {dismissals: []}; |
| - |
| - var priority = mergedCard ? |
| - Math.max( |
| - mergedCard.notification.priority, |
| - unmergedNotification.chromeNotificationOptions.priority) : |
| - unmergedNotification.chromeNotificationOptions.priority; |
| - |
| - if (!mergedCard || notificationGroupRank > mergedCard.groupRank) { |
| - result.groupRank = notificationGroupRank; |
| - var showTime = unmergedNotification.trigger && |
| - unmergedNotification.trigger.showTimeSec && |
| - (notificationTimestamp + |
| - unmergedNotification.trigger.showTimeSec * MS_IN_SECOND); |
| - var hideTime = unmergedNotification.trigger && |
| - unmergedNotification.trigger.hideTimeSec && |
| - (notificationTimestamp + |
| - unmergedNotification.trigger.hideTimeSec * MS_IN_SECOND); |
| - result.trigger = { |
| - showTime: showTime, |
| - hideTime: hideTime |
| +function combineGroup(combinedCards, storedGroup) { |
| + for (var i = 0; i < storedGroup.cards.length; i++) { |
| + /** @type {ReceivedNotification} */ |
| + var receivedNotification = storedGroup.cards[i]; |
| + |
| + /** @type {UncombinedNotification} */ |
| + var uncombinedNotification = { |
| + receivedNotification: receivedNotification, |
| + showTime: receivedNotification.trigger.showTimeSec && |
| + (storedGroup.cardsTimestamp + |
| + receivedNotification.trigger.showTimeSec * MS_IN_SECOND), |
| + hideTime: storedGroup.cardsTimestamp + |
| + receivedNotification.trigger.hideTimeSec * MS_IN_SECOND |
| }; |
| - } |
| - if (!mergedCard || notificationTimestamp > mergedCard.timestamp) { |
| - result.timestamp = notificationTimestamp; |
| - result.notification = unmergedNotification.chromeNotificationOptions; |
| - result.actionUrls = unmergedNotification.actionUrls; |
| - result.version = unmergedNotification.version; |
| - } |
| - |
| - result.locationBased = |
| - result.locationBased || unmergedNotification.locationBased; |
| - |
| - result.notification.priority = priority; |
| - var dismissalData = { |
| - notificationId: unmergedNotification.notificationId, |
| - parameters: unmergedNotification.dismissal |
| - }; |
| - result.dismissals.push(dismissalData); |
| - |
| - return result; |
| -} |
| - |
| -/** |
| - * Merges a card group into a set of merged cards. |
| - * @param {Object.<string, MergedCard>} mergedCards Map from |
| - * chromeNotificationId to a merged card. |
| - * This is an input/output parameter. |
| - * @param {StorageGroup} storageGroup Group to merge into the merged card set. |
| - */ |
| -function mergeGroup(mergedCards, storageGroup) { |
| - for (var i = 0; i < storageGroup.cards.length; i++) { |
| - var card = storageGroup.cards[i]; |
| - mergedCards[card.chromeNotificationId] = mergeCards( |
| - mergedCards[card.chromeNotificationId], |
| - card, |
| - storageGroup.cardsTimestamp, |
| - storageGroup.rank); |
| + var combinedCard = |
| + combinedCards[receivedNotification.chromeNotificationId] || []; |
| + combinedCard.push(uncombinedNotification); |
| + combinedCards[receivedNotification.chromeNotificationId] = combinedCard; |
| } |
| } |
| /** |
| * Schedules next cards poll. |
| - * @param {Object.<string, StorageGroup>} groups Map from group name to group |
| - * information. |
| + * @param {Object.<string, StoredNotificationGroup>} groups Map from group name |
| + * to group information. |
| * @param {boolean} isOptedIn True if the user is opted in to Google Now. |
| */ |
| function scheduleNextPoll(groups, isOptedIn) { |
| @@ -480,30 +413,35 @@ function scheduleNextPoll(groups, isOptedIn) { |
| } |
| /** |
| - * Merges notification groups into a set of Chrome notifications and shows them. |
| - * @param {Object.<string, StorageGroup>} notificationGroups Map from group name |
| - * to group information. |
| - * @param {function(CardCreateInfo)=} onCardShown Optional parameter called when |
| - * each card is shown. |
| + * Combines notification groups into a set of Chrome notifications and shows |
| + * them. |
| + * @param {Object.<string, StoredNotificationGroup>} notificationGroups Map from |
| + * group name to group information. |
| + * @param {function(ReceivedNotification)=} onCardShown Optional parameter |
| + * called when each card is shown. |
| */ |
| -function mergeAndShowNotificationCards(notificationGroups, onCardShown) { |
| - var mergedCards = {}; |
| +function combineAndShowNotificationCards(notificationGroups, onCardShown) { |
| + console.log('combineAndShowNotificationCards ' + |
| + JSON.stringify(notificationGroups)); |
| + /** @type {Object.<ChromeNotificationId, CombinedCard>} */ |
| + var combinedCards = {}; |
| for (var groupName in notificationGroups) |
| - mergeGroup(mergedCards, notificationGroups[groupName]); |
| + combineGroup(combinedCards, notificationGroups[groupName]); |
| - showNotificationCards(mergedCards, onCardShown); |
| + showNotificationCards(combinedCards, onCardShown); |
| } |
| /** |
| * Parses JSON response from the notification server, shows notifications and |
| * schedules next update. |
| * @param {string} response Server response. |
| - * @param {function(CardCreateInfo)=} onCardShown Optional parameter called when |
| - * each card is shown. |
| + * @param {function(ReceivedNotification)=} onCardShown Optional parameter |
| + * called when each card is shown. |
| */ |
| function parseAndShowNotificationCards(response, onCardShown) { |
| console.log('parseAndShowNotificationCards ' + response); |
| + /** @type {ServerResponse} */ |
| var parsedResponse = JSON.parse(response); |
| if (parsedResponse.googleNowDisabled) { |
| @@ -517,29 +455,47 @@ function parseAndShowNotificationCards(response, onCardShown) { |
| var receivedGroups = parsedResponse.groups; |
| - // Populate groups with corresponding cards. |
| - if (parsedResponse.notifications) { |
| - for (var i = 0; i != parsedResponse.notifications.length; ++i) { |
| - var card = parsedResponse.notifications[i]; |
| - var group = receivedGroups[card.groupName]; |
| - group.cards = group.cards || []; |
| - group.cards.push(card); |
| - } |
| - } |
| - |
| - instrumented.storage.local.get('notificationGroups', function(items) { |
| + instrumented.storage.local.get(['notificationGroups', 'recentDismissals'], |
| + function(items) { |
| console.log('parseAndShowNotificationCards-get ' + JSON.stringify(items)); |
|
robliao
2013/12/07 00:51:29
Style: These need to be tabbed over two spaces.
vadimt
2013/12/07 01:04:24
Done.
|
| items = items || {}; |
| + /** @type {Object.<string, StoredNotificationGroup>} */ |
| items.notificationGroups = items.notificationGroups || {}; |
| + /** @type {Object.<NotificationId, number>} */ |
| + items.recentDismissals = items.recentDismissals || {}; |
| + |
| + // Build a set of non-expired recent dismissals. It will be used for |
| + // client-side filtering of cards. |
| + /** @type {Object.<NotificationId, number>} */ |
| + var updatedRecentDismissals = {}; |
| + var now = Date.now(); |
| + for (var notificationId in items.recentDismissals) { |
| + var dismissalAge = now - items.recentDismissals[notificationId]; |
| + if (dismissalAge < DISMISS_RETENTION_TIME_MS) { |
| + updatedRecentDismissals[notificationId] = |
| + items.recentDismissals[notificationId]; |
| + } |
| + } |
| - var now = Date.now(); |
| + // Populate groups with corresponding cards. |
| + if (parsedResponse.notifications) { |
| + for (var i = 0; i < parsedResponse.notifications.length; ++i) { |
| + /** @type {ReceivedNotification} */ |
| + var card = parsedResponse.notifications[i]; |
| + if (!(card.notificationId in updatedRecentDismissals)) { |
| + var group = receivedGroups[card.groupName]; |
| + group.cards = group.cards || []; |
| + group.cards.push(card); |
| + } |
| + } |
| + } |
| // Build updated set of groups. |
| var updatedGroups = {}; |
| for (var groupName in receivedGroups) { |
| var receivedGroup = receivedGroups[groupName]; |
| - var storageGroup = items.notificationGroups[groupName] || { |
| + var storedGroup = items.notificationGroups[groupName] || { |
| cards: [], |
| cardsTimestamp: undefined, |
| nextPollTime: undefined, |
| @@ -552,10 +508,10 @@ function parseAndShowNotificationCards(response, onCardShown) { |
| if (receivedGroup.cards) { |
| // If the group contains a cards update, all its fields will get new |
| // values. |
| - storageGroup.cards = receivedGroup.cards; |
| - storageGroup.cardsTimestamp = now; |
| - storageGroup.rank = receivedGroup.rank; |
| - storageGroup.nextPollTime = undefined; |
| + storedGroup.cards = receivedGroup.cards; |
| + storedGroup.cardsTimestamp = now; |
| + storedGroup.rank = receivedGroup.rank; |
| + storedGroup.nextPollTime = undefined; |
| // The code below assigns nextPollTime a defined value if |
| // nextPollSeconds is specified in the received group. |
| // If the group's cards are not updated, and nextPollSeconds is |
| @@ -565,26 +521,30 @@ function parseAndShowNotificationCards(response, onCardShown) { |
| // 'nextPollSeconds' may be sent even for groups that don't contain cards |
| // updates. |
| if (receivedGroup.nextPollSeconds !== undefined) { |
| - storageGroup.nextPollTime = |
| + storedGroup.nextPollTime = |
| now + receivedGroup.nextPollSeconds * MS_IN_SECOND; |
| } |
| - updatedGroups[groupName] = storageGroup; |
| + updatedGroups[groupName] = storedGroup; |
| } |
| scheduleNextPoll(updatedGroups, !parsedResponse.googleNowDisabled); |
| - chrome.storage.local.set({notificationGroups: updatedGroups}); |
| - mergeAndShowNotificationCards(updatedGroups, onCardShown); |
| + chrome.storage.local.set({ |
| + notificationGroups: updatedGroups, |
| + recentDismissals: updatedRecentDismissals |
| + }); |
| + combineAndShowNotificationCards(updatedGroups, onCardShown); |
| recordEvent(GoogleNowEvent.CARDS_PARSE_SUCCESS); |
| }); |
| } |
| /** |
| * Update Location Cards Shown Count. |
| - * @param {Object} cardCreateInfo Card Create Info |
| + * @param {ReceivedNotification} receivedNotification Notification as it was |
| + * received from the server. |
| */ |
| -function countLocationCard(cardCreateInfo) { |
| - if (cardCreateInfo.locationBased) { |
| +function countLocationCard(receivedNotification) { |
| + if (receivedNotification.locationBased) { |
| localStorage['locationCardsShown']++; |
| } |
| } |
| @@ -620,7 +580,7 @@ function requestNotificationGroups(groupNames) { |
| console.log('requestNotificationGroups-onloadend ' + request.status); |
| if (request.status == HTTP_OK) { |
| recordEvent(GoogleNowEvent.REQUEST_FOR_CARDS_SUCCESS); |
| - parseAndShowNotificationCards(request.response, cardShownCallback); |
| + parseAndShowNotificationCards(request.responseText, cardShownCallback); |
| } |
| }; |
| @@ -644,7 +604,7 @@ function requestOptedIn(optedInCallback) { |
| console.log( |
| 'requestOptedIn-onloadend ' + request.status + ' ' + request.response); |
| if (request.status == HTTP_OK) { |
| - var parsedResponse = JSON.parse(request.response); |
| + var parsedResponse = JSON.parse(request.responseText); |
| if (parsedResponse.value) { |
| chrome.storage.local.set({googleNowEnabled: true}); |
| optedInCallback(); |
| @@ -664,7 +624,7 @@ function requestOptedIn(optedInCallback) { |
| /** |
| * Requests notification cards from the server. |
| - * @param {Location} position Location of this computer. |
| + * @param {Location=} position Location of this computer. |
| */ |
| function requestNotificationCards(position) { |
| console.log('requestNotificationCards ' + JSON.stringify(position)); |
| @@ -674,17 +634,17 @@ function requestNotificationCards(position) { |
| console.log('requestNotificationCards-storage-get ' + |
| JSON.stringify(items)); |
| items = items || {}; |
| + /** @type {Object.<string, StoredNotificationGroup>} */ |
| + items.notificationGroups = items.notificationGroups || {}; |
| var groupsToRequest = []; |
| - if (items.notificationGroups) { |
| - var now = Date.now(); |
| + var now = Date.now(); |
| - for (var groupName in items.notificationGroups) { |
| - var group = items.notificationGroups[groupName]; |
| - if (group.nextPollTime !== undefined && group.nextPollTime <= now) |
| - groupsToRequest.push(groupName); |
| - } |
| + for (var groupName in items.notificationGroups) { |
| + var group = items.notificationGroups[groupName]; |
| + if (group.nextPollTime !== undefined && group.nextPollTime <= now) |
| + groupsToRequest.push(groupName); |
| } |
| if (items.googleNowEnabled) { |
| @@ -736,7 +696,7 @@ function stopRequestLocation() { |
| /** |
| * Obtains new location; requests and shows notification cards based on this |
| * location. |
| - * @param {Location} position Location of this computer. |
| + * @param {Location=} position Location of this computer. |
| */ |
| function updateNotificationsCards(position) { |
| console.log('updateNotificationsCards ' + JSON.stringify(position) + |
| @@ -760,7 +720,8 @@ function updateNotificationsCards(position) { |
| /** |
| * Sends a server request to dismiss a card. |
| - * @param {string} chromeNotificationId chrome.notifications ID of the card. |
| + * @param {ChromeNotificationId} chromeNotificationId chrome.notifications ID of |
| + * the card. |
| * @param {number} dismissalTimeMs Time of the user's dismissal of the card in |
| * milliseconds since epoch. |
| * @param {DismissalData} dismissalData Data to build a dismissal request. |
| @@ -769,8 +730,9 @@ function updateNotificationsCards(position) { |
| */ |
| function requestCardDismissal( |
| chromeNotificationId, dismissalTimeMs, dismissalData, callbackBoolean) { |
| - console.log('requestDismissingCard ' + chromeNotificationId + ' from ' + |
| - NOTIFICATION_CARDS_URL); |
| + console.log('requestDismissingCard ' + chromeNotificationId + |
| + ' from ' + NOTIFICATION_CARDS_URL + |
| + ', dismissalData=' + JSON.stringify(dismissalData)); |
| var dismissalAge = Date.now() - dismissalTimeMs; |
| @@ -781,16 +743,17 @@ function requestCardDismissal( |
| recordEvent(GoogleNowEvent.DISMISS_REQUEST_TOTAL); |
| - var request = 'notifications/' + dismissalData.notificationId + |
| + var requestParameters = 'notifications/' + dismissalData.notificationId + |
| '?age=' + dismissalAge + |
| '&chromeNotificationId=' + chromeNotificationId; |
| for (var paramField in dismissalData.parameters) |
| - request += ('&' + paramField + '=' + dismissalData.parameters[paramField]); |
| + requestParameters += ('&' + paramField + |
| + '=' + dismissalData.parameters[paramField]); |
| - console.log('requestCardDismissal: request=' + request); |
| + console.log('requestCardDismissal: requestParameters=' + requestParameters); |
| - var request = buildServerRequest('DELETE', request); |
| + var request = buildServerRequest('DELETE', requestParameters); |
| request.onloadend = function(event) { |
| console.log('requestDismissingCard-onloadend ' + request.status); |
| if (request.status == HTTP_NOCONTENT) |
| @@ -823,7 +786,9 @@ function processPendingDismissals(callbackBoolean) { |
| console.log('processPendingDismissals-storage-get ' + |
| JSON.stringify(items)); |
| items = items || {}; |
| + /** @type {Array.<PendingDismissal>} */ |
| items.pendingDismissals = items.pendingDismissals || []; |
| + /** @type {Object.<NotificationId, number>} */ |
| items.recentDismissals = items.recentDismissals || {}; |
| var dismissalsChanged = false; |
| @@ -847,6 +812,7 @@ function processPendingDismissals(callbackBoolean) { |
| // Send dismissal for the first card, and if successful, repeat |
| // recursively with the rest. |
| + /** @type {PendingDismissal} */ |
| var dismissal = items.pendingDismissals[0]; |
| requestCardDismissal( |
| dismissal.chromeNotificationId, |
| @@ -856,7 +822,8 @@ function processPendingDismissals(callbackBoolean) { |
| if (done) { |
| dismissalsChanged = true; |
| items.pendingDismissals.splice(0, 1); |
| - items.recentDismissals[dismissal.chromeNotificationId] = |
| + items.recentDismissals[ |
| + dismissal.dismissalData.notificationId] = |
| Date.now(); |
| doProcessDismissals(); |
| } else { |
| @@ -895,12 +862,15 @@ function openUrl(url) { |
| /** |
| * Opens URL corresponding to the clicked part of the notification. |
| - * @param {string} chromeNotificationId chrome.notifications ID of the card. |
| - * @param {function(Object): string} selector Function that extracts the url for |
| - * the clicked area from the button action URLs info. |
| + * @param {ChromeNotificationId} chromeNotificationId chrome.notifications ID of |
| + * the card. |
| + * @param {function((ActionUrls|undefined)): (string|undefined)} selector |
| + * Function that extracts the url for the clicked area from the button |
| + * action URLs info. |
| */ |
| function onNotificationClicked(chromeNotificationId, selector) { |
| instrumented.storage.local.get('notificationsData', function(items) { |
| + /** @type {(NotificationDataEntry|undefined)} */ |
| var notificationData = items && |
| items.notificationsData && |
| items.notificationsData[chromeNotificationId]; |
| @@ -918,7 +888,8 @@ function onNotificationClicked(chromeNotificationId, selector) { |
| /** |
| * Callback for chrome.notifications.onClosed event. |
| - * @param {string} chromeNotificationId chrome.notifications ID of the card. |
| + * @param {ChromeNotificationId} chromeNotificationId chrome.notifications ID of |
| + * the card. |
| * @param {boolean} byUser Whether the notification was closed by the user. |
| */ |
| function onNotificationClosed(chromeNotificationId, byUser) { |
| @@ -934,28 +905,37 @@ function onNotificationClosed(chromeNotificationId, byUser) { |
| instrumented.storage.local.get( |
| ['pendingDismissals', 'notificationsData'], function(items) { |
| items = items || {}; |
| + /** @type {Array.<PendingDismissal>} */ |
| items.pendingDismissals = items.pendingDismissals || []; |
| + /** @type {Object.<string, NotificationDataEntry>} */ |
| items.notificationsData = items.notificationsData || {}; |
| - // Deleting the notification in case it was re-added while this task was |
| - // scheduled, waiting for execution; also cleaning notification's data |
| - // from storage. |
| - cardSet.clear(chromeNotificationId, true); |
| + /** @type {NotificationDataEntry} */ |
| + var notificationData = items.notificationsData[chromeNotificationId] || { |
| + timestamp: Date.now(), |
| + combinedCard: [] |
| + }; |
| - var notificationData = items.notificationsData[chromeNotificationId]; |
| + var dismissalResult = |
| + cardSet.onDismissal(chromeNotificationId, notificationData); |
| + |
| + for (var i = 0; i < dismissalResult.dismissals.length; i++) { |
| + /** @type {PendingDismissal} */ |
| + var dismissal = { |
| + chromeNotificationId: chromeNotificationId, |
| + time: Date.now(), |
| + dismissalData: dismissalResult.dismissals[i] |
| + }; |
| + items.pendingDismissals.push(dismissal); |
| + } |
| - if (notificationData && notificationData.dismissals) { |
| - for (var i = 0; i < notificationData.dismissals.length; i++) { |
| - var dismissal = { |
| - chromeNotificationId: chromeNotificationId, |
| - time: Date.now(), |
| - dismissalData: notificationData.dismissals[i] |
| - }; |
| - items.pendingDismissals.push(dismissal); |
| - } |
| + items.notificationsData[chromeNotificationId] = |
| + dismissalResult.notificationData; |
| - chrome.storage.local.set({pendingDismissals: items.pendingDismissals}); |
| - } |
| + chrome.storage.local.set({ |
| + pendingDismissals: items.pendingDismissals, |
| + notificationsData: items.notificationsData |
| + }); |
| processPendingDismissals(function(success) {}); |
| }); |
| @@ -1140,9 +1120,10 @@ instrumented.runtime.onStartup.addListener(function() { |
| instrumented.storage.local.get('notificationGroups', function(items) { |
| console.log('onStartup-get ' + JSON.stringify(items)); |
| items = items || {}; |
| + /** @type {Object.<string, StoredNotificationGroup>} */ |
| items.notificationGroups = items.notificationGroups || {}; |
| - mergeAndShowNotificationCards(items.notificationGroups); |
| + combineAndShowNotificationCards(items.notificationGroups); |
| }); |
| }); |
| @@ -1178,7 +1159,7 @@ instrumented.notifications.onButtonClicked.addListener( |
| 'GoogleNow.ButtonClicked' + buttonIndex); |
| onNotificationClicked(chromeNotificationId, function(actionUrls) { |
| var url = actionUrls.buttonUrls[buttonIndex]; |
| - verify(url, 'onButtonClicked: no url for a button'); |
| + verify(url !== undefined, 'onButtonClicked: no url for a button'); |
| return url; |
| }); |
| }); |
| @@ -1222,6 +1203,7 @@ instrumented.pushMessaging.onMessage.addListener(function(message) { |
| message.payload) { |
| items.lastPollNowPayloads[message.subchannelId] = message.payload; |
| + /** @type {Object.<string, StoredNotificationGroup>} */ |
| items.notificationGroups = items.notificationGroups || {}; |
| items.notificationGroups['PUSH' + message.subchannelId] = { |
| cards: [], |