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 Utility objects and functions for Google Now extension. | 8 * @fileoverview Utility objects and functions for Google Now extension. |
9 * Most important entities here: | 9 * Most important entities here: |
10 * (1) 'wrapper' is a module used to add error handling and other services to | 10 * (1) 'wrapper' is a module used to add error handling and other services to |
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
316 verify(!isInWrappedCallback, 'Re-entering instrumented callback'); | 316 verify(!isInWrappedCallback, 'Re-entering instrumented callback'); |
317 isInWrappedCallback = true; | 317 isInWrappedCallback = true; |
318 | 318 |
319 if (!opt_isEventListener) | 319 if (!opt_isEventListener) |
320 delete pendingCallbacks[callbackId]; | 320 delete pendingCallbacks[callbackId]; |
321 | 321 |
322 if (wrapperPluginInstance) | 322 if (wrapperPluginInstance) |
323 wrapperPluginInstance.prologue(); | 323 wrapperPluginInstance.prologue(); |
324 | 324 |
325 // Call the original callback. | 325 // Call the original callback. |
326 callback.apply(null, arguments); | 326 var returnValue = callback.apply(null, arguments); |
327 | 327 |
328 if (wrapperPluginInstance) | 328 if (wrapperPluginInstance) |
329 wrapperPluginInstance.epilogue(); | 329 wrapperPluginInstance.epilogue(); |
330 | 330 |
331 verify(isInWrappedCallback, | 331 verify(isInWrappedCallback, |
332 'Instrumented callback is not instrumented upon exit'); | 332 'Instrumented callback is not instrumented upon exit'); |
333 isInWrappedCallback = false; | 333 isInWrappedCallback = false; |
334 | |
335 return returnValue; | |
334 } catch (error) { | 336 } catch (error) { |
335 reportError(error); | 337 reportError(error); |
336 } | 338 } |
337 }; | 339 }; |
338 } | 340 } |
339 | 341 |
340 /** | 342 /** |
341 * Returns an instrumented function. | 343 * Returns an instrumented function. |
342 * @param {!Array.<string>} functionIdentifierParts Path to the chrome.* | 344 * @param {!Array.<string>} functionIdentifierParts Path to the chrome.* |
343 * function. | 345 * function. |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
427 checkInWrappedCallback: checkInWrappedCallback, | 429 checkInWrappedCallback: checkInWrappedCallback, |
428 debugGetStateString: debugGetStateString | 430 debugGetStateString: debugGetStateString |
429 }; | 431 }; |
430 })(); | 432 })(); |
431 | 433 |
432 wrapper.instrumentChromeApiFunction('alarms.get', 1); | 434 wrapper.instrumentChromeApiFunction('alarms.get', 1); |
433 wrapper.instrumentChromeApiFunction('alarms.onAlarm.addListener', 0); | 435 wrapper.instrumentChromeApiFunction('alarms.onAlarm.addListener', 0); |
434 wrapper.instrumentChromeApiFunction('identity.getAuthToken', 1); | 436 wrapper.instrumentChromeApiFunction('identity.getAuthToken', 1); |
435 wrapper.instrumentChromeApiFunction('identity.onSignInChanged.addListener', 0); | 437 wrapper.instrumentChromeApiFunction('identity.onSignInChanged.addListener', 0); |
436 wrapper.instrumentChromeApiFunction('identity.removeCachedAuthToken', 1); | 438 wrapper.instrumentChromeApiFunction('identity.removeCachedAuthToken', 1); |
439 wrapper.instrumentChromeApiFunction('storage.local.get', 1); | |
437 wrapper.instrumentChromeApiFunction('webstorePrivate.getBrowserLogin', 0); | 440 wrapper.instrumentChromeApiFunction('webstorePrivate.getBrowserLogin', 0); |
438 | 441 |
439 /** | 442 /** |
440 * Promise adapter for all JS promises to the task manager. | 443 * Promise adapter for all JS promises to the task manager. |
441 */ | 444 */ |
442 function registerPromiseAdapter() { | 445 function registerPromiseAdapter() { |
443 var originalThen = Promise.prototype.then; | 446 var originalThen = Promise.prototype.then; |
444 var originalCatch = Promise.prototype.catch; | 447 var originalCatch = Promise.prototype.catch; |
445 | 448 |
446 /** | 449 /** |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
612 return { | 615 return { |
613 handleThen: handleThen, | 616 handleThen: handleThen, |
614 handleCatch: handleCatch | 617 handleCatch: handleCatch |
615 }; | 618 }; |
616 } | 619 } |
617 } | 620 } |
618 | 621 |
619 registerPromiseAdapter(); | 622 registerPromiseAdapter(); |
620 | 623 |
621 /** | 624 /** |
625 * Control promise rejection. | |
626 * @enum {boolean} | |
627 */ | |
628 var PromiseRejection = { | |
629 /** Disallow promise rejection */ | |
630 DISALLOW: false, | |
631 /** Allow promise rejection */ | |
632 ALLOW: true | |
633 }; | |
634 | |
635 /** | |
636 * Provides the promise equivalent of instrumented.storage.local.get. | |
637 * @param {Object} defaultStorageObject Default storage object to fill. | |
638 * @param {boolean} opt_allowPromiseRejection If PromiseRejection.ALLOW, | |
rgustafson
2014/02/27 21:32:10
document param as optional
robliao
2014/02/27 23:52:36
Done.
| |
639 * allow promise rejection on errors, otherwise the default storage | |
640 * object is resolved. | |
641 * @return {Promise} A promise that fills the default storage object. On | |
642 * failure, if promise rejection is allowed, the promise is rejected, | |
643 * otherwise it is resolved to the default storage object. | |
644 */ | |
645 function fillFromChromeLocalStorage( | |
646 defaultStorageObject, | |
647 opt_allowPromiseRejection) { | |
648 return new Promise(function(resolve, reject) { | |
649 instrumented.storage.local.get(defaultStorageObject, function(items) { | |
650 if (items) { | |
651 resolve(items); | |
652 } else if (opt_allowPromiseRejection === PromiseRejection.ALLOW) { | |
vadimt
2014/02/27 20:20:36
Why not "if (opt_allowPromiseRejection)"?
robliao
2014/02/27 23:52:36
We're comparing against an enum, so we should do a
vadimt
2014/02/28 20:21:05
You don't use the fact that enum values are boolea
robliao
2014/02/28 20:39:49
We can use the number, but for enums it shouldn't
| |
653 reject(); | |
654 } else { | |
655 resolve(defaultStorageObject); | |
656 } | |
657 }); | |
658 }); | |
659 } | |
660 | |
661 /** | |
622 * Builds the object to manage tasks (mutually exclusive chains of events). | 662 * Builds the object to manage tasks (mutually exclusive chains of events). |
623 * @param {function(string, string): boolean} areConflicting Function that | 663 * @param {function(string, string): boolean} areConflicting Function that |
624 * checks if a new task can't be added to a task queue that contains an | 664 * checks if a new task can't be added to a task queue that contains an |
625 * existing task. | 665 * existing task. |
626 * @return {Object} Task manager interface. | 666 * @return {Object} Task manager interface. |
627 */ | 667 */ |
628 function buildTaskManager(areConflicting) { | 668 function buildTaskManager(areConflicting) { |
629 /** | 669 /** |
630 * Queue of scheduled tasks. The first element, if present, corresponds to the | 670 * Queue of scheduled tasks. The first element, if present, corresponds to the |
631 * currently running task. | 671 * currently running task. |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
852 chrome.alarms.clear(alarmName); | 892 chrome.alarms.clear(alarmName); |
853 chrome.storage.local.remove(currentDelayStorageKey); | 893 chrome.storage.local.remove(currentDelayStorageKey); |
854 } | 894 } |
855 | 895 |
856 /** | 896 /** |
857 * Plans for the next attempt. | 897 * Plans for the next attempt. |
858 * @param {function()} callback Completion callback. It will be invoked after | 898 * @param {function()} callback Completion callback. It will be invoked after |
859 * the planning is done. | 899 * the planning is done. |
860 */ | 900 */ |
861 function planForNext(callback) { | 901 function planForNext(callback) { |
862 instrumented.storage.local.get(currentDelayStorageKey, function(items) { | 902 var request = {}; |
863 if (!items) { | 903 request[currentDelayStorageKey] = maximumDelaySeconds; |
vadimt
2014/02/27 20:20:36
This changes the semantics. If items retrieved, bu
robliao
2014/02/27 23:52:36
Gotcha. Fixed.
On 2014/02/27 20:20:36, vadimt wrot
| |
864 items = {}; | 904 fillFromChromeLocalStorage(request).then(function(items) { |
865 items[currentDelayStorageKey] = maximumDelaySeconds; | |
866 } | |
867 console.log('planForNext-get-storage ' + JSON.stringify(items)); | 905 console.log('planForNext-get-storage ' + JSON.stringify(items)); |
868 scheduleNextAttempt(items[currentDelayStorageKey]); | 906 scheduleNextAttempt(items[currentDelayStorageKey]); |
869 callback(); | 907 callback(); |
870 }); | 908 }); |
871 } | 909 } |
872 | 910 |
873 instrumented.alarms.onAlarm.addListener(function(alarm) { | 911 instrumented.alarms.onAlarm.addListener(function(alarm) { |
874 if (alarm.name == alarmName) | 912 if (alarm.name == alarmName) |
875 isRunning(function(running) { | 913 isRunning(function(running) { |
876 if (running) | 914 if (running) |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
950 function addListener(callback) { | 988 function addListener(callback) { |
951 listeners.push(callback); | 989 listeners.push(callback); |
952 } | 990 } |
953 | 991 |
954 /** | 992 /** |
955 * Checks if the last signed in state matches the current one. | 993 * Checks if the last signed in state matches the current one. |
956 * If it doesn't, it notifies the listeners of the change. | 994 * If it doesn't, it notifies the listeners of the change. |
957 */ | 995 */ |
958 function checkAndNotifyListeners() { | 996 function checkAndNotifyListeners() { |
959 isSignedIn().then(function(signedIn) { | 997 isSignedIn().then(function(signedIn) { |
960 instrumented.storage.local.get('lastSignedInState', function(items) { | 998 fillFromChromeLocalStorage({lastSignedInState: undefined}) |
961 items = items || {}; | 999 .then(function(items) { |
962 if (items.lastSignedInState != signedIn) { | 1000 if (items.lastSignedInState != signedIn) { |
963 chrome.storage.local.set( | 1001 chrome.storage.local.set( |
964 {lastSignedInState: signedIn}); | 1002 {lastSignedInState: signedIn}); |
965 listeners.forEach(function(callback) { | 1003 listeners.forEach(function(callback) { |
966 callback(); | 1004 callback(); |
967 }); | 1005 }); |
968 } | 1006 } |
1007 }); | |
969 }); | 1008 }); |
970 }); | |
971 } | 1009 } |
972 | 1010 |
973 instrumented.identity.onSignInChanged.addListener(function() { | 1011 instrumented.identity.onSignInChanged.addListener(function() { |
974 checkAndNotifyListeners(); | 1012 checkAndNotifyListeners(); |
975 }); | 1013 }); |
976 | 1014 |
977 instrumented.alarms.onAlarm.addListener(function(alarm) { | 1015 instrumented.alarms.onAlarm.addListener(function(alarm) { |
978 if (alarm.name == alarmName) | 1016 if (alarm.name == alarmName) |
979 checkAndNotifyListeners(); | 1017 checkAndNotifyListeners(); |
980 }); | 1018 }); |
981 | 1019 |
982 // Poll for the sign in state every hour. | 1020 // Poll for the sign in state every hour. |
983 // One hour is just an arbitrary amount of time chosen. | 1021 // One hour is just an arbitrary amount of time chosen. |
984 chrome.alarms.create(alarmName, {periodInMinutes: 60}); | 1022 chrome.alarms.create(alarmName, {periodInMinutes: 60}); |
985 | 1023 |
986 return { | 1024 return { |
987 addListener: addListener, | 1025 addListener: addListener, |
988 getAuthToken: getAuthToken, | 1026 getAuthToken: getAuthToken, |
989 isSignedIn: isSignedIn, | 1027 isSignedIn: isSignedIn, |
990 removeToken: removeToken | 1028 removeToken: removeToken |
991 }; | 1029 }; |
992 } | 1030 } |
OLD | NEW |