background.js revision a02191e04bc25c4935f804f2c080ae28663d096d
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)'use strict'; 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @fileoverview The event page for Google Now for Chrome implementation. 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * The Google Now event page gets Google Now cards from the server and shows 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * them as Chrome notifications. 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * The service performs periodic updating of Google Now cards. 12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Each updating of the cards includes 4 steps: 13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * 1. Processing requests for cards dismissals that are not yet sent to the 14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * server. 15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * 2. Making a server request. 16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * 3. Showing the received cards as notifications. 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 19c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// TODO(robliao): Decide what to do in incognito mode. 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Standard response code for successful HTTP requests. This is the only success 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * code the server will send. 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)var HTTP_OK = 200; 264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)var HTTP_NOCONTENT = 204; 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 28ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvar HTTP_BAD_REQUEST = 400; 29eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvar HTTP_UNAUTHORIZED = 401; 30eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvar HTTP_FORBIDDEN = 403; 31ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvar HTTP_METHOD_NOT_ALLOWED = 405; 32eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)var MS_IN_SECOND = 1000; 344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)var MS_IN_MINUTE = 60 * 1000; 354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Initial period for polling for Google Now Notifications cards to use when the 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * period from the server is not available. 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)var INITIAL_POLLING_PERIOD_SECONDS = 5 * 60; // 5 minutes 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Mininal period for polling for Google Now Notifications cards. 444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */ 454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)var MINIMUM_POLLING_PERIOD_SECONDS = 5 * 60; // 5 minutes 464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)/** 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Maximal period for polling for Google Now Notifications cards to use when the 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * period from the server is not available. 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)var MAXIMUM_POLLING_PERIOD_SECONDS = 60 * 60; // 1 hour 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/** 54effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch * Initial period for polling for Google Now optin notification after push 55effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch * messaging indicates Google Now is enabled. 56effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch */ 57effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvar INITIAL_OPTIN_POLLING_PERIOD_SECONDS = 60; // 1 minute 58effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 59effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch/** 60effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch * Maximum period for polling for Google Now optin notification after push 61effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch * messaging indicates Google Now is enabled. It is expected that the alarm 62effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch * will be stopped after this. 63effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch */ 64effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvar MAXIMUM_OPTIN_POLLING_PERIOD_SECONDS = 16 * 60; // 16 minutes 65effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 66effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch/** 6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * Initial period for retrying the server request for dismissing cards. 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */ 6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)var INITIAL_RETRY_DISMISS_PERIOD_SECONDS = 60; // 1 minute 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)/** 7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * Maximum period for retrying the server request for dismissing cards. 7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) */ 7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)var MAXIMUM_RETRY_DISMISS_PERIOD_SECONDS = 60 * 60; // 1 hour 75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/** 77ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * Time we keep retrying dismissals. 78ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch */ 79ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvar MAXIMUM_DISMISSAL_AGE_MS = 24 * 60 * 60 * 1000; // 1 day 80ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 81ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch/** 82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Time we keep dismissals after successful server dismiss requests. 83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */ 84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)var DISMISS_RETENTION_TIME_MS = 20 * 60 * 1000; // 20 minutes 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 870f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) * Default period for checking whether the user is opted in to Google Now. 880f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) */ 890f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)var DEFAULT_OPTIN_CHECK_PERIOD_SECONDS = 60 * 60 * 24 * 7; // 1 week 900f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 910f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)/** 920f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) * URL to open when the user clicked on a link for the our notification 930f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) * settings. 940f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) */ 950f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)var SETTINGS_URL = 'https://support.google.com/chrome/?p=ib_google_now_welcome'; 960f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 970f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)/** 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * Number of cards that need an explanatory link. 990f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) */ 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)var EXPLANATORY_CARDS_LINK_THRESHOLD = 4; 1010f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 1020f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)/** 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Names for tasks that can be created by the extension. 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)var UPDATE_CARDS_TASK_NAME = 'update-cards'; 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)var DISMISS_CARD_TASK_NAME = 'dismiss-card'; 107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)var RETRY_DISMISS_TASK_NAME = 'retry-dismiss'; 108a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)var STATE_CHANGED_TASK_NAME = 'state-changed'; 1094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)var SHOW_ON_START_TASK_NAME = 'show-cards-on-start'; 1108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)var ON_PUSH_MESSAGE_START_TASK_NAME = 'on-push-message'; 111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)/** 113a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * Group as received from the server. 1144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * 1154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @typedef {{ 116a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * nextPollSeconds: (string|undefined), 117a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * rank: (number|undefined), 118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * requested: (boolean|undefined) 1194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * }} 1204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */ 121a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)var ReceivedGroup; 122a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 123a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)/** 124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * Server response with notifications and groups. 125a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * 126a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * @typedef {{ 127a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * googleNowDisabled: (boolean|undefined), 128a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * groups: Object.<string, ReceivedGroup>, 129a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * notifications: Array.<ReceivedNotification> 130a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * }} 131a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) */ 132a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)var ServerResponse; 133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch/** 1354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Notification group as the client stores it. |cardsTimestamp| and |rank| are 1361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) * defined if |cards| is non-empty. |nextPollTime| is undefined if the server 1371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) * (1) never sent 'nextPollSeconds' for the group or 1381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) * (2) didn't send 'nextPollSeconds' with the last group update containing a 1391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) * cards update and all the times after that. 1404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * 1414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @typedef {{ 142a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * cards: Array.<ReceivedNotification>, 143a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * cardsTimestamp: (number|undefined), 144a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * nextPollTime: (number|undefined), 145a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * rank: (number|undefined) 1464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * }} 147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch */ 148a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)var StoredNotificationGroup; 149a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 150a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)/** 151a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * Pending (not yet successfully sent) dismissal for a received notification. 152a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * |time| is the moment when the user requested dismissal. 153a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * 154a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * @typedef {{ 155a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * chromeNotificationId: ChromeNotificationId, 156a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * time: number, 157a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * dismissalData: DismissalData 158a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * }} 159a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) */ 160a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)var PendingDismissal; 161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 162eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch/** 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Checks if a new task can't be scheduled when another task is already 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * scheduled. 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {string} newTaskName Name of the new task. 166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @param {string} scheduledTaskName Name of the scheduled task. 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @return {boolean} Whether the new task conflicts with the existing task. 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)function areTasksConflicting(newTaskName, scheduledTaskName) { 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (newTaskName == UPDATE_CARDS_TASK_NAME && 171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scheduledTaskName == UPDATE_CARDS_TASK_NAME) { 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If a card update is requested while an old update is still scheduled, we 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // don't need the new update. 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (newTaskName == RETRY_DISMISS_TASK_NAME && 178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) (scheduledTaskName == UPDATE_CARDS_TASK_NAME || 179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scheduledTaskName == DISMISS_CARD_TASK_NAME || 180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scheduledTaskName == RETRY_DISMISS_TASK_NAME)) { 181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // No need to schedule retry-dismiss action if another action that tries to 182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // send dismissals is scheduled. 183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return true; 184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)var tasks = buildTaskManager(areTasksConflicting); 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Add error processing to API calls. 192424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)wrapper.instrumentChromeApiFunction('metricsPrivate.getVariationParams', 1); 1934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)wrapper.instrumentChromeApiFunction('notifications.clear', 1); 194424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)wrapper.instrumentChromeApiFunction('notifications.create', 2); 1951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)wrapper.instrumentChromeApiFunction('notifications.getPermissionLevel', 0); 196424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)wrapper.instrumentChromeApiFunction('notifications.update', 2); 197424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)wrapper.instrumentChromeApiFunction('notifications.getAll', 0); 198424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)wrapper.instrumentChromeApiFunction( 199ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 'notifications.onButtonClicked.addListener', 0); 200424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)wrapper.instrumentChromeApiFunction('notifications.onClicked.addListener', 0); 201424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)wrapper.instrumentChromeApiFunction('notifications.onClosed.addListener', 0); 202424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)wrapper.instrumentChromeApiFunction( 2031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 'notifications.onPermissionLevelChanged.addListener', 0); 2041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)wrapper.instrumentChromeApiFunction( 2050f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 'notifications.onShowSettings.addListener', 0); 206424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)wrapper.instrumentChromeApiFunction('permissions.contains', 1); 2078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)wrapper.instrumentChromeApiFunction('pushMessaging.onMessage.addListener', 0); 208424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)wrapper.instrumentChromeApiFunction('runtime.onInstalled.addListener', 0); 209424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)wrapper.instrumentChromeApiFunction('runtime.onStartup.addListener', 0); 210424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)wrapper.instrumentChromeApiFunction('tabs.create', 1); 211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 21290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)var updateCardsAttempts = buildAttemptManager( 21390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 'cards-update', 214a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) requestCards, 21590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) INITIAL_POLLING_PERIOD_SECONDS, 21690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) MAXIMUM_POLLING_PERIOD_SECONDS); 217effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvar optInCheckAttempts = buildAttemptManager( 218effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 'optin', 219effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch pollOptedIn, 220effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch INITIAL_OPTIN_POLLING_PERIOD_SECONDS, 221effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch MAXIMUM_OPTIN_POLLING_PERIOD_SECONDS); 22290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)var dismissalAttempts = buildAttemptManager( 22390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 'dismiss', 22490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) retryPendingDismissals, 22590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) INITIAL_RETRY_DISMISS_PERIOD_SECONDS, 22690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) MAXIMUM_RETRY_DISMISS_PERIOD_SECONDS); 227558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochvar cardSet = buildCardSet(); 22890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 229a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)var authenticationManager = buildAuthenticationManager(); 230a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/** 232a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) * Google Now UMA event identifier. 233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @enum {number} 234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */ 235a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)var GoogleNowEvent = { 236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) REQUEST_FOR_CARDS_TOTAL: 0, 237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) REQUEST_FOR_CARDS_SUCCESS: 1, 238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CARDS_PARSE_SUCCESS: 2, 239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DISMISS_REQUEST_TOTAL: 3, 240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DISMISS_REQUEST_SUCCESS: 4, 24190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) LOCATION_REQUEST: 5, 242a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DELETED_LOCATION_UPDATE: 6, 243eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXTENSION_START: 7, 2444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DELETED_SHOW_WELCOME_TOAST: 8, 245a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) STOPPED: 9, 2464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DELETED_USER_SUPPRESSED: 10, 247effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch SIGNED_OUT: 11, 248effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch NOTIFICATION_DISABLED: 12, 249effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch GOOGLE_NOW_DISABLED: 13, 250effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EVENTS_TOTAL: 14 // EVENTS_TOTAL is not an event; all new events need to be 251a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // added before it. 252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}; 253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/** 255a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) * Records a Google Now Event. 256a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) * @param {GoogleNowEvent} event Event identifier. 257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */ 258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)function recordEvent(event) { 259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) var metricDescription = { 260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) metricName: 'GoogleNow.Event', 261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) type: 'histogram-linear', 262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) min: 1, 263a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) max: GoogleNowEvent.EVENTS_TOTAL, 264a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) buckets: GoogleNowEvent.EVENTS_TOTAL + 1 265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) }; 266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) chrome.metricsPrivate.recordValue(metricDescription, event); 268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 271effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch * Records a notification clicked event. 272effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch * @param {number|undefined} cardTypeId Card type ID. 273effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch */ 274effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochfunction recordNotificationClick(cardTypeId) { 275effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (cardTypeId !== undefined) { 276effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch chrome.metricsPrivate.recordSparseValue( 277effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 'GoogleNow.Card.Clicked', cardTypeId); 278effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 279effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 280effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 281effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch/** 282effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch * Records a button clicked event. 283effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch * @param {number|undefined} cardTypeId Card type ID. 284effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch * @param {number} buttonIndex Button Index 285effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch */ 286effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochfunction recordButtonClick(cardTypeId, buttonIndex) { 287effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (cardTypeId !== undefined) { 288effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch chrome.metricsPrivate.recordSparseValue( 289effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 'GoogleNow.Card.Button.Clicked' + buttonIndex, cardTypeId); 290effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 291effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 292effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 293effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch/** 294a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * Checks the result of the HTTP Request and updates the authentication 295a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * manager on any failure. 296a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * @param {string} token Authentication token to validate against an 297a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * XMLHttpRequest. 298a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * @return {function(XMLHttpRequest)} Function that validates the token with the 299a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * supplied XMLHttpRequest. 300eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch */ 301a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)function checkAuthenticationStatus(token) { 302a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return function(request) { 303a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (request.status == HTTP_FORBIDDEN || 304a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) request.status == HTTP_UNAUTHORIZED) { 305a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) authenticationManager.removeToken(token); 306eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 307a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 308a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 309eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 310a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)/** 311a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * Builds and sends an authenticated request to the notification server. 312a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * @param {string} method Request method. 313a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * @param {string} handlerName Server handler to send the request to. 314a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * @param {string=} opt_contentType Value for the Content-type header. 315a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * @return {Promise} A promise to issue a request to the server. 316c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch * The promise rejects if the response is not within the HTTP 200 range. 317a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) */ 318a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)function requestFromServer(method, handlerName, opt_contentType) { 319a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return authenticationManager.getAuthToken().then(function(token) { 320a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) var request = buildServerRequest(method, handlerName, opt_contentType); 321eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch request.setRequestHeader('Authorization', 'Bearer ' + token); 322c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch var requestPromise = new Promise(function(resolve, reject) { 323a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) request.addEventListener('loadend', function() { 324c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if ((200 <= request.status) && (request.status < 300)) { 325c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch resolve(request); 326c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } else { 327c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch reject(request); 328c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 329a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) }, false); 330a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) request.send(); 331eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch }); 332c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch requestPromise.catch(checkAuthenticationStatus(token)); 333a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return requestPromise; 334eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch }); 335eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 336eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 337eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch/** 338c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch * Shows the notification groups as notification cards. 3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * @param {Object.<string, StoredNotificationGroup>} notificationGroups Map from 3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * group name to group information. 341c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch * @param {function(ReceivedNotification)=} opt_onCardShown Optional parameter 342a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * called when each card is shown. 343c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch * @return {Promise} A promise to show the notification groups as cards. 3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 345c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochfunction showNotificationGroups(notificationGroups, opt_onCardShown) { 346a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch /** @type {Object.<ChromeNotificationId, CombinedCard>} */ 347c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch var cards = combineCardsFromGroups(notificationGroups); 348c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch console.log('showNotificationGroups ' + JSON.stringify(cards)); 349ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 350c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return new Promise(function(resolve) { 351c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch instrumented.notifications.getAll(function(notifications) { 352c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch console.log('showNotificationGroups-getAll ' + 353c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch JSON.stringify(notifications)); 354c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch notifications = notifications || {}; 355c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 356c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // Mark notifications that didn't receive an update as having received 357c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // an empty update. 358c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch for (var chromeNotificationId in notifications) { 359c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch cards[chromeNotificationId] = cards[chromeNotificationId] || []; 360c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 361ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 362a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch /** @type {Object.<ChromeNotificationId, NotificationDataEntry>} */ 363c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch var notificationsData = {}; 364c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 365c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // Create/update/delete notifications. 366c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch for (var chromeNotificationId in cards) { 367c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch notificationsData[chromeNotificationId] = cardSet.update( 368c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch chromeNotificationId, 369c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch cards[chromeNotificationId], 370c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch notificationGroups, 371c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch opt_onCardShown); 372c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 373c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch chrome.storage.local.set({notificationsData: notificationsData}); 374c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch resolve(); 375c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch }); 376a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) }); 3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 380a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) * Removes all cards and card state on Google Now close down. 381a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) */ 382a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)function removeAllCards() { 383a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) console.log('removeAllCards'); 384a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 385a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // TODO(robliao): Once Google Now clears its own checkbox in the 386a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // notifications center and bug 260376 is fixed, the below clearing 387a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // code is no longer necessary. 388ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch instrumented.notifications.getAll(function(notifications) { 3893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) notifications = notifications || {}; 3904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) for (var chromeNotificationId in notifications) { 3914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) instrumented.notifications.clear(chromeNotificationId, function() {}); 392a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 3934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) chrome.storage.local.remove(['notificationsData', 'notificationGroups']); 3944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) }); 3954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 3964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)/** 398a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * Adds a card group into a set of combined cards. 399a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * @param {Object.<ChromeNotificationId, CombinedCard>} combinedCards Map from 400a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * chromeNotificationId to a combined card. 401a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * This is an input/output parameter. 402a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * @param {StoredNotificationGroup} storedGroup Group to combine into the 403a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * combined card set. 4044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */ 405a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)function combineGroup(combinedCards, storedGroup) { 406a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) for (var i = 0; i < storedGroup.cards.length; i++) { 407a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) /** @type {ReceivedNotification} */ 408a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) var receivedNotification = storedGroup.cards[i]; 409a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 410a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) /** @type {UncombinedNotification} */ 411a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) var uncombinedNotification = { 412a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) receivedNotification: receivedNotification, 413a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) showTime: receivedNotification.trigger.showTimeSec && 414a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) (storedGroup.cardsTimestamp + 415a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) receivedNotification.trigger.showTimeSec * MS_IN_SECOND), 416a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) hideTime: storedGroup.cardsTimestamp + 417a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) receivedNotification.trigger.hideTimeSec * MS_IN_SECOND 4184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) }; 4194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 420a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) var combinedCard = 421a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) combinedCards[receivedNotification.chromeNotificationId] || []; 422a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) combinedCard.push(uncombinedNotification); 423a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) combinedCards[receivedNotification.chromeNotificationId] = combinedCard; 4244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 4254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 4264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 4274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)/** 4284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Schedules next cards poll. 429a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * @param {Object.<string, StoredNotificationGroup>} groups Map from group name 430a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * to group information. 4310f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) * @param {boolean} isOptedIn True if the user is opted in to Google Now. 4324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */ 4330f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)function scheduleNextPoll(groups, isOptedIn) { 4340f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (isOptedIn) { 4350f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) var nextPollTime = null; 4360f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 4370f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) for (var groupName in groups) { 4380f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) var group = groups[groupName]; 4390f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (group.nextPollTime !== undefined) { 4400f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) nextPollTime = nextPollTime == null ? 4410f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) group.nextPollTime : Math.min(group.nextPollTime, nextPollTime); 4420f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 4431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 4444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 4450f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // At least one of the groups must have nextPollTime. 4460f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) verify(nextPollTime != null, 'scheduleNextPoll: nextPollTime is null'); 4474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 4480f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) var nextPollDelaySeconds = Math.max( 4490f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) (nextPollTime - Date.now()) / MS_IN_SECOND, 4500f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) MINIMUM_POLLING_PERIOD_SECONDS); 4510f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) updateCardsAttempts.start(nextPollDelaySeconds); 4520f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } else { 4530f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) instrumented.metricsPrivate.getVariationParams( 4540f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 'GoogleNow', function(params) { 4550f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) var optinPollPeriodSeconds = 4560f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) parseInt(params && params.optinPollPeriodSeconds, 10) || 4570f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) DEFAULT_OPTIN_CHECK_PERIOD_SECONDS; 4580f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) updateCardsAttempts.start(optinPollPeriodSeconds); 4590f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) }); 4600f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 4614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 4624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 4634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)/** 464c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch * Combines notification groups into a set of Chrome notifications. 465a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * @param {Object.<string, StoredNotificationGroup>} notificationGroups Map from 466a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * group name to group information. 467c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch * @return {Object.<ChromeNotificationId, CombinedCard>} Cards to show. 4684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */ 469c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochfunction combineCardsFromGroups(notificationGroups) { 470c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch console.log('combineCardsFromGroups ' + JSON.stringify(notificationGroups)); 471a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) /** @type {Object.<ChromeNotificationId, CombinedCard>} */ 472a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) var combinedCards = {}; 4734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 4744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) for (var groupName in notificationGroups) 475a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) combineGroup(combinedCards, notificationGroups[groupName]); 4764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 477c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return combinedCards; 4784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 4794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 4804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)/** 481c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch * Processes a server response for consumption by showNotificationGroups. 4825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * @param {ServerResponse} response Server response. 483c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch * @return {Promise} A promise to process the server response and provide 484c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch * updated groups. Rejects if the server response shouldn't be processed. 4854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) */ 486c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochfunction processServerResponse(response) { 4875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) console.log('processServerResponse ' + JSON.stringify(response)); 4884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 4895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (response.googleNowDisabled) { 4900f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) chrome.storage.local.set({googleNowEnabled: false}); 491c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // TODO(robliao): Remove the line below once the server stops sending groups 4920f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // with 'googleNowDisabled' responses. 4935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) response.groups = {}; 4940f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // Google Now was enabled; now it's disabled. This is a state change. 4950f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) onStateChange(); 496a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // Start the Google Now Disabled polling period. 497a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch scheduleNextPoll({}, false); 498a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // Stop processing now. The state change will clear the cards. 499a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch return Promise.reject(); 5000f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 5010f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 5025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) var receivedGroups = response.groups; 5034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 504c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return fillFromChromeLocalStorage({ 505a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) /** @type {Object.<string, StoredNotificationGroup>} */ 506a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) notificationGroups: {}, 507a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch /** @type {Object.<ServerNotificationId, number>} */ 508a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) recentDismissals: {} 509a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) }).then(function(items) { 510a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) console.log('processServerResponse-get ' + JSON.stringify(items)); 511a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 512a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Build a set of non-expired recent dismissals. It will be used for 513a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // client-side filtering of cards. 514a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch /** @type {Object.<ServerNotificationId, number>} */ 515a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) var updatedRecentDismissals = {}; 516a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) var now = Date.now(); 517a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch for (var serverNotificationId in items.recentDismissals) { 518a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch var dismissalAge = now - items.recentDismissals[serverNotificationId]; 519a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (dismissalAge < DISMISS_RETENTION_TIME_MS) { 520a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch updatedRecentDismissals[serverNotificationId] = 521a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch items.recentDismissals[serverNotificationId]; 522a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 523a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 5244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 525a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Populate groups with corresponding cards. 526a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (response.notifications) { 527a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (var i = 0; i < response.notifications.length; ++i) { 528a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) /** @type {ReceivedNotification} */ 529a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) var card = response.notifications[i]; 530a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!(card.notificationId in updatedRecentDismissals)) { 531a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) var group = receivedGroups[card.groupName]; 532a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) group.cards = group.cards || []; 533a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) group.cards.push(card); 534a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 535a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 536a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 5374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 538a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Build updated set of groups. 539a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) var updatedGroups = {}; 540a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 541a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (var groupName in receivedGroups) { 542a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) var receivedGroup = receivedGroups[groupName]; 543a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) var storedGroup = items.notificationGroups[groupName] || { 544a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) cards: [], 545a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) cardsTimestamp: undefined, 546a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) nextPollTime: undefined, 547a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) rank: undefined 548a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) }; 549a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 550a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (receivedGroup.requested) 551a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) receivedGroup.cards = receivedGroup.cards || []; 552a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 553a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (receivedGroup.cards) { 554a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // If the group contains a cards update, all its fields will get new 555a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // values. 556a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) storedGroup.cards = receivedGroup.cards; 557a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) storedGroup.cardsTimestamp = now; 558a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) storedGroup.rank = receivedGroup.rank; 559a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) storedGroup.nextPollTime = undefined; 560a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // The code below assigns nextPollTime a defined value if 561a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // nextPollSeconds is specified in the received group. 562a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // If the group's cards are not updated, and nextPollSeconds is 563a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // unspecified, this method doesn't change group's nextPollTime. 564a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 5654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 566a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // 'nextPollSeconds' may be sent even for groups that don't contain 567a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // cards updates. 568a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (receivedGroup.nextPollSeconds !== undefined) { 569a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) storedGroup.nextPollTime = 570a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) now + receivedGroup.nextPollSeconds * MS_IN_SECOND; 571a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 5724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 573a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) updatedGroups[groupName] = storedGroup; 574a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 5754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 576a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scheduleNextPoll(updatedGroups, !response.googleNowDisabled); 577c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return { 578c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch updatedGroups: updatedGroups, 579c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch recentDismissals: updatedRecentDismissals 580c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch }; 581a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) }); 582a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 583a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 584a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)/** 5855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * Update the Explanatory Total Cards Shown Count. 5860f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) */ 5875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)function countExplanatoryCard() { 5885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) localStorage['explanatoryCardsShown']++; 5890f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 5900f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 5910f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)/** 592c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch * Determines if cards should have an explanation link. 593c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch * @return {boolean} true if an explanatory card should be shown. 594c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch */ 595c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochfunction shouldShowExplanatoryCard() { 596c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch var isBelowThreshold = 597c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch localStorage['explanatoryCardsShown'] < EXPLANATORY_CARDS_LINK_THRESHOLD; 598c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return isBelowThreshold; 599c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 600c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 601c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch/** 6028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) * Requests notification cards from the server for specified groups. 6038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) * @param {Array.<string>} groupNames Names of groups that need to be refreshed. 604c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch * @return {Promise} A promise to request the specified notification groups. 6058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) */ 606c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochfunction requestNotificationGroupsFromServer(groupNames) { 607c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch console.log( 608c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 'requestNotificationGroupsFromServer from ' + NOTIFICATION_CARDS_URL + 6098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) ', groupNames=' + JSON.stringify(groupNames)); 6108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 6118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) recordEvent(GoogleNowEvent.REQUEST_FOR_CARDS_TOTAL); 6128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 6138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) var requestParameters = '?timeZoneOffsetMs=' + 6140f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) (-new Date().getTimezoneOffset() * MS_IN_MINUTE); 6150f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 616c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (shouldShowExplanatoryCard()) { 6175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) requestParameters += '&cardExplanation=true'; 6180f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 6198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 6208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) groupNames.forEach(function(groupName) { 6218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) requestParameters += ('&requestTypes=' + groupName); 6228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) }); 6238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 624a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) requestParameters += '&uiLocale=' + navigator.language; 6258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 626c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch console.log( 627c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 'requestNotificationGroupsFromServer: request=' + requestParameters); 6280f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 629c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return requestFromServer('GET', 'notifications' + requestParameters).then( 630a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) function(request) { 631c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch console.log( 632c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 'requestNotificationGroupsFromServer-received ' + request.status); 633a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (request.status == HTTP_OK) { 634a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) recordEvent(GoogleNowEvent.REQUEST_FOR_CARDS_SUCCESS); 635c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return JSON.parse(request.responseText); 636a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 637a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) }); 6380f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 6390f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 6400f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)/** 641c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch * Requests the account opted-in state from the server and updates any 642c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch * state as necessary. 643c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch * @return {Promise} A promise to request and update the opted-in state. 644c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch * The promise resolves if the opt-in state is true. 6450f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) */ 646c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochfunction requestAndUpdateOptedIn() { 6470f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) console.log('requestOptedIn from ' + NOTIFICATION_CARDS_URL); 6480f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 649c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return requestFromServer('GET', 'settings/optin').then(function(request) { 6500f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) console.log( 651a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 'requestOptedIn-received ' + request.status + ' ' + request.response); 6520f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (request.status == HTTP_OK) { 653a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) var parsedResponse = JSON.parse(request.responseText); 654c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return parsedResponse.value; 655c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 656c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch }).then(function(optedIn) { 657c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (optedIn) { 658c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch chrome.storage.local.set({googleNowEnabled: true}); 659c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // Google Now was disabled, now it's enabled. This is a state change. 660c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch onStateChange(); 661c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return Promise.resolve(); 662c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } else { 663c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch scheduleNextPoll({}, false); 664c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return Promise.reject(); 6658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 6668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) }); 6678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 6688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 6698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)/** 670c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch * Determines the groups that need to be requested right now. 671c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch * @return {Promise} A promise to determine the groups to request. 6722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 673c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochfunction getGroupsToRequest() { 674c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return fillFromChromeLocalStorage({ 675a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) /** @type {Object.<string, StoredNotificationGroup>} */ 676c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch notificationGroups: {} 677a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) }).then(function(items) { 678c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch console.log('getGroupsToRequest-storage-get ' + JSON.stringify(items)); 6798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) var groupsToRequest = []; 680a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) var now = Date.now(); 6812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 682a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) for (var groupName in items.notificationGroups) { 683a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) var group = items.notificationGroups[groupName]; 684a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (group.nextPollTime !== undefined && group.nextPollTime <= now) 685a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) groupsToRequest.push(groupName); 686eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 687c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return groupsToRequest; 688c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch }); 689c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 6904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 691c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch/** 692c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch * Requests notification cards from the server. 693c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch * @return {Promise} A promise to request the notification cards. 694c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch * Rejects if the cards won't be requested. 695c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch */ 696c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochfunction requestNotificationCards() { 697c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch console.log('requestNotificationCards'); 698c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 699c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return isGoogleNowEnabled() 700c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch .then(function(googleNowEnabled) { 701c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return googleNowEnabled ? Promise.resolve() : requestAndUpdateOptedIn(); 702c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch }) 703c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch .then(getGroupsToRequest) 704c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch .then(requestNotificationGroupsFromServer) 705c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch .then(processServerResponse) 706c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch .then(function(processedResponse) { 707c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch var onCardShown = 708c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch shouldShowExplanatoryCard() ? countExplanatoryCard : undefined; 709c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return showNotificationGroups( 710c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch processedResponse.updatedGroups, onCardShown).then(function() { 711c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch chrome.storage.local.set({ 712c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch notificationGroups: processedResponse.updatedGroups, 713c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch recentDismissals: processedResponse.updatedRecentDismissals 714c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch }); 715c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch recordEvent(GoogleNowEvent.CARDS_PARSE_SUCCESS); 716c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 717c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ); 7180f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) }); 7192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 7202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 722a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * Requests and shows notification cards. 7232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 724a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)function requestCards() { 725a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) console.log('requestCards @' + new Date()); 726a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // LOCATION_REQUEST is a legacy histogram value when we requested location. 727a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // This corresponds to the extension attempting to request for cards. 728a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // We're keeping the name the same to keep our histograms in order. 729a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) recordEvent(GoogleNowEvent.LOCATION_REQUEST); 7304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) tasks.add(UPDATE_CARDS_TASK_NAME, function() { 731a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) console.log('requestCards-task-begin'); 732a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) updateCardsAttempts.isRunning(function(running) { 733a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (running) { 734a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) updateCardsAttempts.planForNext(function() { 735a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // The cards are requested only if there are no unsent dismissals. 736a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) processPendingDismissals().then(requestNotificationCards); 737a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) }); 738a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 7392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }); 7402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }); 7412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 7422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 744c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Sends a server request to dismiss a card. 745a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * @param {ChromeNotificationId} chromeNotificationId chrome.notifications ID of 746a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * the card. 747c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @param {number} dismissalTimeMs Time of the user's dismissal of the card in 748c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * milliseconds since epoch. 7494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @param {DismissalData} dismissalData Data to build a dismissal request. 750a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * @return {Promise} A promise to request the card dismissal, rejects on error. 751c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */ 752c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)function requestCardDismissal( 753a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) chromeNotificationId, dismissalTimeMs, dismissalData) { 754a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) console.log('requestDismissingCard ' + chromeNotificationId + 755a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ' from ' + NOTIFICATION_CARDS_URL + 756a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ', dismissalData=' + JSON.stringify(dismissalData)); 757ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 758ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch var dismissalAge = Date.now() - dismissalTimeMs; 759ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 760ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (dismissalAge > MAXIMUM_DISMISSAL_AGE_MS) { 76123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return Promise.resolve(); 762ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 763ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 764a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) recordEvent(GoogleNowEvent.DISMISS_REQUEST_TOTAL); 7654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 766a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) var requestParameters = 'notifications/' + dismissalData.notificationId + 7674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) '?age=' + dismissalAge + 7684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) '&chromeNotificationId=' + chromeNotificationId; 7694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 7704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) for (var paramField in dismissalData.parameters) 771a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) requestParameters += ('&' + paramField + 772a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) '=' + dismissalData.parameters[paramField]); 7734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 774a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) console.log('requestCardDismissal: requestParameters=' + requestParameters); 7754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 776a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return requestFromServer('DELETE', requestParameters).then(function(request) { 777c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) console.log('requestDismissingCard-onloadend ' + request.status); 7784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (request.status == HTTP_NOCONTENT) 779a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) recordEvent(GoogleNowEvent.DISMISS_REQUEST_SUCCESS); 780c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 781ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // A dismissal doesn't require further retries if it was successful or 782ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // doesn't have a chance for successful completion. 783c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return (request.status == HTTP_NOCONTENT) ? 784c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch Promise.resolve() : 785c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch Promise.reject(); 786c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch }).catch(function(request) { 787c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return (request.status == HTTP_BAD_REQUEST || 788c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch request.status == HTTP_METHOD_NOT_ALLOWED) ? 789c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch Promise.resolve() : 790c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch Promise.reject(); 791eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch }); 792c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 793c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 794c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/** 795c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Tries to send dismiss requests for all pending dismissals. 796a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * @return {Promise} A promise to process the pending dismissals. 797a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * The promise is rejected if a problem was encountered. 798c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */ 799a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)function processPendingDismissals() { 800a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return fillFromChromeLocalStorage({ 801a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) /** @type {Array.<PendingDismissal>} */ 802a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) pendingDismissals: [], 803a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch /** @type {Object.<ServerNotificationId, number>} */ 804a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) recentDismissals: {} 805a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) }).then(function(items) { 806a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) console.log( 807a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 'processPendingDismissals-storage-get ' + JSON.stringify(items)); 808c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 809a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) var dismissalsChanged = false; 810c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 811a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) function onFinish(success) { 812a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (dismissalsChanged) { 813a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) chrome.storage.local.set({ 814a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) pendingDismissals: items.pendingDismissals, 815a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) recentDismissals: items.recentDismissals 816a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) }); 817a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 818a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return success ? Promise.resolve() : Promise.reject(); 819a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 820a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 821a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) function doProcessDismissals() { 822a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (items.pendingDismissals.length == 0) { 823a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) dismissalAttempts.stop(); 824a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return onFinish(true); 825a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 826a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 827a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Send dismissal for the first card, and if successful, repeat 828a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // recursively with the rest. 829a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) /** @type {PendingDismissal} */ 830a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) var dismissal = items.pendingDismissals[0]; 831a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return requestCardDismissal( 832a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) dismissal.chromeNotificationId, 833a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) dismissal.time, 834a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) dismissal.dismissalData).then(function() { 835a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) dismissalsChanged = true; 836a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) items.pendingDismissals.splice(0, 1); 837a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) items.recentDismissals[dismissal.dismissalData.notificationId] = 838a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Date.now(); 839a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return doProcessDismissals(); 840a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) }).catch(function() { 841a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return onFinish(false); 842a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) }); 843a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 844a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 845a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return doProcessDismissals(); 846a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) }); 847c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 848c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 849c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/** 850c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Submits a task to send pending dismissals. 851c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */ 852c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)function retryPendingDismissals() { 8534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) tasks.add(RETRY_DISMISS_TASK_NAME, function() { 85490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) dismissalAttempts.planForNext(function() { 855a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) processPendingDismissals(); 85690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) }); 857c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) }); 858c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 859c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 860c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/** 8610f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) * Opens a URL in a new tab. 8620f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) * @param {string} url URL to open. 8630f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) */ 8640f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)function openUrl(url) { 8650f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) instrumented.tabs.create({url: url}, function(tab) { 8660f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (tab) 8670f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) chrome.windows.update(tab.windowId, {focused: true}); 8680f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) else 8690f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) chrome.windows.create({url: url, focused: true}); 8700f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) }); 8710f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 8720f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 8730f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)/** 8742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Opens URL corresponding to the clicked part of the notification. 875a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * @param {ChromeNotificationId} chromeNotificationId chrome.notifications ID of 876a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * the card. 877effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch * @param {function(NotificationDataEntry): (string|undefined)} selector 878effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch * Function that extracts the url for the clicked area from the 879effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch * notification data entry. 8802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 8814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)function onNotificationClicked(chromeNotificationId, selector) { 882a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) fillFromChromeLocalStorage({ 883a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch /** @type {Object.<ChromeNotificationId, NotificationDataEntry>} */ 884a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) notificationsData: {} 885a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) }).then(function(items) { 886a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) /** @type {(NotificationDataEntry|undefined)} */ 887effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch var notificationDataEntry = items.notificationsData[chromeNotificationId]; 888effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!notificationDataEntry) 889868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return; 8902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 891effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch var url = selector(notificationDataEntry); 8923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!url) 893868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return; 894868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 8950f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) openUrl(url); 8962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }); 8972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 8982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 9002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Callback for chrome.notifications.onClosed event. 901a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * @param {ChromeNotificationId} chromeNotificationId chrome.notifications ID of 902a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * the card. 9032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {boolean} byUser Whether the notification was closed by the user. 9042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 9054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)function onNotificationClosed(chromeNotificationId, byUser) { 9062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!byUser) 9072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 9082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 909eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // At this point we are guaranteed that the notification is a now card. 910c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) chrome.metricsPrivate.recordUserAction('GoogleNow.Dismissed'); 911c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 9124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) tasks.add(DISMISS_CARD_TASK_NAME, function() { 91390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) dismissalAttempts.start(); 914c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 915a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) fillFromChromeLocalStorage({ 916a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) /** @type {Array.<PendingDismissal>} */ 917a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) pendingDismissals: [], 918a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch /** @type {Object.<ChromeNotificationId, NotificationDataEntry>} */ 919a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) notificationsData: {}, 920a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) /** @type {Object.<string, StoredNotificationGroup>} */ 921a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) notificationGroups: {} 922a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) }).then(function(items) { 923a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) /** @type {NotificationDataEntry} */ 924a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) var notificationData = 925a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) items.notificationsData[chromeNotificationId] || 926a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) { 927a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) timestamp: Date.now(), 928a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) combinedCard: [] 929a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) }; 930a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 931a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) var dismissalResult = 932a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) cardSet.onDismissal( 933a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) chromeNotificationId, 934a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) notificationData, 935a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) items.notificationGroups); 936a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 937a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (var i = 0; i < dismissalResult.dismissals.length; i++) { 938a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) /** @type {PendingDismissal} */ 939a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) var dismissal = { 940a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) chromeNotificationId: chromeNotificationId, 941a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) time: Date.now(), 942a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) dismissalData: dismissalResult.dismissals[i] 943a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) }; 944a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) items.pendingDismissals.push(dismissal); 945a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 946a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 947a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) items.notificationsData[chromeNotificationId] = 948a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) dismissalResult.notificationData; 949a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 950a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) chrome.storage.local.set(items); 951a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 952a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) processPendingDismissals(); 953a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) }); 9542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }); 9552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 9562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 958a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * Initializes the polling system to start fetching cards. 9592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 960eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochfunction startPollingCards() { 961a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) console.log('startPollingCards'); 962a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Create an update timer for a case when for some reason requesting 963a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // cards gets stuck. 96490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) updateCardsAttempts.start(MAXIMUM_POLLING_PERIOD_SECONDS); 965a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) requestCards(); 9662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 9672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 968eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch/** 969a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) * Stops all machinery in the polling system. 970a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) */ 971a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)function stopPollingCards() { 972a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) console.log('stopPollingCards'); 973a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) updateCardsAttempts.stop(); 974a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // Since we're stopping everything, clear all runtime storage. 975c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // We don't clear localStorage since those values are still relevant 976c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // across Google Now start-stop events. 977c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch chrome.storage.local.clear(); 978a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 979a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 980a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)/** 981eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * Initializes the event page on install or on browser startup. 982eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch */ 983eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochfunction initialize() { 984a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) recordEvent(GoogleNowEvent.EXTENSION_START); 985a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) onStateChange(); 986a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 987a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 988a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)/** 989a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch * Starts or stops the main pipeline for polling cards. 990a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) * @param {boolean} shouldPollCardsRequest true to start and 991a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) * false to stop polling cards. 992a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) */ 9934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)function setShouldPollCards(shouldPollCardsRequest) { 994a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) updateCardsAttempts.isRunning(function(currentValue) { 995a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (shouldPollCardsRequest != currentValue) { 996a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) console.log('Action Taken setShouldPollCards=' + shouldPollCardsRequest); 997a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (shouldPollCardsRequest) 998a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) startPollingCards(); 999a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) else 1000a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) stopPollingCards(); 1001ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } else { 1002ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch console.log( 1003ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 'Action Ignored setShouldPollCards=' + shouldPollCardsRequest); 1004a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 1005a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) }); 1006a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 1007a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 1008a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)/** 10093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * Enables or disables the Google Now background permission. 10103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @param {boolean} backgroundEnable true to run in the background. 10113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * false to not run in the background. 10123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) */ 10134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)function setBackgroundEnable(backgroundEnable) { 10143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) instrumented.permissions.contains({permissions: ['background']}, 10153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) function(hasPermission) { 10163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (backgroundEnable != hasPermission) { 10173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) console.log('Action Taken setBackgroundEnable=' + backgroundEnable); 10183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (backgroundEnable) 10194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) chrome.permissions.request({permissions: ['background']}); 10203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) else 10214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) chrome.permissions.remove({permissions: ['background']}); 10223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } else { 10233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) console.log('Action Ignored setBackgroundEnable=' + backgroundEnable); 10243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 10253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) }); 10263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 10273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 10283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)/** 1029effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch * Record why this extension would not poll for cards. 1030effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch * @param {boolean} signedIn true if the user is signed in. 1031effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch * @param {boolean} notificationEnabled true if 1032effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch * Google Now for Chrome is allowed to show notifications. 1033effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch * @param {boolean} googleNowEnabled true if 1034effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch * the Google Now is enabled for the user. 1035effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch */ 1036effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochfunction recordEventIfNoCards(signedIn, notificationEnabled, googleNowEnabled) { 1037effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!signedIn) { 1038effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch recordEvent(GoogleNowEvent.SIGNED_OUT); 1039effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } else if (!notificationEnabled) { 1040effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch recordEvent(GoogleNowEvent.NOTIFICATION_DISABLED); 1041effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } else if (!googleNowEnabled) { 1042effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch recordEvent(GoogleNowEvent.GOOGLE_NOW_DISABLED); 1043effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 1044effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 1045effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 1046effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch/** 1047a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) * Does the actual work of deciding what Google Now should do 1048a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) * based off of the current state of Chrome. 1049a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) * @param {boolean} signedIn true if the user is signed in. 10500f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) * @param {boolean} canEnableBackground true if 10510f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) * the background permission can be requested. 10521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) * @param {boolean} notificationEnabled true if 10531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) * Google Now for Chrome is allowed to show notifications. 10540f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) * @param {boolean} googleNowEnabled true if 10550f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) * the Google Now is enabled for the user. 1056a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) */ 1057a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)function updateRunningState( 1058a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) signedIn, 10590f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) canEnableBackground, 10600f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) notificationEnabled, 10610f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) googleNowEnabled) { 1062a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) console.log( 1063a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 'State Update signedIn=' + signedIn + ' ' + 10640f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 'canEnableBackground=' + canEnableBackground + ' ' + 10650f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 'notificationEnabled=' + notificationEnabled + ' ' + 10660f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 'googleNowEnabled=' + googleNowEnabled); 10674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1068a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) var shouldPollCards = false; 10693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) var shouldSetBackground = false; 1070a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch var shouldClearCards = true; 1071a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 10721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (signedIn && notificationEnabled) { 1073a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch shouldClearCards = !googleNowEnabled; 1074a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch shouldSetBackground = canEnableBackground && googleNowEnabled; 1075a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) shouldPollCards = true; 1076a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } else { 1077a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) recordEvent(GoogleNowEvent.STOPPED); 1078a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 1079a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 1080effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch recordEventIfNoCards(signedIn, notificationEnabled, googleNowEnabled); 1081effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 1082a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) console.log( 10833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 'Requested Actions shouldSetBackground=' + shouldSetBackground + ' ' + 1084a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 'setShouldPollCards=' + shouldPollCards + ' ' + 1085a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 'shouldClearCards=' + shouldClearCards); 1086a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 10874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) setBackgroundEnable(shouldSetBackground); 10884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) setShouldPollCards(shouldPollCards); 1089a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (shouldClearCards) { 1090a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch removeAllCards(); 1091a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } 1092a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 1093a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 1094a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)/** 1095a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) * Coordinates the behavior of Google Now for Chrome depending on 1096a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) * Chrome and extension state. 1097a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) */ 1098a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)function onStateChange() { 10994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) tasks.add(STATE_CHANGED_TASK_NAME, function() { 11005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Promise.all([ 1101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) authenticationManager.isSignedIn(), 11025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) canEnableBackground(), 11035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) isNotificationsEnabled(), 11045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) isGoogleNowEnabled()]) 11055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .then(function(results) { 11065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) updateRunningState.apply(null, results); 11075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) }); 11085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) }); 11095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 11105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 11115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)/** 11125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * Determines if background mode should be requested. 11135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * @return {Promise} A promise to determine if background can be enabled. 11145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) */ 11155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)function canEnableBackground() { 11165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return new Promise(function(resolve) { 11175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) instrumented.metricsPrivate.getVariationParams( 11185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'GoogleNow', 11195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) function(response) { 11205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) resolve(!response || (response.canEnableBackground != 'false')); 11215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) }); 11225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) }); 11235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 11245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 11255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)/** 11265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * Checks if Google Now is enabled in the notifications center. 11275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * @return {Promise} A promise to determine if Google Now is enabled 11285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * in the notifications center. 11295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) */ 11305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)function isNotificationsEnabled() { 11315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return new Promise(function(resolve) { 11325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) instrumented.notifications.getPermissionLevel(function(level) { 11335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) resolve(level == 'granted'); 11345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) }); 11355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) }); 11365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 11375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 11385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)/** 11395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * Gets the previous Google Now opt-in state. 11405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * @return {Promise} A promise to determine the previous Google Now 11415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * opt-in state. 11425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) */ 11435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)function isGoogleNowEnabled() { 1144a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return fillFromChromeLocalStorage({googleNowEnabled: false}) 1145a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) .then(function(items) { 1146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return items.googleNowEnabled; 1147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) }); 1148eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 1149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1150effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch/** 1151effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch * Polls the optin state. 1152effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch * Sometimes we get the response to the opted in result too soon during 1153effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch * push messaging. We'll recheck the optin state a few times before giving up. 1154effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch */ 1155effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochfunction pollOptedIn() { 1156effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch /** 1157effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch * Cleans up any state used to recheck the opt-in poll. 1158effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch */ 1159effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch function clearPollingState() { 1160effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch localStorage.removeItem('optedInCheckCount'); 1161effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch optInCheckAttempts.stop(); 1162effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 1163effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 1164c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (localStorage.optedInCheckCount === undefined) { 1165c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch localStorage.optedInCheckCount = 0; 1166c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch optInCheckAttempts.start(); 1167c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 1168c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 1169c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch console.log(new Date() + 1170c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ' checkOptedIn Attempt ' + localStorage.optedInCheckCount); 1171c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 1172c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch requestAndUpdateOptedIn().then(function() { 1173c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch clearPollingState(); 1174c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch requestCards(); 1175c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch }).catch(function() { 1176effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (localStorage.optedInCheckCount < 5) { 1177effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch localStorage.optedInCheckCount++; 1178c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch optInCheckAttempts.planForNext(function() {}); 1179effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } else { 1180effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch clearPollingState(); 1181effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 1182c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch }); 1183effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 1184effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 1185ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochinstrumented.runtime.onInstalled.addListener(function(details) { 1186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) console.log('onInstalled ' + JSON.stringify(details)); 1187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (details.reason != 'chrome_update') { 11882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) initialize(); 1189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 11902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}); 11912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1192ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochinstrumented.runtime.onStartup.addListener(function() { 1193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) console.log('onStartup'); 11944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 11954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Show notifications received by earlier polls. Doing this as early as 11964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // possible to reduce latency of showing first notifications. This mimics how 11974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // persistent notifications will work. 11984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) tasks.add(SHOW_ON_START_TASK_NAME, function() { 1199a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) fillFromChromeLocalStorage({ 1200a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) /** @type {Object.<string, StoredNotificationGroup>} */ 1201a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) notificationGroups: {} 1202a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) }).then(function(items) { 1203a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) console.log('onStartup-get ' + JSON.stringify(items)); 12044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1205c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch showNotificationGroups(items.notificationGroups).then(function() { 12065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) chrome.storage.local.set(items); 12075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) }); 12084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) }); 12094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) }); 12104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 12112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) initialize(); 12122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}); 12132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1214a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)authenticationManager.addListener(function() { 1215a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) console.log('signIn State Change'); 1216a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) onStateChange(); 1217a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}); 1218a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 1219ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochinstrumented.notifications.onClicked.addListener( 12204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) function(chromeNotificationId) { 1221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) chrome.metricsPrivate.recordUserAction('GoogleNow.MessageClicked'); 1222effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch onNotificationClicked(chromeNotificationId, 1223effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch function(notificationDataEntry) { 1224effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch var actionUrls = notificationDataEntry.actionUrls; 1225effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch var url = actionUrls && actionUrls.messageUrl; 1226effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (url) { 1227effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch recordNotificationClick(notificationDataEntry.cardTypeId); 1228effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 1229effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return url; 1230effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch }); 1231effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch }); 12322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1233ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochinstrumented.notifications.onButtonClicked.addListener( 12344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) function(chromeNotificationId, buttonIndex) { 12354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) chrome.metricsPrivate.recordUserAction( 12364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 'GoogleNow.ButtonClicked' + buttonIndex); 1237effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch onNotificationClicked(chromeNotificationId, 1238effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch function(notificationDataEntry) { 1239effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch var actionUrls = notificationDataEntry.actionUrls; 1240effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch var url = actionUrls.buttonUrls[buttonIndex]; 1241effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (url) { 1242effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch recordButtonClick(notificationDataEntry.cardTypeId, buttonIndex); 1243effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } else { 1244effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch verify(false, 'onButtonClicked: no url for a button'); 1245effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 1246effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return url; 1247effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch }); 1248effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch }); 12492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1250ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochinstrumented.notifications.onClosed.addListener(onNotificationClosed); 1251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 12521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)instrumented.notifications.onPermissionLevelChanged.addListener( 12531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) function(permissionLevel) { 12541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) console.log('Notifications permissionLevel Change'); 12551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) onStateChange(); 12561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) }); 12571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 12580f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)instrumented.notifications.onShowSettings.addListener(function() { 12590f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) openUrl(SETTINGS_URL); 12600f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}); 12610f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 12628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)instrumented.pushMessaging.onMessage.addListener(function(message) { 12638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // message.payload will be '' when the extension first starts. 12648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Each time after signing in, we'll get latest payload for all channels. 12658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // So, we need to poll the server only when the payload is non-empty and has 12668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // changed. 12678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) console.log('pushMessaging.onMessage ' + JSON.stringify(message)); 12681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (message.payload.indexOf('REQUEST_CARDS') == 0) { 12698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) tasks.add(ON_PUSH_MESSAGE_START_TASK_NAME, function() { 1270a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Accept promise rejection on failure since it's safer to do nothing, 1271a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // preventing polling the server when the payload really didn't change. 1272a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) fillFromChromeLocalStorage({ 1273a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) lastPollNowPayloads: {}, 1274a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) /** @type {Object.<string, StoredNotificationGroup>} */ 1275a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) notificationGroups: {} 1276a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) }, PromiseRejection.ALLOW).then(function(items) { 12771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (items.lastPollNowPayloads[message.subchannelId] != 12781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) message.payload) { 12791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) items.lastPollNowPayloads[message.subchannelId] = message.payload; 12808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 12810f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) items.notificationGroups['PUSH' + message.subchannelId] = { 12820f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) cards: [], 12830f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) nextPollTime: Date.now() 12840f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) }; 12850f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 12860f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) chrome.storage.local.set({ 12870f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) lastPollNowPayloads: items.lastPollNowPayloads, 12880f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) notificationGroups: items.notificationGroups 12898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) }); 12900f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 1291effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch pollOptedIn(); 12928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 12938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) }); 12948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) }); 12958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 129690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}); 1297