OLD | NEW |
---|---|
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 'use strict'; | 5 'use strict'; |
6 | 6 |
7 /** | 7 /** |
8 * @fileoverview The event page for Google Now for Chrome implementation. | 8 * @fileoverview The event page for Google Now for Chrome implementation. |
9 * The Google Now event page gets Google Now cards from the server and shows | 9 * The Google Now event page gets Google Now cards from the server and shows |
10 * them as Chrome notifications. | 10 * them as Chrome notifications. |
(...skipping 14 matching lines...) Expand all Loading... | |
25 // TODO(vadimt): Remove 'console' calls. | 25 // TODO(vadimt): Remove 'console' calls. |
26 // TODO(vadimt): Consider sending JS stacks for chrome.* API errors and | 26 // TODO(vadimt): Consider sending JS stacks for chrome.* API errors and |
27 // malformed server responses. | 27 // malformed server responses. |
28 | 28 |
29 /** | 29 /** |
30 * Standard response code for successful HTTP requests. This is the only success | 30 * Standard response code for successful HTTP requests. This is the only success |
31 * code the server will send. | 31 * code the server will send. |
32 */ | 32 */ |
33 var HTTP_OK = 200; | 33 var HTTP_OK = 200; |
34 | 34 |
35 var HTTP_FORBIDDEN = 403; | |
36 | |
35 /** | 37 /** |
36 * Initial period for polling for Google Now Notifications cards to use when the | 38 * Initial period for polling for Google Now Notifications cards to use when the |
37 * period from the server is not available. | 39 * period from the server is not available. |
38 */ | 40 */ |
39 var INITIAL_POLLING_PERIOD_SECONDS = 5 * 60; // 5 minutes | 41 var INITIAL_POLLING_PERIOD_SECONDS = 5 * 60; // 5 minutes |
40 | 42 |
41 /** | 43 /** |
42 * Maximal period for polling for Google Now Notifications cards to use when the | 44 * Maximal period for polling for Google Now Notifications cards to use when the |
43 * period from the server is not available. | 45 * period from the server is not available. |
44 */ | 46 */ |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
91 // send dismissals is scheduled. | 93 // send dismissals is scheduled. |
92 return true; | 94 return true; |
93 } | 95 } |
94 | 96 |
95 return false; | 97 return false; |
96 } | 98 } |
97 | 99 |
98 var tasks = buildTaskManager(areTasksConflicting); | 100 var tasks = buildTaskManager(areTasksConflicting); |
99 | 101 |
100 // Add error processing to API calls. | 102 // Add error processing to API calls. |
103 tasks.instrumentApiFunction(chrome.identity, 'getAuthToken', 1); | |
104 tasks.instrumentApiFunction(chrome.identity, 'removeCachedAuthToken', 1); | |
101 tasks.instrumentApiFunction(chrome.location.onLocationUpdate, 'addListener', 0); | 105 tasks.instrumentApiFunction(chrome.location.onLocationUpdate, 'addListener', 0); |
102 tasks.instrumentApiFunction(chrome.notifications, 'create', 2); | 106 tasks.instrumentApiFunction(chrome.notifications, 'create', 2); |
103 tasks.instrumentApiFunction(chrome.notifications, 'update', 2); | 107 tasks.instrumentApiFunction(chrome.notifications, 'update', 2); |
104 tasks.instrumentApiFunction(chrome.notifications, 'getAll', 0); | 108 tasks.instrumentApiFunction(chrome.notifications, 'getAll', 0); |
105 tasks.instrumentApiFunction( | 109 tasks.instrumentApiFunction( |
106 chrome.notifications.onButtonClicked, 'addListener', 0); | 110 chrome.notifications.onButtonClicked, 'addListener', 0); |
107 tasks.instrumentApiFunction(chrome.notifications.onClicked, 'addListener', 0); | 111 tasks.instrumentApiFunction(chrome.notifications.onClicked, 'addListener', 0); |
108 tasks.instrumentApiFunction(chrome.notifications.onClosed, 'addListener', 0); | 112 tasks.instrumentApiFunction(chrome.notifications.onClosed, 'addListener', 0); |
109 tasks.instrumentApiFunction(chrome.runtime.onInstalled, 'addListener', 0); | 113 tasks.instrumentApiFunction(chrome.runtime.onInstalled, 'addListener', 0); |
110 tasks.instrumentApiFunction(chrome.runtime.onStartup, 'addListener', 0); | 114 tasks.instrumentApiFunction(chrome.runtime.onStartup, 'addListener', 0); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
148 type: 'histogram-linear', | 152 type: 'histogram-linear', |
149 min: 1, | 153 min: 1, |
150 max: DiagnosticEvent.EVENTS_TOTAL, | 154 max: DiagnosticEvent.EVENTS_TOTAL, |
151 buckets: DiagnosticEvent.EVENTS_TOTAL + 1 | 155 buckets: DiagnosticEvent.EVENTS_TOTAL + 1 |
152 }; | 156 }; |
153 | 157 |
154 chrome.metricsPrivate.recordValue(metricDescription, event); | 158 chrome.metricsPrivate.recordValue(metricDescription, event); |
155 } | 159 } |
156 | 160 |
157 /** | 161 /** |
162 * Adds authorization behavior to the request. | |
163 * @param {XMLHttpRequest} request Server request. | |
164 * @param {function(boolean)} callbackBoolean Completion callback with 'success' | |
165 * parameter. | |
166 */ | |
167 function setAuthorization(request, callbackBoolean) { | |
168 tasks.debugSetStepName('setAuthorization-getAuthToken'); | |
169 chrome.identity.getAuthToken({interactive: false}, function(token) { | |
170 var errorMessage = | |
171 chrome.runtime.lastError && chrome.runtime.lastError.message; | |
172 console.log('setAuthorization: error=' + errorMessage + ', token=' + token); | |
rgustafson
2013/06/19 00:56:51
Does adding the token onto this log really help? I
vadimt
2013/06/19 01:38:07
Done.
| |
173 if (chrome.runtime.lastError || !token) { | |
174 callbackBoolean(false); | |
175 return; | |
176 } | |
177 | |
178 request.setRequestHeader('Authorization', 'Bearer ' + token); | |
179 | |
180 // Instrument onloadend to remove stale auth tokens. | |
181 var originalOnLoadEnd = request.onloadend; | |
182 request.onloadend = tasks.wrapCallback(function(event) { | |
183 if (request.status == HTTP_FORBIDDEN) { | |
rgustafson
2013/06/19 00:56:51
Could we also handle 401 unauthorized here? It wou
vadimt
2013/06/19 01:38:07
Done.
skare_
2013/06/19 05:21:23
half-curiosity -- have you seen "forbidden" in pra
rgustafson
2013/06/19 18:39:10
The server should only be involved in the revoked
| |
184 tasks.debugSetStepName('setAuthorization-removeCachedAuthToken'); | |
185 chrome.identity.removeCachedAuthToken({token: token}, function() { | |
186 // After purging the token cache, call getAuthToken() again to let | |
187 // Chrome know about the problem with the token. | |
188 chrome.identity.getAuthToken({interactive: false}, function() {}); | |
189 originalOnLoadEnd(event); | |
190 }); | |
191 } else { | |
192 originalOnLoadEnd(event); | |
193 } | |
194 }); | |
195 | |
196 callbackBoolean(true); | |
197 }); | |
198 } | |
199 | |
200 /** | |
158 * Shows a notification and remembers information associated with it. | 201 * Shows a notification and remembers information associated with it. |
159 * @param {Object} card Google Now card represented as a set of parameters for | 202 * @param {Object} card Google Now card represented as a set of parameters for |
160 * showing a Chrome notification. | 203 * showing a Chrome notification. |
161 * @param {Object} notificationsData Map from notification id to the data | 204 * @param {Object} notificationsData Map from notification id to the data |
162 * associated with a notification. | 205 * associated with a notification. |
163 * @param {number=} opt_previousVersion The version of the shown card with this | 206 * @param {number=} opt_previousVersion The version of the shown card with this |
164 * id, if it exists, undefined otherwise. | 207 * id, if it exists, undefined otherwise. |
165 */ | 208 */ |
166 function showNotification(card, notificationsData, opt_previousVersion) { | 209 function showNotification(card, notificationsData, opt_previousVersion) { |
167 console.log('showNotification ' + JSON.stringify(card) + ' ' + | 210 console.log('showNotification ' + JSON.stringify(card) + ' ' + |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
336 } | 379 } |
337 | 380 |
338 recordEvent(DiagnosticEvent.REQUEST_FOR_CARDS_TOTAL); | 381 recordEvent(DiagnosticEvent.REQUEST_FOR_CARDS_TOTAL); |
339 | 382 |
340 // TODO(vadimt): Should we use 'q' as the parameter name? | 383 // TODO(vadimt): Should we use 'q' as the parameter name? |
341 var requestParameters = | 384 var requestParameters = |
342 'q=' + position.coords.latitude + | 385 'q=' + position.coords.latitude + |
343 ',' + position.coords.longitude + | 386 ',' + position.coords.longitude + |
344 ',' + position.coords.accuracy; | 387 ',' + position.coords.accuracy; |
345 | 388 |
346 // TODO(vadimt): Figure out how to send user's identity to the server. | |
347 var request = buildServerRequest('notifications'); | 389 var request = buildServerRequest('notifications'); |
348 | 390 |
349 request.onloadend = tasks.wrapCallback(function(event) { | 391 request.onloadend = function(event) { |
350 console.log('requestNotificationCards-onloadend ' + request.status); | 392 console.log('requestNotificationCards-onloadend ' + request.status); |
351 if (request.status == HTTP_OK) { | 393 if (request.status == HTTP_OK) { |
352 recordEvent(DiagnosticEvent.REQUEST_FOR_CARDS_SUCCESS); | 394 recordEvent(DiagnosticEvent.REQUEST_FOR_CARDS_SUCCESS); |
353 parseAndShowNotificationCards(request.response, callback); | 395 parseAndShowNotificationCards(request.response, callback); |
354 } else { | 396 } else { |
355 callback(); | 397 callback(); |
356 } | 398 } |
399 }; | |
400 | |
401 setAuthorization(request, function(success) { | |
402 if (success) { | |
403 tasks.debugSetStepName('requestNotificationCards-send-request'); | |
404 request.send(requestParameters); | |
405 } else { | |
406 callback(); | |
407 } | |
357 }); | 408 }); |
358 | |
359 tasks.debugSetStepName('requestNotificationCards-send-request'); | |
360 request.send(requestParameters); | |
361 } | 409 } |
362 | 410 |
363 /** | 411 /** |
364 * Starts getting location for a cards update. | 412 * Starts getting location for a cards update. |
365 */ | 413 */ |
366 function requestLocation() { | 414 function requestLocation() { |
367 console.log('requestLocation'); | 415 console.log('requestLocation'); |
368 recordEvent(DiagnosticEvent.LOCATION_REQUEST); | 416 recordEvent(DiagnosticEvent.LOCATION_REQUEST); |
369 // TODO(vadimt): Figure out location request options. | 417 // TODO(vadimt): Figure out location request options. |
370 chrome.location.watchLocation(LOCATION_WATCH_NAME, {}); | 418 chrome.location.watchLocation(LOCATION_WATCH_NAME, {}); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
404 */ | 452 */ |
405 function requestCardDismissal( | 453 function requestCardDismissal( |
406 notificationId, dismissalTimeMs, callbackBoolean) { | 454 notificationId, dismissalTimeMs, callbackBoolean) { |
407 console.log('requestDismissingCard ' + notificationId + ' from ' + | 455 console.log('requestDismissingCard ' + notificationId + ' from ' + |
408 NOTIFICATION_CARDS_URL); | 456 NOTIFICATION_CARDS_URL); |
409 recordEvent(DiagnosticEvent.DISMISS_REQUEST_TOTAL); | 457 recordEvent(DiagnosticEvent.DISMISS_REQUEST_TOTAL); |
410 // Send a dismiss request to the server. | 458 // Send a dismiss request to the server. |
411 var requestParameters = 'id=' + notificationId + | 459 var requestParameters = 'id=' + notificationId + |
412 '&dismissalAge=' + (Date.now() - dismissalTimeMs); | 460 '&dismissalAge=' + (Date.now() - dismissalTimeMs); |
413 var request = buildServerRequest('dismiss'); | 461 var request = buildServerRequest('dismiss'); |
414 request.onloadend = tasks.wrapCallback(function(event) { | 462 request.onloadend = function(event) { |
415 console.log('requestDismissingCard-onloadend ' + request.status); | 463 console.log('requestDismissingCard-onloadend ' + request.status); |
416 if (request.status == HTTP_OK) | 464 if (request.status == HTTP_OK) |
417 recordEvent(DiagnosticEvent.DISMISS_REQUEST_SUCCESS); | 465 recordEvent(DiagnosticEvent.DISMISS_REQUEST_SUCCESS); |
418 | 466 |
419 callbackBoolean(request.status == HTTP_OK); | 467 callbackBoolean(request.status == HTTP_OK); |
468 }; | |
469 | |
470 setAuthorization(request, function(success) { | |
471 if (success) { | |
472 tasks.debugSetStepName('requestCardDismissal-send-request'); | |
473 request.send(requestParameters); | |
474 } else { | |
475 callbackBoolean(false); | |
476 } | |
420 }); | 477 }); |
421 | |
422 tasks.debugSetStepName('requestCardDismissal-send-request'); | |
423 request.send(requestParameters); | |
424 } | 478 } |
425 | 479 |
426 /** | 480 /** |
427 * Tries to send dismiss requests for all pending dismissals. | 481 * Tries to send dismiss requests for all pending dismissals. |
428 * @param {function(boolean)} callbackBoolean Completion callback with 'success' | 482 * @param {function(boolean)} callbackBoolean Completion callback with 'success' |
429 * parameter. Success means that no pending dismissals are left. | 483 * parameter. Success means that no pending dismissals are left. |
430 */ | 484 */ |
431 function processPendingDismissals(callbackBoolean) { | 485 function processPendingDismissals(callbackBoolean) { |
432 tasks.debugSetStepName('processPendingDismissals-storage-get'); | 486 tasks.debugSetStepName('processPendingDismissals-storage-get'); |
433 storage.get(['pendingDismissals', 'recentDismissals'], function(items) { | 487 storage.get(['pendingDismissals', 'recentDismissals'], function(items) { |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
603 | 657 |
604 chrome.location.onLocationUpdate.addListener(function(position) { | 658 chrome.location.onLocationUpdate.addListener(function(position) { |
605 recordEvent(DiagnosticEvent.LOCATION_UPDATE); | 659 recordEvent(DiagnosticEvent.LOCATION_UPDATE); |
606 updateNotificationsCards(position); | 660 updateNotificationsCards(position); |
607 }); | 661 }); |
608 | 662 |
609 chrome.omnibox.onInputEntered.addListener(function(text) { | 663 chrome.omnibox.onInputEntered.addListener(function(text) { |
610 localStorage['server_url'] = NOTIFICATION_CARDS_URL = text; | 664 localStorage['server_url'] = NOTIFICATION_CARDS_URL = text; |
611 initialize(); | 665 initialize(); |
612 }); | 666 }); |
OLD | NEW |