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