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 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
145 INITIAL_POLLING_PERIOD_SECONDS, | 145 INITIAL_POLLING_PERIOD_SECONDS, |
146 MAXIMUM_POLLING_PERIOD_SECONDS); | 146 MAXIMUM_POLLING_PERIOD_SECONDS); |
147 var dismissalAttempts = buildAttemptManager( | 147 var dismissalAttempts = buildAttemptManager( |
148 'dismiss', | 148 'dismiss', |
149 retryPendingDismissals, | 149 retryPendingDismissals, |
150 INITIAL_RETRY_DISMISS_PERIOD_SECONDS, | 150 INITIAL_RETRY_DISMISS_PERIOD_SECONDS, |
151 MAXIMUM_RETRY_DISMISS_PERIOD_SECONDS); | 151 MAXIMUM_RETRY_DISMISS_PERIOD_SECONDS); |
152 var cardSet = buildCardSet(); | 152 var cardSet = buildCardSet(); |
153 | 153 |
154 /** | 154 /** |
155 * Diagnostic event identifier. | 155 * Google Now UMA event identifier. |
156 * @enum {number} | 156 * @enum {number} |
157 */ | 157 */ |
158 var DiagnosticEvent = { | 158 var GoogleNowEvent = { |
159 REQUEST_FOR_CARDS_TOTAL: 0, | 159 REQUEST_FOR_CARDS_TOTAL: 0, |
160 REQUEST_FOR_CARDS_SUCCESS: 1, | 160 REQUEST_FOR_CARDS_SUCCESS: 1, |
161 CARDS_PARSE_SUCCESS: 2, | 161 CARDS_PARSE_SUCCESS: 2, |
162 DISMISS_REQUEST_TOTAL: 3, | 162 DISMISS_REQUEST_TOTAL: 3, |
163 DISMISS_REQUEST_SUCCESS: 4, | 163 DISMISS_REQUEST_SUCCESS: 4, |
164 LOCATION_REQUEST: 5, | 164 LOCATION_REQUEST: 5, |
165 LOCATION_UPDATE: 6, | 165 LOCATION_UPDATE: 6, |
166 EXTENSION_START: 7, | 166 EXTENSION_START: 7, |
167 SHOW_WELCOME_TOAST: 8, | 167 SHOW_WELCOME_TOAST: 8, |
168 EVENTS_TOTAL: 9 // EVENTS_TOTAL is not an event; all new events need to be | 168 EVENTS_TOTAL: 9 // EVENTS_TOTAL is not an event; all new events need to be |
169 // added before it. | 169 // added before it. |
170 }; | 170 }; |
171 | 171 |
172 /** | 172 /** |
173 * Records a diagnostic event. | 173 * Records a Google Now Event. |
174 * @param {DiagnosticEvent} event Event identifier. | 174 * @param {GoogleNowEvent} event Event identifier. |
175 */ | 175 */ |
176 function recordEvent(event) { | 176 function recordEvent(event) { |
177 var metricDescription = { | 177 var metricDescription = { |
178 metricName: 'GoogleNow.Event', | 178 metricName: 'GoogleNow.Event', |
179 type: 'histogram-linear', | 179 type: 'histogram-linear', |
180 min: 1, | 180 min: 1, |
181 max: DiagnosticEvent.EVENTS_TOTAL, | 181 max: GoogleNowEvent.EVENTS_TOTAL, |
182 buckets: DiagnosticEvent.EVENTS_TOTAL + 1 | 182 buckets: GoogleNowEvent.EVENTS_TOTAL + 1 |
183 }; | 183 }; |
184 | 184 |
185 chrome.metricsPrivate.recordValue(metricDescription, event); | 185 chrome.metricsPrivate.recordValue(metricDescription, event); |
186 } | 186 } |
187 | 187 |
188 /** | 188 /** |
189 * Adds authorization behavior to the request. | 189 * Adds authorization behavior to the request. |
190 * @param {XMLHttpRequest} request Server request. | 190 * @param {XMLHttpRequest} request Server request. |
191 * @param {function(boolean)} callbackBoolean Completion callback with 'success' | 191 * @param {function(boolean)} callbackBoolean Completion callback with 'success' |
192 * parameter. | 192 * parameter. |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
296 // Delete notifications that didn't receive an update. | 296 // Delete notifications that didn't receive an update. |
297 for (var notificationId in notifications) { | 297 for (var notificationId in notifications) { |
298 console.log('parseAndShowNotificationCards-delete-check ' + | 298 console.log('parseAndShowNotificationCards-delete-check ' + |
299 notificationId); | 299 notificationId); |
300 if (!(notificationId in updatedNotifications)) { | 300 if (!(notificationId in updatedNotifications)) { |
301 console.log('parseAndShowNotificationCards-delete ' + notificationId); | 301 console.log('parseAndShowNotificationCards-delete ' + notificationId); |
302 cardSet.clear(notificationId); | 302 cardSet.clear(notificationId); |
303 } | 303 } |
304 } | 304 } |
305 | 305 |
306 recordEvent(DiagnosticEvent.CARDS_PARSE_SUCCESS); | 306 recordEvent(GoogleNowEvent.CARDS_PARSE_SUCCESS); |
307 | 307 |
308 // Create/update notifications and store their new properties. | 308 // Create/update notifications and store their new properties. |
309 var newNotificationsData = {}; | 309 var newNotificationsData = {}; |
310 for (var i = 0; i < cards.length; ++i) { | 310 for (var i = 0; i < cards.length; ++i) { |
311 var card = cards[i]; | 311 var card = cards[i]; |
312 if (!(card.notificationId in updatedRecentDismissals)) { | 312 if (!(card.notificationId in updatedRecentDismissals)) { |
313 var notificationData = items.notificationsData[card.notificationId]; | 313 var notificationData = items.notificationsData[card.notificationId]; |
314 var previousVersion = notifications[card.notificationId] && | 314 var previousVersion = notifications[card.notificationId] && |
315 notificationData && | 315 notificationData && |
316 notificationData.cardCreateInfo && | 316 notificationData.cardCreateInfo && |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
357 */ | 357 */ |
358 function requestNotificationCards(position, callback) { | 358 function requestNotificationCards(position, callback) { |
359 console.log('requestNotificationCards ' + JSON.stringify(position) + | 359 console.log('requestNotificationCards ' + JSON.stringify(position) + |
360 ' from ' + NOTIFICATION_CARDS_URL); | 360 ' from ' + NOTIFICATION_CARDS_URL); |
361 | 361 |
362 if (!NOTIFICATION_CARDS_URL) { | 362 if (!NOTIFICATION_CARDS_URL) { |
363 callback(); | 363 callback(); |
364 return; | 364 return; |
365 } | 365 } |
366 | 366 |
367 recordEvent(DiagnosticEvent.REQUEST_FOR_CARDS_TOTAL); | 367 recordEvent(GoogleNowEvent.REQUEST_FOR_CARDS_TOTAL); |
368 | 368 |
369 // TODO(vadimt): Should we use 'q' as the parameter name? | 369 // TODO(vadimt): Should we use 'q' as the parameter name? |
370 var requestParameters = | 370 var requestParameters = |
371 'q=' + position.coords.latitude + | 371 'q=' + position.coords.latitude + |
372 ',' + position.coords.longitude + | 372 ',' + position.coords.longitude + |
373 ',' + position.coords.accuracy; | 373 ',' + position.coords.accuracy; |
374 | 374 |
375 var request = buildServerRequest('notifications', | 375 var request = buildServerRequest('notifications', |
376 'application/x-www-form-urlencoded'); | 376 'application/x-www-form-urlencoded'); |
377 | 377 |
378 request.onloadend = function(event) { | 378 request.onloadend = function(event) { |
379 console.log('requestNotificationCards-onloadend ' + request.status); | 379 console.log('requestNotificationCards-onloadend ' + request.status); |
380 if (request.status == HTTP_OK) { | 380 if (request.status == HTTP_OK) { |
381 recordEvent(DiagnosticEvent.REQUEST_FOR_CARDS_SUCCESS); | 381 recordEvent(GoogleNowEvent.REQUEST_FOR_CARDS_SUCCESS); |
382 parseAndShowNotificationCards(request.response, callback); | 382 parseAndShowNotificationCards(request.response, callback); |
383 } else { | 383 } else { |
384 callback(); | 384 callback(); |
385 } | 385 } |
386 }; | 386 }; |
387 | 387 |
388 setAuthorization(request, function(success) { | 388 setAuthorization(request, function(success) { |
389 if (success) { | 389 if (success) { |
390 tasks.debugSetStepName('requestNotificationCards-send-request'); | 390 tasks.debugSetStepName('requestNotificationCards-send-request'); |
391 request.send(requestParameters); | 391 request.send(requestParameters); |
392 } else { | 392 } else { |
393 callback(); | 393 callback(); |
394 } | 394 } |
395 }); | 395 }); |
396 } | 396 } |
397 | 397 |
398 /** | 398 /** |
399 * Starts getting location for a cards update. | 399 * Starts getting location for a cards update. |
400 */ | 400 */ |
401 function requestLocation() { | 401 function requestLocation() { |
402 console.log('requestLocation'); | 402 console.log('requestLocation'); |
403 recordEvent(DiagnosticEvent.LOCATION_REQUEST); | 403 recordEvent(GoogleNowEvent.LOCATION_REQUEST); |
404 // TODO(vadimt): Figure out location request options. | 404 // TODO(vadimt): Figure out location request options. |
405 chrome.location.watchLocation(LOCATION_WATCH_NAME, {}); | 405 chrome.location.watchLocation(LOCATION_WATCH_NAME, {}); |
406 } | 406 } |
407 | 407 |
408 /** | 408 /** |
409 * Stops getting the location. | 409 * Stops getting the location. |
410 */ | 410 */ |
411 function stopRequestLocation() { | 411 function stopRequestLocation() { |
412 console.log('stopRequestLocation'); | 412 console.log('stopRequestLocation'); |
413 chrome.location.clearWatch(LOCATION_WATCH_NAME); | 413 chrome.location.clearWatch(LOCATION_WATCH_NAME); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
454 console.log('requestDismissingCard ' + notificationId + ' from ' + | 454 console.log('requestDismissingCard ' + notificationId + ' from ' + |
455 NOTIFICATION_CARDS_URL); | 455 NOTIFICATION_CARDS_URL); |
456 | 456 |
457 var dismissalAge = Date.now() - dismissalTimeMs; | 457 var dismissalAge = Date.now() - dismissalTimeMs; |
458 | 458 |
459 if (dismissalAge > MAXIMUM_DISMISSAL_AGE_MS) { | 459 if (dismissalAge > MAXIMUM_DISMISSAL_AGE_MS) { |
460 callbackBoolean(true); | 460 callbackBoolean(true); |
461 return; | 461 return; |
462 } | 462 } |
463 | 463 |
464 recordEvent(DiagnosticEvent.DISMISS_REQUEST_TOTAL); | 464 recordEvent(GoogleNowEvent.DISMISS_REQUEST_TOTAL); |
465 var request = buildServerRequest('dismiss', 'application/json'); | 465 var request = buildServerRequest('dismiss', 'application/json'); |
466 request.onloadend = function(event) { | 466 request.onloadend = function(event) { |
467 console.log('requestDismissingCard-onloadend ' + request.status); | 467 console.log('requestDismissingCard-onloadend ' + request.status); |
468 if (request.status == HTTP_OK) | 468 if (request.status == HTTP_OK) |
469 recordEvent(DiagnosticEvent.DISMISS_REQUEST_SUCCESS); | 469 recordEvent(GoogleNowEvent.DISMISS_REQUEST_SUCCESS); |
470 | 470 |
471 // A dismissal doesn't require further retries if it was successful or | 471 // A dismissal doesn't require further retries if it was successful or |
472 // doesn't have a chance for successful completion. | 472 // doesn't have a chance for successful completion. |
473 var done = request.status == HTTP_OK || | 473 var done = request.status == HTTP_OK || |
474 request.status == HTTP_BAD_REQUEST || | 474 request.status == HTTP_BAD_REQUEST || |
475 request.status == HTTP_METHOD_NOT_ALLOWED; | 475 request.status == HTTP_METHOD_NOT_ALLOWED; |
476 callbackBoolean(done); | 476 callbackBoolean(done); |
477 }; | 477 }; |
478 | 478 |
479 setAuthorization(request, function(success) { | 479 setAuthorization(request, function(success) { |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
677 | 677 |
678 updateCardsAttempts.stop(); | 678 updateCardsAttempts.stop(); |
679 | 679 |
680 removeAllCards(); | 680 removeAllCards(); |
681 } | 681 } |
682 | 682 |
683 /** | 683 /** |
684 * Initializes the event page on install or on browser startup. | 684 * Initializes the event page on install or on browser startup. |
685 */ | 685 */ |
686 function initialize() { | 686 function initialize() { |
687 recordEvent(DiagnosticEvent.EXTENSION_START); | 687 recordEvent(GoogleNowEvent.EXTENSION_START); |
688 | 688 |
689 // Alarms persist across chrome restarts. This is undesirable since it | 689 // Alarms persist across chrome restarts. This is undesirable since it |
690 // prevents us from starting up everything (alarms are a heuristic to | 690 // prevents us from starting up everything (alarms are a heuristic to |
691 // determine if we are already running). To mitigate this, we will | 691 // determine if we are already running). To mitigate this, we will |
692 // shut everything down on initialize before starting everything up. | 692 // shut everything down on initialize before starting everything up. |
693 stopPollingCards(); | 693 stopPollingCards(); |
694 onStateChange(); | 694 onStateChange(); |
695 } | 695 } |
696 | 696 |
697 /** | 697 /** |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
808 }); | 808 }); |
809 }); | 809 }); |
810 }); | 810 }); |
811 } | 811 } |
812 | 812 |
813 /** | 813 /** |
814 * Displays a toast to the user asking if they want to opt in to receiving | 814 * Displays a toast to the user asking if they want to opt in to receiving |
815 * Google Now cards. | 815 * Google Now cards. |
816 */ | 816 */ |
817 function showWelcomeToast() { | 817 function showWelcomeToast() { |
818 recordEvent(DiagnosticEvent.SHOW_WELCOME_TOAST); | 818 recordEvent(GoogleNowEvent.SHOW_WELCOME_TOAST); |
819 // TODO(zturner): Localize this once the component extension localization | 819 // TODO(zturner): Localize this once the component extension localization |
820 // api is complete. | 820 // api is complete. |
821 // TODO(zturner): Add icons. | 821 // TODO(zturner): Add icons. |
822 var buttons = [{title: 'Yes'}, {title: 'No'}]; | 822 var buttons = [{title: 'Yes'}, {title: 'No'}]; |
823 var options = { | 823 var options = { |
824 type: 'basic', | 824 type: 'basic', |
825 title: 'Enable Google Now Cards', | 825 title: 'Enable Google Now Cards', |
826 message: 'Would you like to be shown Google Now cards?', | 826 message: 'Would you like to be shown Google Now cards?', |
827 iconUrl: 'http://www.gstatic.com/googlenow/chrome/default.png', | 827 iconUrl: 'http://www.gstatic.com/googlenow/chrome/default.png', |
828 priority: 2, | 828 priority: 2, |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
878 return undefined; | 878 return undefined; |
879 | 879 |
880 return actionUrls.buttonUrls[buttonIndex]; | 880 return actionUrls.buttonUrls[buttonIndex]; |
881 }); | 881 }); |
882 } | 882 } |
883 }); | 883 }); |
884 | 884 |
885 chrome.notifications.onClosed.addListener(onNotificationClosed); | 885 chrome.notifications.onClosed.addListener(onNotificationClosed); |
886 | 886 |
887 chrome.location.onLocationUpdate.addListener(function(position) { | 887 chrome.location.onLocationUpdate.addListener(function(position) { |
888 recordEvent(DiagnosticEvent.LOCATION_UPDATE); | 888 recordEvent(GoogleNowEvent.LOCATION_UPDATE); |
889 updateNotificationsCards(position); | 889 updateNotificationsCards(position); |
890 }); | 890 }); |
891 | 891 |
892 chrome.omnibox.onInputEntered.addListener(function(text) { | 892 chrome.omnibox.onInputEntered.addListener(function(text) { |
893 localStorage['server_url'] = NOTIFICATION_CARDS_URL = text; | 893 localStorage['server_url'] = NOTIFICATION_CARDS_URL = text; |
894 initialize(); | 894 initialize(); |
895 }); | 895 }); |
OLD | NEW |