Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(348)

Side by Side Diff: chrome/browser/resources/google_now/background.js

Issue 22912021: Handling errors from chrome APIs (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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.
11 * The service performs periodic updating of Google Now cards. 11 * The service performs periodic updating of Google Now cards.
12 * Each updating of the cards includes 4 steps: 12 * Each updating of the cards includes 4 steps:
13 * 1. Obtaining the location of the machine; 13 * 1. Obtaining the location of the machine;
14 * 2. Processing requests for cards dismissals that are not yet sent to the 14 * 2. Processing requests for cards dismissals that are not yet sent to the
15 * server; 15 * server;
16 * 3. Making a server request based on that location; 16 * 3. Making a server request based on that location;
17 * 4. Showing the received cards as notifications. 17 * 4. Showing the received cards as notifications.
18 */ 18 */
19 19
20 // TODO(vadimt): Use background permission to show notifications even when all 20 // TODO(vadimt): Use background permission to show notifications even when all
21 // browser windows are closed. 21 // browser windows are closed.
22 // TODO(vadimt): Decide what to do in incognito mode. 22 // TODO(vadimt): Decide what to do in incognito mode.
23 // TODO(vadimt): Honor the flag the enables Google Now integration. 23 // TODO(vadimt): Honor the flag the enables Google Now integration.
24 // TODO(vadimt): Figure out the final values of the constants. 24 // TODO(vadimt): Figure out the final values of the constants.
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 malformed server responses.
27 // malformed server responses.
28 27
29 /** 28 /**
30 * Standard response code for successful HTTP requests. This is the only success 29 * Standard response code for successful HTTP requests. This is the only success
31 * code the server will send. 30 * code the server will send.
32 */ 31 */
33 var HTTP_OK = 200; 32 var HTTP_OK = 200;
34 33
35 var HTTP_BAD_REQUEST = 400; 34 var HTTP_BAD_REQUEST = 400;
36 var HTTP_UNAUTHORIZED = 401; 35 var HTTP_UNAUTHORIZED = 401;
37 var HTTP_FORBIDDEN = 403; 36 var HTTP_FORBIDDEN = 403;
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
251 if (typeof parsedResponse.next_poll_seconds != 'number') { 250 if (typeof parsedResponse.next_poll_seconds != 'number') {
252 callback(); 251 callback();
253 return; 252 return;
254 } 253 }
255 254
256 tasks.debugSetStepName('parseAndShowNotificationCards-storage-get'); 255 tasks.debugSetStepName('parseAndShowNotificationCards-storage-get');
257 instrumented.storage.local.get(['notificationsData', 'recentDismissals'], 256 instrumented.storage.local.get(['notificationsData', 'recentDismissals'],
258 function(items) { 257 function(items) {
259 console.log('parseAndShowNotificationCards-get ' + 258 console.log('parseAndShowNotificationCards-get ' +
260 JSON.stringify(items)); 259 JSON.stringify(items));
261 items.notificationsData = items.notificationsData || {}; 260 items.notificationsData = items.notificationsData || {};
robliao 2013/08/22 00:01:56 Is a check here necessary too?
vadimt 2013/08/22 01:24:28 Yes, but this would cause conflicts with other CLs
262 items.recentDismissals = items.recentDismissals || {}; 261 items.recentDismissals = items.recentDismissals || {};
263 262
264 tasks.debugSetStepName( 263 tasks.debugSetStepName(
265 'parseAndShowNotificationCards-notifications-getAll'); 264 'parseAndShowNotificationCards-notifications-getAll');
266 instrumented.notifications.getAll(function(notifications) { 265 instrumented.notifications.getAll(function(notifications) {
267 console.log('parseAndShowNotificationCards-getAll ' + 266 console.log('parseAndShowNotificationCards-getAll ' +
268 JSON.stringify(notifications)); 267 JSON.stringify(notifications));
269 // TODO(vadimt): Figure out what to do when notifications are 268 // TODO(vadimt): Figure out what to do when notifications are
270 // disabled for our extension. 269 // disabled for our extension.
271 notifications = notifications || {}; 270 notifications = notifications || {};
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
339 * For example, this occurs when the geolocation preference is unchecked in the 338 * For example, this occurs when the geolocation preference is unchecked in the
340 * content settings. 339 * content settings.
341 */ 340 */
342 function removeAllCards() { 341 function removeAllCards() {
343 console.log('removeAllCards'); 342 console.log('removeAllCards');
344 343
345 // TODO(robliao): Once Google Now clears its own checkbox in the 344 // TODO(robliao): Once Google Now clears its own checkbox in the
346 // notifications center and bug 260376 is fixed, the below clearing 345 // notifications center and bug 260376 is fixed, the below clearing
347 // code is no longer necessary. 346 // code is no longer necessary.
348 instrumented.notifications.getAll(function(notifications) { 347 instrumented.notifications.getAll(function(notifications) {
348 notifications = notifications || {};
349 for (var notificationId in notifications) { 349 for (var notificationId in notifications) {
350 chrome.notifications.clear(notificationId, function() {}); 350 chrome.notifications.clear(notificationId, function() {});
351 } 351 }
352 chrome.storage.local.set({notificationsData: {}}); 352 chrome.storage.local.set({notificationsData: {}});
353 }); 353 });
354 } 354 }
355 355
356 /** 356 /**
357 * Requests notification cards from the server. 357 * Requests notification cards from the server.
358 * @param {Location} position Location of this computer. 358 * @param {Location} position Location of this computer.
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
398 }); 398 });
399 } 399 }
400 400
401 /** 401 /**
402 * Starts getting location for a cards update. 402 * Starts getting location for a cards update.
403 */ 403 */
404 function requestLocation() { 404 function requestLocation() {
405 console.log('requestLocation'); 405 console.log('requestLocation');
406 recordEvent(GoogleNowEvent.LOCATION_REQUEST); 406 recordEvent(GoogleNowEvent.LOCATION_REQUEST);
407 // TODO(vadimt): Figure out location request options. 407 // TODO(vadimt): Figure out location request options.
408 chrome.metricsPrivate.getVariationParams('GoogleNow', function(params) { 408 instrumented.metricsPrivate.getVariationParams('GoogleNow', function(params) {
409 var minDistanceInMeters = 409 var minDistanceInMeters =
410 parseInt(params && params.minDistanceInMeters, 10) || 410 parseInt(params && params.minDistanceInMeters, 10) ||
411 100; 411 100;
412 var minTimeInMilliseconds = 412 var minTimeInMilliseconds =
413 parseInt(params && params.minTimeInMilliseconds, 10) || 413 parseInt(params && params.minTimeInMilliseconds, 10) ||
414 180000; // 3 minutes. 414 180000; // 3 minutes.
415 415
416 chrome.location.watchLocation(LOCATION_WATCH_NAME, { 416 chrome.location.watchLocation(LOCATION_WATCH_NAME, {
417 minDistanceInMeters: minDistanceInMeters, 417 minDistanceInMeters: minDistanceInMeters,
418 minTimeInMilliseconds: minTimeInMilliseconds 418 minTimeInMilliseconds: minTimeInMilliseconds
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
511 * Tries to send dismiss requests for all pending dismissals. 511 * Tries to send dismiss requests for all pending dismissals.
512 * @param {function(boolean)} callbackBoolean Completion callback with 'success' 512 * @param {function(boolean)} callbackBoolean Completion callback with 'success'
513 * parameter. Success means that no pending dismissals are left. 513 * parameter. Success means that no pending dismissals are left.
514 */ 514 */
515 function processPendingDismissals(callbackBoolean) { 515 function processPendingDismissals(callbackBoolean) {
516 tasks.debugSetStepName('processPendingDismissals-storage-get'); 516 tasks.debugSetStepName('processPendingDismissals-storage-get');
517 instrumented.storage.local.get(['pendingDismissals', 'recentDismissals'], 517 instrumented.storage.local.get(['pendingDismissals', 'recentDismissals'],
518 function(items) { 518 function(items) {
519 console.log('processPendingDismissals-storage-get ' + 519 console.log('processPendingDismissals-storage-get ' +
520 JSON.stringify(items)); 520 JSON.stringify(items));
521 items.pendingDismissals = items.pendingDismissals || []; 521 items.pendingDismissals = items.pendingDismissals || [];
robliao 2013/08/22 00:01:56 Should we check items here?
vadimt 2013/08/22 01:24:28 Conflicts, see above.
522 items.recentDismissals = items.recentDismissals || {}; 522 items.recentDismissals = items.recentDismissals || {};
523 523
524 var dismissalsChanged = false; 524 var dismissalsChanged = false;
525 525
526 function onFinish(success) { 526 function onFinish(success) {
527 if (dismissalsChanged) { 527 if (dismissalsChanged) {
528 chrome.storage.local.set({ 528 chrome.storage.local.set({
529 pendingDismissals: items.pendingDismissals, 529 pendingDismissals: items.pendingDismissals,
530 recentDismissals: items.recentDismissals 530 recentDismissals: items.recentDismissals
531 }); 531 });
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
575 } 575 }
576 576
577 /** 577 /**
578 * Opens URL corresponding to the clicked part of the notification. 578 * Opens URL corresponding to the clicked part of the notification.
579 * @param {string} notificationId Unique identifier of the notification. 579 * @param {string} notificationId Unique identifier of the notification.
580 * @param {function(Object): string} selector Function that extracts the url for 580 * @param {function(Object): string} selector Function that extracts the url for
581 * the clicked area from the button action URLs info. 581 * the clicked area from the button action URLs info.
582 */ 582 */
583 function onNotificationClicked(notificationId, selector) { 583 function onNotificationClicked(notificationId, selector) {
584 instrumented.storage.local.get('notificationsData', function(items) { 584 instrumented.storage.local.get('notificationsData', function(items) {
585 items.notificationsData = items.notificationsData || {}; 585 if (!items || !items.notificationsData)
586 return;
586 587
587 var notificationData = items.notificationsData[notificationId]; 588 var notificationData = items.notificationsData[notificationId];
skare_ 2013/08/21 23:12:32 no action required but consider var nd = items &&
rgustafson 2013/08/22 00:46:14 +1, will return below anyways.
vadimt 2013/08/22 01:24:28 Done.
588 589
589 if (!notificationData) { 590 if (!notificationData) {
590 // 'notificationsData' in storage may not match the actual list of 591 // 'notificationsData' in storage may not match the actual list of
591 // notifications. 592 // notifications.
592 return; 593 return;
593 } 594 }
594 595
595 var actionUrls = notificationData.actionUrls; 596 var actionUrls = notificationData.actionUrls;
596 if (typeof actionUrls != 'object') { 597 if (typeof actionUrls != 'object') {
597 return; 598 return;
598 } 599 }
599 600
600 var url = selector(actionUrls); 601 var url = selector(actionUrls);
601 602 if (!url)
rgustafson 2013/08/22 00:46:14 This is verified already in the selector. if state
vadimt 2013/08/22 01:24:28 Not in selector in 'instrumented.notifications.onC
602 if (typeof url != 'string')
603 return; 603 return;
604 604
605 instrumented.tabs.create({url: url}, function(tab) { 605 instrumented.tabs.create({url: url}, function(tab) {
606 if (tab) 606 if (tab)
607 chrome.windows.update(tab.windowId, {focused: true}); 607 chrome.windows.update(tab.windowId, {focused: true});
608 else 608 else
609 chrome.windows.create({url: url, focused: true}); 609 chrome.windows.create({url: url, focused: true});
610 }); 610 });
611 }); 611 });
612 } 612 }
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
652 tasks.add(DISMISS_CARD_TASK_NAME, function(callback) { 652 tasks.add(DISMISS_CARD_TASK_NAME, function(callback) {
653 dismissalAttempts.start(); 653 dismissalAttempts.start();
654 654
655 // Deleting the notification in case it was re-added while this task was 655 // Deleting the notification in case it was re-added while this task was
656 // scheduled, waiting for execution. 656 // scheduled, waiting for execution.
657 cardSet.clear(notificationId); 657 cardSet.clear(notificationId);
658 658
659 tasks.debugSetStepName('onNotificationClosed-storage-get'); 659 tasks.debugSetStepName('onNotificationClosed-storage-get');
660 instrumented.storage.local.get(['pendingDismissals', 'notificationsData'], 660 instrumented.storage.local.get(['pendingDismissals', 'notificationsData'],
661 function(items) { 661 function(items) {
662 items.pendingDismissals = items.pendingDismissals || []; 662 items.pendingDismissals = items.pendingDismissals || [];
robliao 2013/08/22 00:01:56 Check?
vadimt 2013/08/22 01:24:28 Conflicts.
663 items.notificationsData = items.notificationsData || {}; 663 items.notificationsData = items.notificationsData || {};
664 664
665 var notificationData = items.notificationsData[notificationId]; 665 var notificationData = items.notificationsData[notificationId];
666 666
667 var dismissal = { 667 var dismissal = {
668 notificationId: notificationId, 668 notificationId: notificationId,
669 time: Date.now(), 669 time: Date.now(),
670 parameters: notificationData && notificationData.dismissalParameters 670 parameters: notificationData && notificationData.dismissalParameters
671 }; 671 };
672 items.pendingDismissals.push(dismissal); 672 items.pendingDismissals.push(dismissal);
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
873 'GoogleNow', 873 'GoogleNow',
874 function(response) { 874 function(response) {
875 var enableBackground = 875 var enableBackground =
876 (!response || (response.enableBackground != 'false')); 876 (!response || (response.enableBackground != 'false'));
877 tasks.debugSetStepName( 877 tasks.debugSetStepName(
878 'onStateChange-get-googleGeolocationAccessEnabledPref'); 878 'onStateChange-get-googleGeolocationAccessEnabledPref');
879 instrumented. 879 instrumented.
880 preferencesPrivate. 880 preferencesPrivate.
881 googleGeolocationAccessEnabled. 881 googleGeolocationAccessEnabled.
882 get({}, function(prefValue) { 882 get({}, function(prefValue) {
883 var geolocationEnabled = !!prefValue.value; 883 var geolocationEnabled = !!prefValue.value;
robliao 2013/08/22 00:01:56 Is any Chrome API subject to returning undefined?
vadimt 2013/08/22 01:24:28 No. Only those that are explicitly implemented to
robliao 2013/08/22 18:01:13 As written, it cannot fail. On 2013/08/22 01:24:28
884 tasks.debugSetStepName( 884 tasks.debugSetStepName(
885 'onStateChange-get-userRespondedToToast'); 885 'onStateChange-get-userRespondedToToast');
886 instrumented.storage.local.get( 886 instrumented.storage.local.get(
887 'userRespondedToToast', 887 'userRespondedToToast',
888 function(items) { 888 function(items) {
889 var userRespondedToToast = !!items.userRespondedToToast; 889 var userRespondedToToast =
890 !items || !!items.userRespondedToToast;
rgustafson 2013/08/22 00:46:14 Could this get the user in a weird state if there
vadimt 2013/08/22 01:24:28 Deep comment again. If we are polling, the final s
rgustafson 2013/08/22 19:07:32 We'll hide the toast and disable ourselves for jus
vadimt 2013/08/22 19:34:55 https://code.google.com/p/chromium/issues/detail?i
890 updateRunningState( 891 updateRunningState(
891 signedIn, 892 signedIn,
892 geolocationEnabled, 893 geolocationEnabled,
893 userRespondedToToast, 894 userRespondedToToast,
894 enableBackground, 895 enableBackground,
895 callback); 896 callback);
896 }); 897 });
897 }); 898 });
898 }); 899 });
899 }); 900 });
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
967 }); 968 });
968 969
969 instrumented.notifications.onButtonClicked.addListener( 970 instrumented.notifications.onButtonClicked.addListener(
970 function(notificationId, buttonIndex) { 971 function(notificationId, buttonIndex) {
971 if (notificationId == WELCOME_TOAST_NOTIFICATION_ID) { 972 if (notificationId == WELCOME_TOAST_NOTIFICATION_ID) {
972 onToastNotificationClicked(buttonIndex); 973 onToastNotificationClicked(buttonIndex);
973 } else { 974 } else {
974 chrome.metricsPrivate.recordUserAction( 975 chrome.metricsPrivate.recordUserAction(
975 'GoogleNow.ButtonClicked' + buttonIndex); 976 'GoogleNow.ButtonClicked' + buttonIndex);
976 onNotificationClicked(notificationId, function(actionUrls) { 977 onNotificationClicked(notificationId, function(actionUrls) {
977 if (!Array.isArray(actionUrls.buttonUrls)) 978 verify(actionUrls.buttonUrls[buttonIndex],
rgustafson 2013/08/22 00:46:14 pull actionUrls.buttonUrls[buttonIndex] out into u
vadimt 2013/08/22 01:24:28 Done.
978 return undefined; 979 'onButtonClicked: no url for a button');
979
980 return actionUrls.buttonUrls[buttonIndex]; 980 return actionUrls.buttonUrls[buttonIndex];
981 }); 981 });
982 } 982 }
983 }); 983 });
984 984
985 instrumented.notifications.onClosed.addListener(onNotificationClosed); 985 instrumented.notifications.onClosed.addListener(onNotificationClosed);
986 986
987 instrumented.location.onLocationUpdate.addListener(function(position) { 987 instrumented.location.onLocationUpdate.addListener(function(position) {
988 recordEvent(GoogleNowEvent.LOCATION_UPDATE); 988 recordEvent(GoogleNowEvent.LOCATION_UPDATE);
989 updateNotificationsCards(position); 989 updateNotificationsCards(position);
990 }); 990 });
991 991
992 instrumented.omnibox.onInputEntered.addListener(function(text) { 992 instrumented.omnibox.onInputEntered.addListener(function(text) {
993 localStorage['server_url'] = NOTIFICATION_CARDS_URL = text; 993 localStorage['server_url'] = NOTIFICATION_CARDS_URL = text;
994 initialize(); 994 initialize();
995 }); 995 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698