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 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 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 186 | 186 |
| 187 // Limiting 1 error report per background page load. | 187 // Limiting 1 error report per background page load. |
| 188 var errorReported = false; | 188 var errorReported = false; |
| 189 | 189 |
| 190 /** | 190 /** |
| 191 * Reports an error to the server and the user, as appropriate. | 191 * Reports an error to the server and the user, as appropriate. |
| 192 * @param {Error} error Error to report. | 192 * @param {Error} error Error to report. |
| 193 */ | 193 */ |
| 194 function reportError(error) { | 194 function reportError(error) { |
| 195 var message = 'Critical error:\n' + error.stack; | 195 var message = 'Critical error:\n' + error.stack; |
| 196 if (isInDebugMode()) | 196 if (isInDebugMode()) |
|
robliao
2014/05/05 17:24:30
This is a codesync artifact.
| |
| 197 console.error(message); | 197 console.error(message); |
| 198 | 198 |
| 199 if (!errorReported) { | 199 if (!errorReported) { |
| 200 errorReported = true; | 200 errorReported = true; |
| 201 chrome.metricsPrivate.getIsCrashReportingEnabled(function(isEnabled) { | 201 chrome.metricsPrivate.getIsCrashReportingEnabled(function(isEnabled) { |
| 202 if (isEnabled) | 202 if (isEnabled) |
| 203 sendErrorReport(error); | 203 sendErrorReport(error); |
| 204 if (isInDebugMode()) | 204 if (isInDebugMode()) |
| 205 alert(message); | 205 alert(message); |
| 206 }); | 206 }); |
| (...skipping 665 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 872 * @param {function(boolean)} callback The function's boolean parameter is | 872 * @param {function(boolean)} callback The function's boolean parameter is |
| 873 * true if the attempt manager has started, false otherwise. | 873 * true if the attempt manager has started, false otherwise. |
| 874 */ | 874 */ |
| 875 function isRunning(callback) { | 875 function isRunning(callback) { |
| 876 instrumented.alarms.get(alarmName, function(alarmInfo) { | 876 instrumented.alarms.get(alarmName, function(alarmInfo) { |
| 877 callback(!!alarmInfo); | 877 callback(!!alarmInfo); |
| 878 }); | 878 }); |
| 879 } | 879 } |
| 880 | 880 |
| 881 /** | 881 /** |
| 882 * Schedules next attempt. | 882 * Schedules the alarm with a random factor to reduce the chance that all |
| 883 * @param {number=} opt_previousDelaySeconds Previous delay in a sequence of | 883 * clients will fire their timers at the same time. |
| 884 * retry attempts, if specified. Not specified for scheduling first retry | 884 * @param {number} durationSeconds Number of seconds before firing the alarm. |
| 885 * in the exponential sequence. | |
| 886 */ | 885 */ |
| 887 function scheduleNextAttempt(opt_previousDelaySeconds) { | 886 function scheduleAlarm(durationSeconds) { |
| 888 var base = opt_previousDelaySeconds ? opt_previousDelaySeconds * 2 : | 887 var randomizedRetryDuration = |
| 889 initialDelaySeconds; | 888 Math.min(durationSeconds * (1 + 0.2 * Math.random()), |
| 890 var newRetryDelaySeconds = | 889 maximumDelaySeconds); |
| 891 Math.min(base * (1 + 0.2 * Math.random()), maximumDelaySeconds); | |
| 892 | 890 |
| 893 createAlarm(newRetryDelaySeconds); | 891 createAlarm(randomizedRetryDuration); |
| 894 | 892 |
| 895 var items = {}; | 893 var items = {}; |
| 896 items[currentDelayStorageKey] = newRetryDelaySeconds; | 894 items[currentDelayStorageKey] = randomizedRetryDuration; |
| 897 chrome.storage.local.set(items); | 895 chrome.storage.local.set(items); |
| 898 } | 896 } |
| 899 | 897 |
| 900 /** | 898 /** |
| 901 * Starts repeated attempts. | 899 * Starts repeated attempts. |
| 902 * @param {number=} opt_firstDelaySeconds Time until the first attempt, if | 900 * @param {number=} opt_firstDelaySeconds Time until the first attempt, if |
| 903 * specified. Otherwise, initialDelaySeconds will be used for the first | 901 * specified. Otherwise, initialDelaySeconds will be used for the first |
| 904 * attempt. | 902 * attempt. |
| 905 */ | 903 */ |
| 906 function start(opt_firstDelaySeconds) { | 904 function start(opt_firstDelaySeconds) { |
| 907 if (opt_firstDelaySeconds) { | 905 if (opt_firstDelaySeconds) { |
| 908 createAlarm(opt_firstDelaySeconds); | 906 createAlarm(opt_firstDelaySeconds); |
| 909 chrome.storage.local.remove(currentDelayStorageKey); | 907 chrome.storage.local.remove(currentDelayStorageKey); |
| 910 } else { | 908 } else { |
| 911 scheduleNextAttempt(); | 909 scheduleAlarm(initialDelaySeconds); |
| 912 } | 910 } |
| 913 } | 911 } |
| 914 | 912 |
| 915 /** | 913 /** |
| 916 * Stops repeated attempts. | 914 * Stops repeated attempts. |
| 917 */ | 915 */ |
| 918 function stop() { | 916 function stop() { |
| 919 chrome.alarms.clear(alarmName); | 917 chrome.alarms.clear(alarmName); |
| 920 chrome.storage.local.remove(currentDelayStorageKey); | 918 chrome.storage.local.remove(currentDelayStorageKey); |
| 921 } | 919 } |
| 922 | 920 |
| 923 /** | 921 /** |
| 924 * Plans for the next attempt. | 922 * Schedules an exponential backoff retry. |
| 925 * @param {function()} callback Completion callback. It will be invoked after | 923 * @return {Promise} A promise to schedule the retry. |
| 926 * the planning is done. | |
| 927 */ | 924 */ |
| 928 function planForNext(callback) { | 925 function scheduleRetry() { |
| 929 var request = {}; | 926 var request = {}; |
| 930 request[currentDelayStorageKey] = undefined; | 927 request[currentDelayStorageKey] = undefined; |
| 931 fillFromChromeLocalStorage(request, PromiseRejection.ALLOW) | 928 return fillFromChromeLocalStorage(request, PromiseRejection.ALLOW) |
| 932 .catch(function() { | 929 .catch(function() { |
| 933 request[currentDelayStorageKey] = maximumDelaySeconds; | 930 request[currentDelayStorageKey] = maximumDelaySeconds; |
| 934 return Promise.resolve(request); | 931 return Promise.resolve(request); |
| 935 }).then(function(items) { | 932 }) |
| 936 console.log('planForNext-get-storage ' + JSON.stringify(items)); | 933 .then(function(items) { |
| 937 scheduleNextAttempt(items[currentDelayStorageKey]); | 934 console.log('scheduleRetry-get-storage ' + JSON.stringify(items)); |
| 938 callback(); | 935 var retrySeconds = initialDelaySeconds; |
| 936 if (items[currentDelayStorageKey]) { | |
| 937 retrySeconds = items[currentDelayStorageKey] * 2; | |
| 938 } | |
| 939 scheduleAlarm(retrySeconds); | |
| 939 }); | 940 }); |
| 940 } | 941 } |
| 941 | 942 |
| 942 instrumented.alarms.onAlarm.addListener(function(alarm) { | 943 instrumented.alarms.onAlarm.addListener(function(alarm) { |
| 943 if (alarm.name == alarmName) | 944 if (alarm.name == alarmName) |
| 944 isRunning(function(running) { | 945 isRunning(function(running) { |
| 945 if (running) | 946 if (running) |
| 946 attempt(); | 947 attempt(); |
| 947 }); | 948 }); |
| 948 }); | 949 }); |
| 949 | 950 |
| 950 return { | 951 return { |
| 951 start: start, | 952 start: start, |
| 952 planForNext: planForNext, | 953 scheduleRetry: scheduleRetry, |
| 953 stop: stop, | 954 stop: stop, |
| 954 isRunning: isRunning | 955 isRunning: isRunning |
| 955 }; | 956 }; |
| 956 } | 957 } |
| 957 | 958 |
| 958 // TODO(robliao): Use signed-in state change watch API when it's available. | 959 // TODO(robliao): Use signed-in state change watch API when it's available. |
| 959 /** | 960 /** |
| 960 * Wraps chrome.identity to provide limited listening support for | 961 * Wraps chrome.identity to provide limited listening support for |
| 961 * the sign in state by polling periodically for the auth token. | 962 * the sign in state by polling periodically for the auth token. |
| 962 * @return {Object} The Authentication Manager interface. | 963 * @return {Object} The Authentication Manager interface. |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1052 // One hour is just an arbitrary amount of time chosen. | 1053 // One hour is just an arbitrary amount of time chosen. |
| 1053 chrome.alarms.create(alarmName, {periodInMinutes: 60}); | 1054 chrome.alarms.create(alarmName, {periodInMinutes: 60}); |
| 1054 | 1055 |
| 1055 return { | 1056 return { |
| 1056 addListener: addListener, | 1057 addListener: addListener, |
| 1057 getAuthToken: getAuthToken, | 1058 getAuthToken: getAuthToken, |
| 1058 isSignedIn: isSignedIn, | 1059 isSignedIn: isSignedIn, |
| 1059 removeToken: removeToken | 1060 removeToken: removeToken |
| 1060 }; | 1061 }; |
| 1061 } | 1062 } |
| OLD | NEW |