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) { |
vadimt
2013/08/08 01:15:10
You could also add newline before ['notificationsD
robliao
2013/08/08 17:43:31
I would rather pay for the indentation here rather
vadimt
2013/08/08 18:19:25
You can fit the whole array AND "function(items) {
robliao
2013/08/08 21:35:35
The right thing to do here is to keep the separate
| |
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}); |
vadimt
2013/08/08 01:15:10
Nothing still prevents from having googleGeolocati
robliao
2013/08/08 17:43:31
True, but it wasn't universally applicable (e.g. c
| |
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 }); |
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) { |
vadimt
2013/08/08 01:15:10
So, Chrome recognizes this call and loads the page
robliao
2013/08/08 17:43:31
It appears so. Right after launch the event page i
vadimt
2013/08/08 18:19:25
I've started a thread to clarify this.
| |
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() { |
vadimt
2013/08/08 01:15:10
Same here.
robliao
2013/08/08 17:43:31
See above
On 2013/08/08 01:15:10, vadimt wrote:
| |
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 |