Chromium Code Reviews| 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 |