OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 /** |
| 6 * @fileoverview The event page for Google Now for Chrome implementation. |
| 7 * The Google Now event page gets Google Now cards from the server and shows |
| 8 * them as Chrome notifications. |
| 9 * The service performs periodic updating of Google Now cards. |
| 10 * Each updating of the cards includes 3 steps: |
| 11 * 1. Obtaining the location of the machine; |
| 12 * 2. Making a server request based on that location; |
| 13 * 3. Showing the received cards as notifications. |
| 14 */ |
| 15 |
| 16 // TODO(vadimt): Use background permission to show notifications even when all |
| 17 // browser windows are closed. |
| 18 // TODO(vadimt): Remove the C++ implementation. |
| 19 // TODO(vadimt): Decide what to do in incognito mode. |
| 20 // TODO(vadimt): Gather UMAs. |
| 21 // TODO(vadimt): Honor the flag the enables Google Now integration. |
| 22 // TODO(vadimt): Figure out the final values of the constants. |
| 23 // TODO(vadimt): Report errors to the user. |
| 24 |
| 25 // TODO(vadimt): Figure out the server name. Use it in the manifest and for |
| 26 // NOTIFICATION_CARDS_URL. Meanwhile, to use the feature, you need to manually |
| 27 // edit NOTIFICATION_CARDS_URL before building Chrome. |
| 28 /** |
| 29 * URL to retrieve notification cards. |
| 30 */ |
| 31 var NOTIFICATION_CARDS_URL = ''; |
| 32 |
| 33 /** |
| 34 * Standard response code for successful HTTP requests. This is the only success |
| 35 * code the server will send. |
| 36 */ |
| 37 var HTTP_OK = 200; |
| 38 |
| 39 /** |
| 40 * Period for polling for Google Now Notifications cards to use when the period |
| 41 * from the server is not available. |
| 42 */ |
| 43 var DEFAULT_POLLING_PERIOD_SECONDS = 300; // 5 minutes |
| 44 |
| 45 /** |
| 46 * Parse JSON response of the notifications server, show notifications and |
| 47 * schedule next update. |
| 48 * @param {string} response Server response. |
| 49 */ |
| 50 function ParseAndShowNotificationCards(response) { |
| 51 var parsedResponse = JSON.parse(response); |
| 52 var cards = parsedResponse.cards; |
| 53 |
| 54 for (var i = 0; i != cards.length; ++i) |
| 55 chrome.experimental.notification.show(cards[i], function(showInfo) {}); |
| 56 |
| 57 ScheduleNextUpdate(parsedResponse.expiration_timestamp_seconds); |
| 58 } |
| 59 |
| 60 /** |
| 61 * Request notification cards from the server. |
| 62 * @param {string} requestParameters Query string for the request. |
| 63 */ |
| 64 function RequestNotificationCards(requestParameters) { |
| 65 // TODO(vadimt): Figure out how to send user's identity to the server. |
| 66 var request = new XMLHttpRequest(); |
| 67 request.onreadystatechange = function(event) { |
| 68 if (request.readyState == request.DONE && request.status == HTTP_OK) |
| 69 ParseAndShowNotificationCards(request.response); |
| 70 } |
| 71 request.open('GET', NOTIFICATION_CARDS_URL + requestParameters, true); |
| 72 request.send(); |
| 73 } |
| 74 |
| 75 /** |
| 76 * Request notification cards from the server when we have geolocation. |
| 77 * @param {Geoposition} position Location of this computer. |
| 78 */ |
| 79 function RequestNotificationCardsWithLocation(position) { |
| 80 // TODO(vadimt): Should we use 'q' as the parameter name? |
| 81 var requestParameters = |
| 82 '?q=' + position.coords.latitude + |
| 83 ',' + position.coords.longitude + |
| 84 ',' + position.coords.accuracy; |
| 85 |
| 86 RequestNotificationCards(requestParameters); |
| 87 } |
| 88 |
| 89 /** |
| 90 * Request notification cards from the server when we don't have geolocation. |
| 91 * @param {PositionError} positionError Position error. |
| 92 */ |
| 93 function RequestNotificationCardsWithoutLocation(positionError) { |
| 94 RequestNotificationCards(''); |
| 95 } |
| 96 |
| 97 /** |
| 98 * Obtain new location; request and show notification cards based on this |
| 99 * location. |
| 100 */ |
| 101 function UpdateNotificationsCards() { |
| 102 // Immediately schedule the update after the default period. If we |
| 103 // successfully retrieve, parse and show the notifications cards, we'll |
| 104 // schedule next update based on the expiration timestamp received from the |
| 105 // server. At that point scheduled time will be overwritten by the new one |
| 106 // based on the expiration timestamp. |
| 107 // TODO(vadimt): Implement exponential backoff with randomized jitter. |
| 108 ScheduleNextUpdate(DEFAULT_POLLING_PERIOD_SECONDS); |
| 109 |
| 110 // TODO(vadimt): Use chrome.* geolocation API once it's ready. |
| 111 navigator.geolocation.getCurrentPosition( |
| 112 RequestNotificationCardsWithLocation, |
| 113 RequestNotificationCardsWithoutLocation); |
| 114 } |
| 115 |
| 116 /** |
| 117 * Schedule next update for notification cards. |
| 118 * @param {int} delaySeconds Length of time in seconds after which the alarm |
| 119 * event should fire. |
| 120 */ |
| 121 function ScheduleNextUpdate(delaySeconds) { |
| 122 chrome.alarms.create({ when: Date.now() + delaySeconds * 1000 }); |
| 123 } |
| 124 |
| 125 /** |
| 126 * Initialize the event page on install or on browser startup. |
| 127 */ |
| 128 function Initialize() { |
| 129 UpdateNotificationsCards(); |
| 130 } |
| 131 |
| 132 chrome.runtime.onInstalled.addListener(function(details) { |
| 133 if (details.reason != 'chrome_update') |
| 134 Initialize(); |
| 135 }); |
| 136 |
| 137 chrome.runtime.onStartup.addListener(function() { |
| 138 Initialize(); |
| 139 }); |
| 140 |
| 141 chrome.alarms.onAlarm.addListener(function(alarm) { |
| 142 UpdateNotificationsCards(); |
| 143 }); |
OLD | NEW |