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 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 107 scheduledTaskName == DISMISS_CARD_TASK_NAME || | 107 scheduledTaskName == DISMISS_CARD_TASK_NAME || |
| 108 scheduledTaskName == RETRY_DISMISS_TASK_NAME)) { | 108 scheduledTaskName == RETRY_DISMISS_TASK_NAME)) { |
| 109 // No need to schedule retry-dismiss action if another action that tries to | 109 // No need to schedule retry-dismiss action if another action that tries to |
| 110 // send dismissals is scheduled. | 110 // send dismissals is scheduled. |
| 111 return true; | 111 return true; |
| 112 } | 112 } |
| 113 | 113 |
| 114 return false; | 114 return false; |
| 115 } | 115 } |
| 116 | 116 |
| 117 var googleGeolocationAccessEnabledPref = | |
| 118 chrome.preferencesPrivate.googleGeolocationAccessEnabled; | |
| 119 | |
| 120 var tasks = buildTaskManager(areTasksConflicting); | 117 var tasks = buildTaskManager(areTasksConflicting); |
| 121 | 118 |
| 122 // Add error processing to API calls. | 119 // Add error processing to API calls. |
| 123 tasks.instrumentApiFunction(chrome.location.onLocationUpdate, 'addListener', 0); | 120 tasks.instrumentChromeApiFunction('location.onLocationUpdate.addListener', 0); |
| 124 tasks.instrumentApiFunction(chrome.notifications, 'create', 2); | 121 tasks.instrumentChromeApiFunction('notifications.create', 2); |
| 125 tasks.instrumentApiFunction(chrome.notifications, 'update', 2); | 122 tasks.instrumentChromeApiFunction('notifications.update', 2); |
| 126 tasks.instrumentApiFunction(chrome.notifications, 'getAll', 0); | 123 tasks.instrumentChromeApiFunction('notifications.getAll', 0); |
| 127 tasks.instrumentApiFunction( | 124 tasks.instrumentChromeApiFunction( |
| 128 chrome.notifications.onButtonClicked, 'addListener', 0); | 125 'notifications.onButtonClicked.addListener', 0); |
| 129 tasks.instrumentApiFunction(chrome.notifications.onClicked, 'addListener', 0); | 126 tasks.instrumentChromeApiFunction('notifications.onClicked.addListener', 0); |
| 130 tasks.instrumentApiFunction(chrome.notifications.onClosed, 'addListener', 0); | 127 tasks.instrumentChromeApiFunction('notifications.onClosed.addListener', 0); |
| 131 tasks.instrumentApiFunction(chrome.omnibox.onInputEntered, 'addListener', 0); | 128 tasks.instrumentChromeApiFunction('omnibox.onInputEntered.addListener', 0); |
| 132 tasks.instrumentApiFunction( | 129 tasks.instrumentChromeApiFunction( |
| 133 googleGeolocationAccessEnabledPref, | 130 'preferencesPrivate.googleGeolocationAccessEnabled.get', |
| 134 'get', | |
| 135 1); | 131 1); |
| 136 tasks.instrumentApiFunction( | 132 tasks.instrumentChromeApiFunction( |
| 137 googleGeolocationAccessEnabledPref.onChange, | 133 'preferencesPrivate.googleGeolocationAccessEnabled.onChange.addListener', |
| 138 'addListener', | |
| 139 0); | 134 0); |
| 140 tasks.instrumentApiFunction(chrome.runtime.onInstalled, 'addListener', 0); | 135 tasks.instrumentChromeApiFunction('runtime.onInstalled.addListener', 0); |
| 141 tasks.instrumentApiFunction(chrome.runtime.onStartup, 'addListener', 0); | 136 tasks.instrumentChromeApiFunction('runtime.onStartup.addListener', 0); |
| 142 tasks.instrumentApiFunction(chrome.tabs, 'create', 1); | 137 tasks.instrumentChromeApiFunction('tabs.create', 1); |
| 143 tasks.instrumentApiFunction(storage, 'get', 1); | 138 tasks.instrumentChromeApiFunction('storage.local.get', 1); |
| 144 | 139 |
| 145 var updateCardsAttempts = buildAttemptManager( | 140 var updateCardsAttempts = buildAttemptManager( |
| 146 'cards-update', | 141 'cards-update', |
| 147 requestLocation, | 142 requestLocation, |
| 148 INITIAL_POLLING_PERIOD_SECONDS, | 143 INITIAL_POLLING_PERIOD_SECONDS, |
| 149 MAXIMUM_POLLING_PERIOD_SECONDS); | 144 MAXIMUM_POLLING_PERIOD_SECONDS); |
| 150 var dismissalAttempts = buildAttemptManager( | 145 var dismissalAttempts = buildAttemptManager( |
| 151 'dismiss', | 146 'dismiss', |
| 152 retryPendingDismissals, | 147 retryPendingDismissals, |
| 153 INITIAL_RETRY_DISMISS_PERIOD_SECONDS, | 148 INITIAL_RETRY_DISMISS_PERIOD_SECONDS, |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 248 callback(); | 243 callback(); |
| 249 return; | 244 return; |
| 250 } | 245 } |
| 251 | 246 |
| 252 if (typeof parsedResponse.next_poll_seconds != 'number') { | 247 if (typeof parsedResponse.next_poll_seconds != 'number') { |
| 253 callback(); | 248 callback(); |
| 254 return; | 249 return; |
| 255 } | 250 } |
| 256 | 251 |
| 257 tasks.debugSetStepName('parseAndShowNotificationCards-storage-get'); | 252 tasks.debugSetStepName('parseAndShowNotificationCards-storage-get'); |
| 258 storage.get(['notificationsData', 'recentDismissals'], function(items) { | 253 instrumented.storage.local.get(['notificationsData', 'recentDismissals'], |
| 259 console.log('parseAndShowNotificationCards-get ' + JSON.stringify(items)); | 254 function(items) { |
| 260 items.notificationsData = items.notificationsData || {}; | 255 console.log('parseAndShowNotificationCards-get ' + |
| 261 items.recentDismissals = items.recentDismissals || {}; | 256 JSON.stringify(items)); |
| 257 items.notificationsData = items.notificationsData || {}; | |
| 258 items.recentDismissals = items.recentDismissals || {}; | |
| 262 | 259 |
| 263 tasks.debugSetStepName( | 260 tasks.debugSetStepName( |
| 264 'parseAndShowNotificationCards-notifications-getAll'); | 261 'parseAndShowNotificationCards-notifications-getAll'); |
| 265 chrome.notifications.getAll(function(notifications) { | 262 instrumented.notifications.getAll(function(notifications) { |
| 266 console.log('parseAndShowNotificationCards-getAll ' + | 263 console.log('parseAndShowNotificationCards-getAll ' + |
| 267 JSON.stringify(notifications)); | 264 JSON.stringify(notifications)); |
| 268 // TODO(vadimt): Figure out what to do when notifications are disabled for | 265 // TODO(vadimt): Figure out what to do when notifications are |
| 269 // our extension. | 266 // disabled for our extension. |
| 270 notifications = notifications || {}; | 267 notifications = notifications || {}; |
| 271 | 268 |
| 272 // Build a set of non-expired recent dismissals. It will be used for | 269 // Build a set of non-expired recent dismissals. It will be used for |
| 273 // client-side filtering of cards. | 270 // client-side filtering of cards. |
| 274 var updatedRecentDismissals = {}; | 271 var updatedRecentDismissals = {}; |
| 275 var currentTimeMs = Date.now(); | 272 var currentTimeMs = Date.now(); |
| 276 for (var notificationId in items.recentDismissals) { | 273 for (var notificationId in items.recentDismissals) { |
| 277 if (currentTimeMs - items.recentDismissals[notificationId] < | 274 if (currentTimeMs - items.recentDismissals[notificationId] < |
| 278 DISMISS_RETENTION_TIME_MS) { | 275 DISMISS_RETENTION_TIME_MS) { |
| 279 updatedRecentDismissals[notificationId] = | 276 updatedRecentDismissals[notificationId] = |
| 280 items.recentDismissals[notificationId]; | 277 items.recentDismissals[notificationId]; |
| 281 } | 278 } |
| 282 } | 279 } |
| 283 | 280 |
| 284 // Mark existing notifications that received an update in this server | 281 // Mark existing notifications that received an update in this server |
| 285 // response. | 282 // response. |
| 286 var updatedNotifications = {}; | 283 var updatedNotifications = {}; |
| 287 | 284 |
| 288 for (var i = 0; i < cards.length; ++i) { | 285 for (var i = 0; i < cards.length; ++i) { |
| 289 var notificationId = cards[i].notificationId; | 286 var notificationId = cards[i].notificationId; |
| 290 if (!(notificationId in updatedRecentDismissals) && | 287 if (!(notificationId in updatedRecentDismissals) && |
| 291 notificationId in notifications) { | 288 notificationId in notifications) { |
| 292 updatedNotifications[notificationId] = true; | 289 updatedNotifications[notificationId] = true; |
| 293 } | 290 } |
| 294 } | 291 } |
| 295 | 292 |
| 296 // Delete notifications that didn't receive an update. | 293 // Delete notifications that didn't receive an update. |
| 297 for (var notificationId in notifications) { | 294 for (var notificationId in notifications) { |
| 298 console.log('parseAndShowNotificationCards-delete-check ' + | 295 console.log('parseAndShowNotificationCards-delete-check ' + |
| 299 notificationId); | 296 notificationId); |
| 300 if (!(notificationId in updatedNotifications)) { | 297 if (!(notificationId in updatedNotifications)) { |
| 301 console.log('parseAndShowNotificationCards-delete ' + notificationId); | 298 console.log('parseAndShowNotificationCards-delete ' + |
| 302 cardSet.clear(notificationId); | 299 notificationId); |
| 303 } | 300 cardSet.clear(notificationId); |
| 304 } | 301 } |
| 302 } | |
| 305 | 303 |
| 306 recordEvent(GoogleNowEvent.CARDS_PARSE_SUCCESS); | 304 recordEvent(GoogleNowEvent.CARDS_PARSE_SUCCESS); |
| 307 | 305 |
| 308 // Create/update notifications and store their new properties. | 306 // Create/update notifications and store their new properties. |
| 309 var newNotificationsData = {}; | 307 var newNotificationsData = {}; |
| 310 for (var i = 0; i < cards.length; ++i) { | 308 for (var i = 0; i < cards.length; ++i) { |
| 311 var card = cards[i]; | 309 var card = cards[i]; |
| 312 if (!(card.notificationId in updatedRecentDismissals)) { | 310 if (!(card.notificationId in updatedRecentDismissals)) { |
| 313 var notificationData = items.notificationsData[card.notificationId]; | 311 var notificationData = |
| 314 var previousVersion = notifications[card.notificationId] && | 312 items.notificationsData[card.notificationId]; |
| 315 notificationData && | 313 var previousVersion = notifications[card.notificationId] && |
| 316 notificationData.cardCreateInfo && | 314 notificationData && |
| 317 notificationData.cardCreateInfo.version; | 315 notificationData.cardCreateInfo && |
| 318 newNotificationsData[card.notificationId] = | 316 notificationData.cardCreateInfo.version; |
| 319 cardSet.update(card, previousVersion); | 317 newNotificationsData[card.notificationId] = |
| 320 } | 318 cardSet.update(card, previousVersion); |
| 321 } | 319 } |
| 320 } | |
| 322 | 321 |
| 323 updateCardsAttempts.start(parsedResponse.next_poll_seconds); | 322 updateCardsAttempts.start(parsedResponse.next_poll_seconds); |
| 324 | 323 |
| 325 storage.set({ | 324 chrome.storage.local.set({ |
| 326 notificationsData: newNotificationsData, | 325 notificationsData: newNotificationsData, |
| 327 recentDismissals: updatedRecentDismissals | 326 recentDismissals: updatedRecentDismissals |
| 327 }); | |
| 328 callback(); | |
| 329 }); | |
| 328 }); | 330 }); |
| 329 callback(); | |
| 330 }); | |
| 331 }); | |
| 332 } | 331 } |
| 333 | 332 |
| 334 /** | 333 /** |
| 335 * Removes all cards and card state on Google Now close down. | 334 * Removes all cards and card state on Google Now close down. |
| 336 * For example, this occurs when the geolocation preference is unchecked in the | 335 * For example, this occurs when the geolocation preference is unchecked in the |
| 337 * content settings. | 336 * content settings. |
| 338 */ | 337 */ |
| 339 function removeAllCards() { | 338 function removeAllCards() { |
| 340 console.log('removeAllCards'); | 339 console.log('removeAllCards'); |
| 341 | 340 |
| 342 // TODO(robliao): Once Google Now clears its own checkbox in the | 341 // TODO(robliao): Once Google Now clears its own checkbox in the |
| 343 // notifications center and bug 260376 is fixed, the below clearing | 342 // notifications center and bug 260376 is fixed, the below clearing |
| 344 // code is no longer necessary. | 343 // code is no longer necessary. |
| 345 chrome.notifications.getAll(function(notifications) { | 344 instrumented.notifications.getAll(function(notifications) { |
| 346 for (var notificationId in notifications) { | 345 for (var notificationId in notifications) { |
| 347 chrome.notifications.clear(notificationId, function() {}); | 346 chrome.notifications.clear(notificationId, function() {}); |
| 348 } | 347 } |
| 349 storage.set({notificationsData: {}}); | 348 chrome.storage.local.set({notificationsData: {}}); |
| 350 }); | 349 }); |
| 351 } | 350 } |
| 352 | 351 |
| 353 /** | 352 /** |
| 354 * Requests notification cards from the server. | 353 * Requests notification cards from the server. |
| 355 * @param {Location} position Location of this computer. | 354 * @param {Location} position Location of this computer. |
| 356 * @param {function()} callback Completion callback. | 355 * @param {function()} callback Completion callback. |
| 357 */ | 356 */ |
| 358 function requestNotificationCards(position, callback) { | 357 function requestNotificationCards(position, callback) { |
| 359 console.log('requestNotificationCards ' + JSON.stringify(position) + | 358 console.log('requestNotificationCards ' + JSON.stringify(position) + |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 496 }); | 495 }); |
| 497 } | 496 } |
| 498 | 497 |
| 499 /** | 498 /** |
| 500 * Tries to send dismiss requests for all pending dismissals. | 499 * Tries to send dismiss requests for all pending dismissals. |
| 501 * @param {function(boolean)} callbackBoolean Completion callback with 'success' | 500 * @param {function(boolean)} callbackBoolean Completion callback with 'success' |
| 502 * parameter. Success means that no pending dismissals are left. | 501 * parameter. Success means that no pending dismissals are left. |
| 503 */ | 502 */ |
| 504 function processPendingDismissals(callbackBoolean) { | 503 function processPendingDismissals(callbackBoolean) { |
| 505 tasks.debugSetStepName('processPendingDismissals-storage-get'); | 504 tasks.debugSetStepName('processPendingDismissals-storage-get'); |
| 506 storage.get(['pendingDismissals', 'recentDismissals'], function(items) { | 505 instrumented.storage.local.get(['pendingDismissals', 'recentDismissals'], |
| 507 console.log('processPendingDismissals-storage-get ' + | 506 function(items) { |
| 508 JSON.stringify(items)); | 507 console.log('processPendingDismissals-storage-get ' + |
| 509 items.pendingDismissals = items.pendingDismissals || []; | 508 JSON.stringify(items)); |
| 510 items.recentDismissals = items.recentDismissals || {}; | 509 items.pendingDismissals = items.pendingDismissals || []; |
| 510 items.recentDismissals = items.recentDismissals || {}; | |
| 511 | 511 |
| 512 var dismissalsChanged = false; | 512 var dismissalsChanged = false; |
| 513 | 513 |
| 514 function onFinish(success) { | 514 function onFinish(success) { |
| 515 if (dismissalsChanged) { | 515 if (dismissalsChanged) { |
| 516 storage.set({ | 516 chrome.storage.local.set({ |
| 517 pendingDismissals: items.pendingDismissals, | 517 pendingDismissals: items.pendingDismissals, |
| 518 recentDismissals: items.recentDismissals | 518 recentDismissals: items.recentDismissals |
| 519 }); | 519 }); |
| 520 } | 520 } |
| 521 callbackBoolean(success); | 521 callbackBoolean(success); |
| 522 } | 522 } |
| 523 | 523 |
| 524 function doProcessDismissals() { | 524 function doProcessDismissals() { |
| 525 if (items.pendingDismissals.length == 0) { | 525 if (items.pendingDismissals.length == 0) { |
| 526 dismissalAttempts.stop(); | 526 dismissalAttempts.stop(); |
| 527 onFinish(true); | 527 onFinish(true); |
| 528 return; | 528 return; |
| 529 } | 529 } |
| 530 | 530 |
| 531 // Send dismissal for the first card, and if successful, repeat | 531 // Send dismissal for the first card, and if successful, repeat |
| 532 // recursively with the rest. | 532 // recursively with the rest. |
| 533 var dismissal = items.pendingDismissals[0]; | 533 var dismissal = items.pendingDismissals[0]; |
| 534 requestCardDismissal( | 534 requestCardDismissal( |
| 535 dismissal.notificationId, | 535 dismissal.notificationId, |
| 536 dismissal.time, | 536 dismissal.time, |
| 537 dismissal.parameters, | 537 dismissal.parameters, |
| 538 function(done) { | 538 function(done) { |
| 539 if (done) { | 539 if (done) { |
| 540 dismissalsChanged = true; | 540 dismissalsChanged = true; |
| 541 items.pendingDismissals.splice(0, 1); | 541 items.pendingDismissals.splice(0, 1); |
| 542 items.recentDismissals[dismissal.notificationId] = Date.now(); | 542 items.recentDismissals[dismissal.notificationId] = Date.now(); |
| 543 doProcessDismissals(); | 543 doProcessDismissals(); |
| 544 } else { | 544 } else { |
| 545 onFinish(false); | 545 onFinish(false); |
| 546 } | 546 } |
| 547 }); | 547 }); |
| 548 } | 548 } |
| 549 | 549 |
| 550 doProcessDismissals(); | 550 doProcessDismissals(); |
| 551 }); | 551 }); |
| 552 } | 552 } |
| 553 | 553 |
| 554 /** | 554 /** |
| 555 * Submits a task to send pending dismissals. | 555 * Submits a task to send pending dismissals. |
| 556 */ | 556 */ |
| 557 function retryPendingDismissals() { | 557 function retryPendingDismissals() { |
| 558 tasks.add(RETRY_DISMISS_TASK_NAME, function(callback) { | 558 tasks.add(RETRY_DISMISS_TASK_NAME, function(callback) { |
| 559 dismissalAttempts.planForNext(function() { | 559 dismissalAttempts.planForNext(function() { |
| 560 processPendingDismissals(function(success) { callback(); }); | 560 processPendingDismissals(function(success) { callback(); }); |
| 561 }); | 561 }); |
| 562 }); | 562 }); |
| 563 } | 563 } |
| 564 | 564 |
| 565 /** | 565 /** |
| 566 * Opens URL corresponding to the clicked part of the notification. | 566 * Opens URL corresponding to the clicked part of the notification. |
| 567 * @param {string} notificationId Unique identifier of the notification. | 567 * @param {string} notificationId Unique identifier of the notification. |
| 568 * @param {function(Object): string} selector Function that extracts the url for | 568 * @param {function(Object): string} selector Function that extracts the url for |
| 569 * the clicked area from the button action URLs info. | 569 * the clicked area from the button action URLs info. |
| 570 */ | 570 */ |
| 571 function onNotificationClicked(notificationId, selector) { | 571 function onNotificationClicked(notificationId, selector) { |
| 572 storage.get('notificationsData', function(items) { | 572 instrumented.storage.local.get('notificationsData', function(items) { |
| 573 items.notificationsData = items.notificationsData || {}; | 573 items.notificationsData = items.notificationsData || {}; |
| 574 | 574 |
| 575 var notificationData = items.notificationsData[notificationId]; | 575 var notificationData = items.notificationsData[notificationId]; |
| 576 | 576 |
| 577 if (!notificationData) { | 577 if (!notificationData) { |
| 578 // 'notificationsData' in storage may not match the actual list of | 578 // 'notificationsData' in storage may not match the actual list of |
| 579 // notifications. | 579 // notifications. |
| 580 return; | 580 return; |
| 581 } | 581 } |
| 582 | 582 |
| 583 var actionUrls = notificationData.actionUrls; | 583 var actionUrls = notificationData.actionUrls; |
| 584 if (typeof actionUrls != 'object') { | 584 if (typeof actionUrls != 'object') { |
| 585 return; | 585 return; |
| 586 } | 586 } |
| 587 | 587 |
| 588 var url = selector(actionUrls); | 588 var url = selector(actionUrls); |
| 589 | 589 |
| 590 if (typeof url != 'string') | 590 if (typeof url != 'string') |
| 591 return; | 591 return; |
| 592 | 592 |
| 593 chrome.tabs.create({url: url}, function(tab) { | 593 instrumented.tabs.create({url: url}, function(tab) { |
| 594 if (!tab) | 594 if (!tab) |
| 595 chrome.windows.create({url: url}); | 595 chrome.windows.create({url: url}); |
| 596 }); | 596 }); |
| 597 }); | 597 }); |
| 598 } | 598 } |
| 599 | 599 |
| 600 /** | 600 /** |
| 601 * Responds to a click of one of the buttons on the welcome toast. | 601 * Responds to a click of one of the buttons on the welcome toast. |
| 602 * @param {number} buttonIndex The index of the button which was clicked. | 602 * @param {number} buttonIndex The index of the button which was clicked. |
| 603 */ | 603 */ |
| 604 function onToastNotificationClicked(buttonIndex) { | 604 function onToastNotificationClicked(buttonIndex) { |
| 605 storage.set({userRespondedToToast: true}); | 605 chrome.storage.local.set({userRespondedToToast: true}); |
| 606 | 606 |
| 607 if (buttonIndex == ToastButtonIndex.YES) { | 607 if (buttonIndex == ToastButtonIndex.YES) { |
| 608 chrome.metricsPrivate.recordUserAction('GoogleNow.WelcomeToastClickedYes'); | 608 chrome.metricsPrivate.recordUserAction('GoogleNow.WelcomeToastClickedYes'); |
| 609 googleGeolocationAccessEnabledPref.set({value: true}); | 609 chrome.preferencesPrivate.googleGeolocationAccessEnabled.set({value: true}); |
| 610 // The googlegeolocationaccessenabled preference change callback | 610 // The googlegeolocationaccessenabled preference change callback |
| 611 // will take care of starting the poll for cards. | 611 // will take care of starting the poll for cards. |
| 612 } else { | 612 } else { |
| 613 chrome.metricsPrivate.recordUserAction('GoogleNow.WelcomeToastClickedNo'); | 613 chrome.metricsPrivate.recordUserAction('GoogleNow.WelcomeToastClickedNo'); |
| 614 onStateChange(); | 614 onStateChange(); |
| 615 } | 615 } |
| 616 } | 616 } |
| 617 | 617 |
| 618 /** | 618 /** |
| 619 * Callback for chrome.notifications.onClosed event. | 619 * Callback for chrome.notifications.onClosed event. |
| 620 * @param {string} notificationId Unique identifier of the notification. | 620 * @param {string} notificationId Unique identifier of the notification. |
| 621 * @param {boolean} byUser Whether the notification was closed by the user. | 621 * @param {boolean} byUser Whether the notification was closed by the user. |
| 622 */ | 622 */ |
| 623 function onNotificationClosed(notificationId, byUser) { | 623 function onNotificationClosed(notificationId, byUser) { |
| 624 if (!byUser) | 624 if (!byUser) |
| 625 return; | 625 return; |
| 626 | 626 |
| 627 if (notificationId == WELCOME_TOAST_NOTIFICATION_ID) { | 627 if (notificationId == WELCOME_TOAST_NOTIFICATION_ID) { |
| 628 // Even though they only closed the notification without clicking no, treat | 628 // Even though they only closed the notification without clicking no, treat |
| 629 // it as though they clicked No anwyay, and don't show the toast again. | 629 // it as though they clicked No anwyay, and don't show the toast again. |
| 630 chrome.metricsPrivate.recordUserAction('GoogleNow.WelcomeToastDismissed'); | 630 chrome.metricsPrivate.recordUserAction('GoogleNow.WelcomeToastDismissed'); |
| 631 storage.set({userRespondedToToast: true}); | 631 chrome.storage.local.set({userRespondedToToast: true}); |
| 632 return; | 632 return; |
| 633 } | 633 } |
| 634 | 634 |
| 635 // At this point we are guaranteed that the notification is a now card. | 635 // At this point we are guaranteed that the notification is a now card. |
| 636 chrome.metricsPrivate.recordUserAction('GoogleNow.Dismissed'); | 636 chrome.metricsPrivate.recordUserAction('GoogleNow.Dismissed'); |
| 637 | 637 |
| 638 tasks.add(DISMISS_CARD_TASK_NAME, function(callback) { | 638 tasks.add(DISMISS_CARD_TASK_NAME, function(callback) { |
| 639 dismissalAttempts.start(); | 639 dismissalAttempts.start(); |
| 640 | 640 |
| 641 // Deleting the notification in case it was re-added while this task was | 641 // Deleting the notification in case it was re-added while this task was |
| 642 // scheduled, waiting for execution. | 642 // scheduled, waiting for execution. |
| 643 cardSet.clear(notificationId); | 643 cardSet.clear(notificationId); |
| 644 | 644 |
| 645 tasks.debugSetStepName('onNotificationClosed-storage-get'); | 645 tasks.debugSetStepName('onNotificationClosed-storage-get'); |
| 646 storage.get(['pendingDismissals', 'notificationsData'], function(items) { | 646 instrumented.storage.local.get(['pendingDismissals', 'notificationsData'], |
| 647 items.pendingDismissals = items.pendingDismissals || []; | 647 function(items) { |
| 648 items.notificationsData = items.notificationsData || {}; | 648 items.pendingDismissals = items.pendingDismissals || []; |
| 649 items.notificationsData = items.notificationsData || {}; | |
| 649 | 650 |
| 650 var notificationData = items.notificationsData[notificationId]; | 651 var notificationData = items.notificationsData[notificationId]; |
| 651 | 652 |
| 652 var dismissal = { | 653 var dismissal = { |
| 653 notificationId: notificationId, | 654 notificationId: notificationId, |
| 654 time: Date.now(), | 655 time: Date.now(), |
| 655 parameters: notificationData && notificationData.dismissalParameters | 656 parameters: notificationData && notificationData.dismissalParameters |
| 656 }; | 657 }; |
| 657 items.pendingDismissals.push(dismissal); | 658 items.pendingDismissals.push(dismissal); |
| 658 storage.set({pendingDismissals: items.pendingDismissals}); | 659 chrome.storage.local.set( |
| 659 processPendingDismissals(function(success) { callback(); }); | 660 {pendingDismissals: items.pendingDismissals}); |
| 660 }); | 661 processPendingDismissals(function(success) { callback(); }); |
| 662 }); | |
| 661 }); | 663 }); |
| 662 } | 664 } |
| 663 | 665 |
| 664 /** | 666 /** |
| 665 * Initializes the polling system to start monitoring location and fetching | 667 * Initializes the polling system to start monitoring location and fetching |
| 666 * cards. | 668 * cards. |
| 667 */ | 669 */ |
| 668 function startPollingCards() { | 670 function startPollingCards() { |
| 669 // Create an update timer for a case when for some reason location request | 671 // Create an update timer for a case when for some reason location request |
| 670 // gets stuck. | 672 // gets stuck. |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 724 | 726 |
| 725 /** | 727 /** |
| 726 * Shows or hides the toast. | 728 * Shows or hides the toast. |
| 727 * @param {boolean} visibleRequest true to show the toast and | 729 * @param {boolean} visibleRequest true to show the toast and |
| 728 * false to hide the toast. | 730 * false to hide the toast. |
| 729 * @param {function} callback Called on completion. | 731 * @param {function} callback Called on completion. |
| 730 */ | 732 */ |
| 731 function setToastVisible(visibleRequest, callback) { | 733 function setToastVisible(visibleRequest, callback) { |
| 732 tasks.debugSetStepName( | 734 tasks.debugSetStepName( |
| 733 'setToastVisible-shouldSetToastVisible-getAllNotifications'); | 735 'setToastVisible-shouldSetToastVisible-getAllNotifications'); |
| 734 chrome.notifications.getAll(function(notifications) { | 736 instrumented.notifications.getAll(function(notifications) { |
| 735 // TODO(vadimt): Figure out what to do when notifications are disabled for | 737 // TODO(vadimt): Figure out what to do when notifications are disabled for |
| 736 // our extension. | 738 // our extension. |
| 737 notifications = notifications || {}; | 739 notifications = notifications || {}; |
| 738 | 740 |
| 739 if (visibleRequest != !!notifications[WELCOME_TOAST_NOTIFICATION_ID]) { | 741 if (visibleRequest != !!notifications[WELCOME_TOAST_NOTIFICATION_ID]) { |
| 740 console.log('Action Taken setToastVisible=' + visibleRequest); | 742 console.log('Action Taken setToastVisible=' + visibleRequest); |
| 741 if (visibleRequest) | 743 if (visibleRequest) |
| 742 showWelcomeToast(); | 744 showWelcomeToast(); |
| 743 else | 745 else |
| 744 hideWelcomeToast(); | 746 hideWelcomeToast(); |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 773 | 775 |
| 774 var shouldSetToastVisible = false; | 776 var shouldSetToastVisible = false; |
| 775 var shouldPollCards = false; | 777 var shouldPollCards = false; |
| 776 | 778 |
| 777 if (signedIn) { | 779 if (signedIn) { |
| 778 if (geolocationEnabled) { | 780 if (geolocationEnabled) { |
| 779 if (!userRespondedToToast) { | 781 if (!userRespondedToToast) { |
| 780 // If the user enabled geolocation independently of Google Now, | 782 // If the user enabled geolocation independently of Google Now, |
| 781 // the user has implicitly responded to the toast. | 783 // the user has implicitly responded to the toast. |
| 782 // We do not want to show it again. | 784 // We do not want to show it again. |
| 783 storage.set({userRespondedToToast: true}); | 785 chrome.storage.local.set({userRespondedToToast: true}); |
| 784 } | 786 } |
| 785 | 787 |
| 786 shouldPollCards = true; | 788 shouldPollCards = true; |
| 787 } else { | 789 } else { |
| 788 if (userRespondedToToast) { | 790 if (userRespondedToToast) { |
| 789 recordEvent(GoogleNowEvent.USER_SUPPRESSED); | 791 recordEvent(GoogleNowEvent.USER_SUPPRESSED); |
| 790 } else { | 792 } else { |
| 791 shouldSetToastVisible = true; | 793 shouldSetToastVisible = true; |
| 792 } | 794 } |
| 793 } | 795 } |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 808 * Coordinates the behavior of Google Now for Chrome depending on | 810 * Coordinates the behavior of Google Now for Chrome depending on |
| 809 * Chrome and extension state. | 811 * Chrome and extension state. |
| 810 */ | 812 */ |
| 811 function onStateChange() { | 813 function onStateChange() { |
| 812 tasks.add(STATE_CHANGED_TASK_NAME, function(callback) { | 814 tasks.add(STATE_CHANGED_TASK_NAME, function(callback) { |
| 813 tasks.debugSetStepName('onStateChange-isSignedIn'); | 815 tasks.debugSetStepName('onStateChange-isSignedIn'); |
| 814 authenticationManager.isSignedIn(function(token) { | 816 authenticationManager.isSignedIn(function(token) { |
| 815 var signedIn = !!token && !!NOTIFICATION_CARDS_URL; | 817 var signedIn = !!token && !!NOTIFICATION_CARDS_URL; |
| 816 tasks.debugSetStepName( | 818 tasks.debugSetStepName( |
| 817 'onStateChange-get-googleGeolocationAccessEnabledPref'); | 819 'onStateChange-get-googleGeolocationAccessEnabledPref'); |
| 818 googleGeolocationAccessEnabledPref.get({}, function(prefValue) { | 820 instrumented. |
| 819 var geolocationEnabled = !!prefValue.value; | 821 preferencesPrivate. |
| 820 tasks.debugSetStepName( | 822 googleGeolocationAccessEnabled. |
| 821 'onStateChange-get-userRespondedToToast'); | 823 get({}, function(prefValue) { |
| 822 storage.get('userRespondedToToast', function(items) { | 824 var geolocationEnabled = !!prefValue.value; |
| 823 var userRespondedToToast = !!items.userRespondedToToast; | 825 tasks.debugSetStepName( |
| 824 updateRunningState( | 826 'onStateChange-get-userRespondedToToast'); |
| 825 signedIn, | 827 instrumented.storage.local.get( |
| 826 geolocationEnabled, | 828 'userRespondedToToast', |
| 827 userRespondedToToast, | 829 function(items) { |
| 828 callback); | 830 var userRespondedToToast = !!items.userRespondedToToast; |
| 829 }); | 831 updateRunningState( |
| 832 signedIn, | |
| 833 geolocationEnabled, | |
| 834 userRespondedToToast, | |
| 835 callback); | |
| 836 }); | |
| 830 }); | 837 }); |
|
xiyuan
2013/08/08 23:26:29
nit: this should align with 'get' at line 823 sinc
robliao
2013/08/09 00:44:52
Done.
| |
| 831 }); | 838 }); |
| 832 }); | 839 }); |
| 833 } | 840 } |
| 834 | 841 |
| 835 /** | 842 /** |
| 836 * Displays a toast to the user asking if they want to opt in to receiving | 843 * Displays a toast to the user asking if they want to opt in to receiving |
| 837 * Google Now cards. | 844 * Google Now cards. |
| 838 */ | 845 */ |
| 839 function showWelcomeToast() { | 846 function showWelcomeToast() { |
| 840 recordEvent(GoogleNowEvent.SHOW_WELCOME_TOAST); | 847 recordEvent(GoogleNowEvent.SHOW_WELCOME_TOAST); |
| 841 // TODO(zturner): Localize this once the component extension localization | 848 // TODO(zturner): Localize this once the component extension localization |
| 842 // api is complete. | 849 // api is complete. |
| 843 // TODO(zturner): Add icons. | 850 // TODO(zturner): Add icons. |
| 844 var buttons = [{title: 'Yes'}, {title: 'No'}]; | 851 var buttons = [{title: 'Yes'}, {title: 'No'}]; |
| 845 var options = { | 852 var options = { |
| 846 type: 'basic', | 853 type: 'basic', |
| 847 title: 'Enable Google Now Cards', | 854 title: 'Enable Google Now Cards', |
| 848 message: 'Would you like to be shown Google Now cards?', | 855 message: 'Would you like to be shown Google Now cards?', |
| 849 iconUrl: 'http://www.gstatic.com/googlenow/chrome/default.png', | 856 iconUrl: 'http://www.gstatic.com/googlenow/chrome/default.png', |
| 850 priority: 2, | 857 priority: 2, |
| 851 buttons: buttons | 858 buttons: buttons |
| 852 }; | 859 }; |
| 853 chrome.notifications.create(WELCOME_TOAST_NOTIFICATION_ID, options, | 860 instrumented.notifications.create(WELCOME_TOAST_NOTIFICATION_ID, options, |
| 854 function(notificationId) {}); | 861 function(notificationId) {}); |
| 855 } | 862 } |
| 856 | 863 |
| 857 /** | 864 /** |
| 858 * Hides the welcome toast. | 865 * Hides the welcome toast. |
| 859 */ | 866 */ |
| 860 function hideWelcomeToast() { | 867 function hideWelcomeToast() { |
| 861 chrome.notifications.clear( | 868 chrome.notifications.clear( |
| 862 WELCOME_TOAST_NOTIFICATION_ID, | 869 WELCOME_TOAST_NOTIFICATION_ID, |
| 863 function() {}); | 870 function() {}); |
| 864 } | 871 } |
| 865 | 872 |
| 866 chrome.runtime.onInstalled.addListener(function(details) { | 873 instrumented.runtime.onInstalled.addListener(function(details) { |
| 867 console.log('onInstalled ' + JSON.stringify(details)); | 874 console.log('onInstalled ' + JSON.stringify(details)); |
| 868 if (details.reason != 'chrome_update') { | 875 if (details.reason != 'chrome_update') { |
| 869 initialize(); | 876 initialize(); |
| 870 } | 877 } |
| 871 }); | 878 }); |
| 872 | 879 |
| 873 chrome.runtime.onStartup.addListener(function() { | 880 instrumented.runtime.onStartup.addListener(function() { |
| 874 console.log('onStartup'); | 881 console.log('onStartup'); |
| 875 initialize(); | 882 initialize(); |
| 876 }); | 883 }); |
| 877 | 884 |
| 878 googleGeolocationAccessEnabledPref.onChange.addListener(function(prefValue) { | 885 instrumented. |
| 879 console.log('googleGeolocationAccessEnabledPref onChange ' + prefValue.value); | 886 preferencesPrivate. |
| 880 onStateChange(); | 887 googleGeolocationAccessEnabled. |
| 888 onChange. | |
| 889 addListener(function(prefValue) { | |
| 890 console.log('googleGeolocationAccessEnabled Pref onChange ' + | |
| 891 prefValue.value); | |
| 892 onStateChange(); | |
| 881 }); | 893 }); |
| 882 | 894 |
| 883 authenticationManager.addListener(function() { | 895 authenticationManager.addListener(function() { |
| 884 console.log('signIn State Change'); | 896 console.log('signIn State Change'); |
| 885 onStateChange(); | 897 onStateChange(); |
| 886 }); | 898 }); |
| 887 | 899 |
| 888 chrome.notifications.onClicked.addListener( | 900 instrumented.notifications.onClicked.addListener( |
| 889 function(notificationId) { | 901 function(notificationId) { |
| 890 chrome.metricsPrivate.recordUserAction('GoogleNow.MessageClicked'); | 902 chrome.metricsPrivate.recordUserAction('GoogleNow.MessageClicked'); |
| 891 onNotificationClicked(notificationId, function(actionUrls) { | 903 onNotificationClicked(notificationId, function(actionUrls) { |
| 892 return actionUrls.messageUrl; | 904 return actionUrls.messageUrl; |
| 893 }); | 905 }); |
| 894 }); | 906 }); |
| 895 | 907 |
| 896 chrome.notifications.onButtonClicked.addListener( | 908 instrumented.notifications.onButtonClicked.addListener( |
| 897 function(notificationId, buttonIndex) { | 909 function(notificationId, buttonIndex) { |
| 898 if (notificationId == WELCOME_TOAST_NOTIFICATION_ID) { | 910 if (notificationId == WELCOME_TOAST_NOTIFICATION_ID) { |
| 899 onToastNotificationClicked(buttonIndex); | 911 onToastNotificationClicked(buttonIndex); |
| 900 } else { | 912 } else { |
| 901 chrome.metricsPrivate.recordUserAction( | 913 chrome.metricsPrivate.recordUserAction( |
| 902 'GoogleNow.ButtonClicked' + buttonIndex); | 914 'GoogleNow.ButtonClicked' + buttonIndex); |
| 903 onNotificationClicked(notificationId, function(actionUrls) { | 915 onNotificationClicked(notificationId, function(actionUrls) { |
| 904 if (!Array.isArray(actionUrls.buttonUrls)) | 916 if (!Array.isArray(actionUrls.buttonUrls)) |
| 905 return undefined; | 917 return undefined; |
| 906 | 918 |
| 907 return actionUrls.buttonUrls[buttonIndex]; | 919 return actionUrls.buttonUrls[buttonIndex]; |
| 908 }); | 920 }); |
| 909 } | 921 } |
| 910 }); | 922 }); |
| 911 | 923 |
| 912 chrome.notifications.onClosed.addListener(onNotificationClosed); | 924 instrumented.notifications.onClosed.addListener(onNotificationClosed); |
| 913 | 925 |
| 914 chrome.location.onLocationUpdate.addListener(function(position) { | 926 instrumented.location.onLocationUpdate.addListener(function(position) { |
| 915 recordEvent(GoogleNowEvent.LOCATION_UPDATE); | 927 recordEvent(GoogleNowEvent.LOCATION_UPDATE); |
| 916 updateNotificationsCards(position); | 928 updateNotificationsCards(position); |
| 917 }); | 929 }); |
| 918 | 930 |
| 919 chrome.omnibox.onInputEntered.addListener(function(text) { | 931 instrumented.omnibox.onInputEntered.addListener(function(text) { |
| 920 localStorage['server_url'] = NOTIFICATION_CARDS_URL = text; | 932 localStorage['server_url'] = NOTIFICATION_CARDS_URL = text; |
| 921 initialize(); | 933 initialize(); |
| 922 }); | 934 }); |
| OLD | NEW |