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'; TODO(vadimt): Uncomment once crbug.com/237617 is fixed. | 5 // 'use strict'; TODO(vadimt): Uncomment once crbug.com/237617 is fixed. |
| 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 unexpected exceptions (including | 26 // TODO(vadimt): Consider sending JS stacks for chrome.* API errors and |
| 27 // ones from verify()), unfinished and infinite tasks, chrome.* API errors and | |
| 28 // malformed server responses. | 27 // malformed server responses. |
| 29 | 28 |
| 30 /** | 29 /** |
| 31 * 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 |
| 32 * code the server will send. | 31 * code the server will send. |
| 33 */ | 32 */ |
| 34 var HTTP_OK = 200; | 33 var HTTP_OK = 200; |
| 35 | 34 |
| 36 /** | 35 /** |
| 37 * Initial period for polling for Google Now Notifications cards to use when the | 36 * Initial period for polling for Google Now Notifications cards to use when the |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 237 callback(); | 236 callback(); |
| 238 return; | 237 return; |
| 239 } | 238 } |
| 240 | 239 |
| 241 if (typeof parsedResponse.expiration_timestamp_seconds != 'number') { | 240 if (typeof parsedResponse.expiration_timestamp_seconds != 'number') { |
| 242 callback(); | 241 callback(); |
| 243 return; | 242 return; |
| 244 } | 243 } |
| 245 | 244 |
| 246 tasks.debugSetStepName('parseAndShowNotificationCards-storage-get'); | 245 tasks.debugSetStepName('parseAndShowNotificationCards-storage-get'); |
| 247 storage.get(['activeNotifications', 'recentDismissals'], function(items) { | 246 storage.get(['activeNotifications', 'recentDismissals'], function(items) { |
|
not at google - send to devlin
2013/05/24 00:01:12
instead you could call
storage.get({
'activeNot
| |
| 248 console.log('parseAndShowNotificationCards-get ' + JSON.stringify(items)); | 247 console.log('parseAndShowNotificationCards-get ' + JSON.stringify(items)); |
| 248 items.activeNotifications = items.activeNotifications || {}; | |
| 249 items.recentDismissals = items.recentDismissals || {}; | |
| 249 | 250 |
| 250 // Build a set of non-expired recent dismissals. It will be used for | 251 // Build a set of non-expired recent dismissals. It will be used for |
| 251 // client-side filtering of cards. | 252 // client-side filtering of cards. |
| 252 var updatedRecentDismissals = {}; | 253 var updatedRecentDismissals = {}; |
| 253 var currentTimeMs = Date.now(); | 254 var currentTimeMs = Date.now(); |
| 254 for (var notificationId in items.recentDismissals) { | 255 for (var notificationId in items.recentDismissals) { |
| 255 if (currentTimeMs - items.recentDismissals[notificationId] < | 256 if (currentTimeMs - items.recentDismissals[notificationId] < |
| 256 DISMISS_RETENTION_TIME_MS) { | 257 DISMISS_RETENTION_TIME_MS) { |
| 257 updatedRecentDismissals[notificationId] = | 258 updatedRecentDismissals[notificationId] = |
| 258 items.recentDismissals[notificationId]; | 259 items.recentDismissals[notificationId]; |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 409 /** | 410 /** |
| 410 * Tries to send dismiss requests for all pending dismissals. | 411 * Tries to send dismiss requests for all pending dismissals. |
| 411 * @param {function(boolean)} callbackBoolean Completion callback with 'success' | 412 * @param {function(boolean)} callbackBoolean Completion callback with 'success' |
| 412 * parameter. Success means that no pending dismissals are left. | 413 * parameter. Success means that no pending dismissals are left. |
| 413 */ | 414 */ |
| 414 function processPendingDismissals(callbackBoolean) { | 415 function processPendingDismissals(callbackBoolean) { |
| 415 tasks.debugSetStepName('processPendingDismissals-storage-get'); | 416 tasks.debugSetStepName('processPendingDismissals-storage-get'); |
| 416 storage.get(['pendingDismissals', 'recentDismissals'], function(items) { | 417 storage.get(['pendingDismissals', 'recentDismissals'], function(items) { |
| 417 console.log('processPendingDismissals-storage-get ' + | 418 console.log('processPendingDismissals-storage-get ' + |
| 418 JSON.stringify(items)); | 419 JSON.stringify(items)); |
| 420 items.pendingDismissals = items.pendingDismissals || []; | |
| 421 items.recentDismissals = items.recentDismissals || {}; | |
| 422 | |
| 419 var dismissalsChanged = false; | 423 var dismissalsChanged = false; |
| 420 | 424 |
| 421 function onFinish(success) { | 425 function onFinish(success) { |
| 422 if (dismissalsChanged) { | 426 if (dismissalsChanged) { |
| 423 storage.set({ | 427 storage.set({ |
| 424 pendingDismissals: items.pendingDismissals, | 428 pendingDismissals: items.pendingDismissals, |
| 425 recentDismissals: items.recentDismissals | 429 recentDismissals: items.recentDismissals |
| 426 }); | 430 }); |
| 427 } | 431 } |
| 428 callbackBoolean(success); | 432 callbackBoolean(success); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 469 /** | 473 /** |
| 470 * Opens URL corresponding to the clicked part of the notification. | 474 * Opens URL corresponding to the clicked part of the notification. |
| 471 * @param {string} notificationId Unique identifier of the notification. | 475 * @param {string} notificationId Unique identifier of the notification. |
| 472 * @param {function(Object): string} selector Function that extracts the url for | 476 * @param {function(Object): string} selector Function that extracts the url for |
| 473 * the clicked area from the button action URLs info. | 477 * the clicked area from the button action URLs info. |
| 474 */ | 478 */ |
| 475 function onNotificationClicked(notificationId, selector) { | 479 function onNotificationClicked(notificationId, selector) { |
| 476 tasks.add(CARD_CLICKED_TASK_NAME, function(callback) { | 480 tasks.add(CARD_CLICKED_TASK_NAME, function(callback) { |
| 477 tasks.debugSetStepName('onNotificationClicked-get-activeNotifications'); | 481 tasks.debugSetStepName('onNotificationClicked-get-activeNotifications'); |
| 478 storage.get('activeNotifications', function(items) { | 482 storage.get('activeNotifications', function(items) { |
| 483 items.activeNotifications = items.activeNotifications || {}; | |
| 484 | |
| 479 var actionUrls = items.activeNotifications[notificationId].actionUrls; | 485 var actionUrls = items.activeNotifications[notificationId].actionUrls; |
| 480 if (typeof actionUrls != 'object') { | 486 if (typeof actionUrls != 'object') { |
| 481 callback(); | 487 callback(); |
| 482 return; | 488 return; |
| 483 } | 489 } |
| 484 | 490 |
| 485 var url = selector(actionUrls); | 491 var url = selector(actionUrls); |
| 486 | 492 |
| 487 if (typeof url != 'string') { | 493 if (typeof url != 'string') { |
| 488 callback(); | 494 callback(); |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 513 dismissalAttempts.start(); | 519 dismissalAttempts.start(); |
| 514 | 520 |
| 515 // Deleting the notification in case it was re-added while this task was | 521 // Deleting the notification in case it was re-added while this task was |
| 516 // scheduled, waiting for execution. | 522 // scheduled, waiting for execution. |
| 517 chrome.notifications.clear( | 523 chrome.notifications.clear( |
| 518 notificationId, | 524 notificationId, |
| 519 function() {}); | 525 function() {}); |
| 520 | 526 |
| 521 tasks.debugSetStepName('onNotificationClosed-get-pendingDismissals'); | 527 tasks.debugSetStepName('onNotificationClosed-get-pendingDismissals'); |
| 522 storage.get('pendingDismissals', function(items) { | 528 storage.get('pendingDismissals', function(items) { |
| 529 items.pendingDismissals = items.pendingDismissals || []; | |
| 530 | |
| 523 var dismissal = { | 531 var dismissal = { |
| 524 notificationId: notificationId, | 532 notificationId: notificationId, |
| 525 time: Date.now() | 533 time: Date.now() |
| 526 }; | 534 }; |
| 527 items.pendingDismissals.push(dismissal); | 535 items.pendingDismissals.push(dismissal); |
| 528 storage.set({pendingDismissals: items.pendingDismissals}); | 536 storage.set({pendingDismissals: items.pendingDismissals}); |
| 529 processPendingDismissals(function(success) { callback(); }); | 537 processPendingDismissals(function(success) { callback(); }); |
| 530 }); | 538 }); |
| 531 }); | 539 }); |
| 532 } | 540 } |
| 533 | 541 |
| 534 /** | 542 /** |
| 535 * Initializes the event page on install or on browser startup. | 543 * Initializes the event page on install or on browser startup. |
| 536 */ | 544 */ |
| 537 function initialize() { | 545 function initialize() { |
| 538 // Create an update timer for a case when for some reason location request | 546 // Create an update timer for a case when for some reason location request |
| 539 // gets stuck. | 547 // gets stuck. |
| 540 updateCardsAttempts.start(MAXIMUM_POLLING_PERIOD_SECONDS); | 548 updateCardsAttempts.start(MAXIMUM_POLLING_PERIOD_SECONDS); |
| 541 | 549 |
| 542 var initialStorage = { | 550 var initialStorage = { |
| 543 activeNotifications: {}, | 551 activeNotifications: {} |
| 544 recentDismissals: {} | |
| 545 }; | 552 }; |
| 546 storage.set(initialStorage); | 553 storage.set(initialStorage); |
| 547 | 554 |
| 548 requestLocation(); | 555 requestLocation(); |
| 549 } | 556 } |
| 550 | 557 |
| 551 chrome.runtime.onInstalled.addListener(function(details) { | 558 chrome.runtime.onInstalled.addListener(function(details) { |
| 552 console.log('onInstalled ' + JSON.stringify(details)); | 559 console.log('onInstalled ' + JSON.stringify(details)); |
| 553 if (details.reason != 'chrome_update') { | 560 if (details.reason != 'chrome_update') { |
| 554 storage.set({pendingDismissals: []}); | |
| 555 initialize(); | 561 initialize(); |
| 556 } | 562 } |
| 557 }); | 563 }); |
| 558 | 564 |
| 559 chrome.runtime.onStartup.addListener(function() { | 565 chrome.runtime.onStartup.addListener(function() { |
| 560 console.log('onStartup'); | 566 console.log('onStartup'); |
| 561 initialize(); | 567 initialize(); |
| 562 }); | 568 }); |
| 563 | 569 |
| 564 chrome.notifications.onClicked.addListener( | 570 chrome.notifications.onClicked.addListener( |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 577 if (!Array.isArray(actionUrls.buttonUrls)) | 583 if (!Array.isArray(actionUrls.buttonUrls)) |
| 578 return undefined; | 584 return undefined; |
| 579 | 585 |
| 580 return actionUrls.buttonUrls[buttonIndex]; | 586 return actionUrls.buttonUrls[buttonIndex]; |
| 581 }); | 587 }); |
| 582 }); | 588 }); |
| 583 | 589 |
| 584 chrome.notifications.onClosed.addListener(onNotificationClosed); | 590 chrome.notifications.onClosed.addListener(onNotificationClosed); |
| 585 | 591 |
| 586 chrome.location.onLocationUpdate.addListener(updateNotificationsCards); | 592 chrome.location.onLocationUpdate.addListener(updateNotificationsCards); |
| OLD | NEW |