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 // TODO(vadimt): Remove alerts. | 7 // TODO(vadimt): Remove alerts. |
| 8 | 8 |
| 9 /** | 9 /** |
| 10 * @fileoverview Utility objects and functions for Google Now extension. | 10 * @fileoverview Utility objects and functions for Google Now extension. |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 75 */ | 75 */ |
| 76 var pendingCallbacks = {}; | 76 var pendingCallbacks = {}; |
| 77 | 77 |
| 78 /** | 78 /** |
| 79 * True if currently executed code is a part of a task. | 79 * True if currently executed code is a part of a task. |
| 80 * @type {boolean} | 80 * @type {boolean} |
| 81 */ | 81 */ |
| 82 var isInTask = false; | 82 var isInTask = false; |
| 83 | 83 |
| 84 /** | 84 /** |
| 85 * True if currently executed code runs in an instrumented callback. | |
| 86 * @type {boolean} | |
| 87 */ | |
| 88 var isInInstrumentedCallback = false; | |
| 89 | |
| 90 /** | |
| 91 * Checks that we run in an instrumented callback. | |
| 92 */ | |
| 93 function checkInInstrumentedCallback() { | |
| 94 if (!isInInstrumentedCallback) { | |
| 95 // Cannot use verify() since no one will catch the exception. | |
| 96 // This alert will detect bugs at the development stage, and is very | |
| 97 // unlikely to be seen by users. | |
| 98 var error = 'Not in instrumented callback: ' + new Error().stack; | |
| 99 console.error(error); | |
| 100 alert(error); | |
|
arv (Not doing code reviews)
2013/08/02 22:41:52
why both alert and console.log?
vadimt
2013/08/02 22:47:04
Alert to know that this has happened at all.
conso
| |
| 101 } | |
| 102 } | |
| 103 | |
| 104 /** | |
| 85 * Starts the first queued task. | 105 * Starts the first queued task. |
| 86 */ | 106 */ |
| 87 function startFirst() { | 107 function startFirst() { |
| 88 verify(queue.length >= 1, 'startFirst: queue is empty'); | 108 verify(queue.length >= 1, 'startFirst: queue is empty'); |
| 89 verify(!isInTask, 'startFirst: already in task'); | 109 verify(!isInTask, 'startFirst: already in task'); |
| 90 isInTask = true; | 110 isInTask = true; |
| 91 | 111 |
| 92 // Start the oldest queued task, but don't remove it from the queue. | 112 // Start the oldest queued task, but don't remove it from the queue. |
| 93 verify( | 113 verify( |
| 94 taskPendingCallbackCount == 0, | 114 taskPendingCallbackCount == 0, |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 126 | 146 |
| 127 /** | 147 /** |
| 128 * Adds a new task. If another task is not running, runs the task immediately. | 148 * Adds a new task. If another task is not running, runs the task immediately. |
| 129 * If any task in the queue is not compatible with the task, ignores the new | 149 * If any task in the queue is not compatible with the task, ignores the new |
| 130 * task. Otherwise, stores the task for future execution. | 150 * task. Otherwise, stores the task for future execution. |
| 131 * @param {string} taskName Name of the task. | 151 * @param {string} taskName Name of the task. |
| 132 * @param {function(function())} task Function to run. Takes a callback | 152 * @param {function(function())} task Function to run. Takes a callback |
| 133 * parameter. Call this callback on completion. | 153 * parameter. Call this callback on completion. |
| 134 */ | 154 */ |
| 135 function add(taskName, task) { | 155 function add(taskName, task) { |
| 156 checkInInstrumentedCallback(); | |
| 136 console.log('Adding task ' + taskName); | 157 console.log('Adding task ' + taskName); |
| 137 if (!canQueue(taskName)) | 158 if (!canQueue(taskName)) |
| 138 return; | 159 return; |
| 139 | 160 |
| 140 queue.push({name: taskName, task: task}); | 161 queue.push({name: taskName, task: task}); |
| 141 | 162 |
| 142 if (queue.length == 1) { | 163 if (queue.length == 1) { |
| 143 startFirst(); | 164 startFirst(); |
| 144 } | 165 } |
| 145 } | 166 } |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 200 | 221 |
| 201 /** | 222 /** |
| 202 * Unique ID of the next callback. | 223 * Unique ID of the next callback. |
| 203 * @type {number} | 224 * @type {number} |
| 204 */ | 225 */ |
| 205 var nextCallbackId = 0; | 226 var nextCallbackId = 0; |
| 206 | 227 |
| 207 /** | 228 /** |
| 208 * Adds error processing to an API callback. | 229 * Adds error processing to an API callback. |
| 209 * @param {Function} callback Callback to instrument. | 230 * @param {Function} callback Callback to instrument. |
| 210 * @param {boolean=} opt_dontRequire True if the callback is not required to | 231 * @param {boolean=} opt_isEventListener True if the callback is an event |
| 211 * be invoked. | 232 * listener. |
| 212 * @return {Function} Instrumented callback. | 233 * @return {Function} Instrumented callback. |
| 213 */ | 234 */ |
| 214 function wrapCallback(callback, opt_dontRequire) { | 235 function wrapCallback(callback, opt_isEventListener) { |
| 215 verify(!(opt_dontRequire && isInTask), 'Unrequired callback in a task.'); | 236 verify(!(opt_isEventListener && isInTask), |
| 237 'Unrequired callback in a task.'); | |
| 216 var callbackId = nextCallbackId++; | 238 var callbackId = nextCallbackId++; |
| 217 var isTaskCallback = isInTask; | 239 var isTaskCallback = isInTask; |
| 218 if (isTaskCallback) | 240 if (isTaskCallback) |
| 219 ++taskPendingCallbackCount; | 241 ++taskPendingCallbackCount; |
| 220 if (!opt_dontRequire) | 242 if (!opt_isEventListener) { |
| 243 checkInInstrumentedCallback(); | |
| 221 pendingCallbacks[callbackId] = new Error().stack; | 244 pendingCallbacks[callbackId] = new Error().stack; |
| 245 } | |
| 222 | 246 |
| 223 return function() { | 247 return function() { |
| 224 // This is the wrapper for the callback. | 248 // This is the wrapper for the callback. |
| 225 try { | 249 try { |
| 226 if (isTaskCallback) { | 250 if (isTaskCallback) { |
| 227 verify(!isInTask, 'wrapCallback: already in task'); | 251 verify(!isInTask, 'wrapCallback: already in task'); |
| 228 isInTask = true; | 252 isInTask = true; |
| 229 } | 253 } |
| 230 if (!opt_dontRequire) | 254 if (!opt_isEventListener) |
| 231 delete pendingCallbacks[callbackId]; | 255 delete pendingCallbacks[callbackId]; |
| 232 | 256 |
| 233 // Call the original callback. | 257 // Call the original callback. |
| 258 verify(!isInInstrumentedCallback, 'Re-entering instrumented callback'); | |
| 259 isInInstrumentedCallback = true; | |
| 234 callback.apply(null, arguments); | 260 callback.apply(null, arguments); |
| 261 verify(isInInstrumentedCallback, | |
| 262 'Instrumented callback is not instrumented upon exit'); | |
| 263 isInInstrumentedCallback = false; | |
| 235 | 264 |
| 236 if (isTaskCallback) { | 265 if (isTaskCallback) { |
| 237 verify(isInTask, 'wrapCallback: not in task at exit'); | 266 verify(isInTask, 'wrapCallback: not in task at exit'); |
| 238 isInTask = false; | 267 isInTask = false; |
| 239 if (--taskPendingCallbackCount == 0) | 268 if (--taskPendingCallbackCount == 0) |
| 240 finish(); | 269 finish(); |
| 241 } | 270 } |
| 242 } catch (error) { | 271 } catch (error) { |
| 243 var message = 'Uncaught exception:\n' + error.stack; | 272 var message = 'Uncaught exception:\n' + error.stack; |
| 244 console.error(message); | 273 console.error(message); |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 275 if (typeof callback != 'function') { | 304 if (typeof callback != 'function') { |
| 276 alert('Argument ' + callbackParameter + ' of ' + functionName + | 305 alert('Argument ' + callbackParameter + ' of ' + functionName + |
| 277 ' is not a function'); | 306 ' is not a function'); |
| 278 } | 307 } |
| 279 arguments[callbackParameter] = wrapCallback( | 308 arguments[callbackParameter] = wrapCallback( |
| 280 callback, functionName == 'addListener'); | 309 callback, functionName == 'addListener'); |
| 281 return originalFunction.apply(namespace, arguments); | 310 return originalFunction.apply(namespace, arguments); |
| 282 }; | 311 }; |
| 283 } | 312 } |
| 284 | 313 |
| 314 instrumentApiFunction(chrome.alarms, 'get', 1); | |
| 285 instrumentApiFunction(chrome.alarms.onAlarm, 'addListener', 0); | 315 instrumentApiFunction(chrome.alarms.onAlarm, 'addListener', 0); |
| 316 instrumentApiFunction(chrome.identity, 'getAuthToken', 1); | |
| 286 instrumentApiFunction(chrome.runtime.onSuspend, 'addListener', 0); | 317 instrumentApiFunction(chrome.runtime.onSuspend, 'addListener', 0); |
| 287 | 318 |
| 288 chrome.runtime.onSuspend.addListener(function() { | 319 chrome.runtime.onSuspend.addListener(function() { |
| 289 var stringifiedPendingCallbacks = JSON.stringify(pendingCallbacks); | 320 var stringifiedPendingCallbacks = JSON.stringify(pendingCallbacks); |
| 290 verify( | 321 verify( |
| 291 queue.length == 0 && stringifiedPendingCallbacks == '{}', | 322 queue.length == 0 && stringifiedPendingCallbacks == '{}', |
| 292 'Incomplete task or pending callbacks when unloading event page,' + | 323 'Incomplete task or pending callbacks when unloading event page,' + |
| 293 ' queue = ' + JSON.stringify(queue) + | 324 ' queue = ' + JSON.stringify(queue) + |
| 294 ', pendingCallbacks = ' + stringifiedPendingCallbacks); | 325 ', pendingCallbacks = ' + stringifiedPendingCallbacks); |
| 295 }); | 326 }); |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 487 // Poll for the sign in state every hour. | 518 // Poll for the sign in state every hour. |
| 488 // One hour is just an arbitrary amount of time chosen. | 519 // One hour is just an arbitrary amount of time chosen. |
| 489 chrome.alarms.create(alarmName, {periodInMinutes: 60}); | 520 chrome.alarms.create(alarmName, {periodInMinutes: 60}); |
| 490 | 521 |
| 491 return { | 522 return { |
| 492 addListener: addListener, | 523 addListener: addListener, |
| 493 isSignedIn: isSignedIn, | 524 isSignedIn: isSignedIn, |
| 494 removeToken: removeToken | 525 removeToken: removeToken |
| 495 }; | 526 }; |
| 496 } | 527 } |
| OLD | NEW |