OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 var GetAvailability = requireNative('v8_context').GetAvailability; | |
6 var GetGlobal = requireNative('sendRequest').GetGlobal; | |
7 | |
8 // Utility for setting chrome.*.lastError. | |
9 // | |
10 // A utility here is useful for two reasons: | |
11 // 1. For backwards compatibility we need to set chrome.extension.lastError, | |
12 // but not all contexts actually have access to the extension namespace. | |
13 // 2. When calling across contexts, the global object that gets lastError set | |
14 // needs to be that of the caller. We force callers to explicitly specify | |
15 // the chrome object to try to prevent bugs here. | |
16 | |
17 /** | |
18 * Sets the last error for |name| on |targetChrome| to |message| with an | |
19 * optional |stack|. | |
20 */ | |
21 function set(name, message, stack, targetChrome) { | |
22 var errorMessage = name + ': ' + message; | |
23 if (stack != null && stack != '') | |
24 errorMessage += '\n' + stack; | |
25 | |
26 if (!targetChrome) | |
27 throw new Error('No chrome object to set error: ' + errorMessage); | |
28 clear(targetChrome); // in case somebody has set a sneaky getter/setter | |
29 | |
30 var errorObject = { message: message }; | |
31 if (GetAvailability('extension.lastError').is_available) | |
32 targetChrome.extension.lastError = errorObject; | |
33 | |
34 assertRuntimeIsAvailable(); | |
35 | |
36 // We check to see if developers access runtime.lastError in order to decide | |
37 // whether or not to log it in the (error) console. | |
38 privates(targetChrome.runtime).accessedLastError = false; | |
39 $Object.defineProperty(targetChrome.runtime, 'lastError', { | |
40 configurable: true, | |
41 get: function() { | |
42 privates(targetChrome.runtime).accessedLastError = true; | |
43 return errorObject; | |
44 }, | |
45 set: function(error) { | |
46 errorObject = errorObject; | |
47 }}); | |
48 }; | |
49 | |
50 /** | |
51 * Check if anyone has checked chrome.runtime.lastError since it was set. | |
52 * @param {Object} targetChrome the Chrome object to check. | |
53 * @return boolean True if the lastError property was set. | |
54 */ | |
55 function hasAccessed(targetChrome) { | |
56 assertRuntimeIsAvailable(); | |
57 return privates(targetChrome.runtime).accessedLastError === true; | |
58 } | |
59 | |
60 /** | |
61 * Check whether there is an error set on |targetChrome| without setting | |
62 * |accessedLastError|. | |
63 * @param {Object} targetChrome the Chrome object to check. | |
64 * @return boolean Whether lastError has been set. | |
65 */ | |
66 function hasError(targetChrome) { | |
67 if (!targetChrome) | |
68 throw new Error('No target chrome to check'); | |
69 | |
70 assertRuntimeIsAvailable(); | |
71 if ('lastError' in targetChrome.runtime) | |
72 return true; | |
73 | |
74 return false; | |
75 }; | |
76 | |
77 /** | |
78 * Clears the last error on |targetChrome|. | |
79 */ | |
80 function clear(targetChrome) { | |
81 if (!targetChrome) | |
82 throw new Error('No target chrome to clear error'); | |
83 | |
84 if (GetAvailability('extension.lastError').is_available) | |
85 delete targetChrome.extension.lastError; | |
86 | |
87 assertRuntimeIsAvailable(); | |
88 delete targetChrome.runtime.lastError; | |
89 delete privates(targetChrome.runtime).accessedLastError; | |
90 }; | |
91 | |
92 function assertRuntimeIsAvailable() { | |
93 // chrome.runtime should always be available, but maybe it's disappeared for | |
94 // some reason? Add debugging for http://crbug.com/258526. | |
95 var runtimeAvailability = GetAvailability('runtime.lastError'); | |
96 if (!runtimeAvailability.is_available) { | |
97 throw new Error('runtime.lastError is not available: ' + | |
98 runtimeAvailability.message); | |
99 } | |
100 if (!chrome.runtime) | |
101 throw new Error('runtime namespace is null or undefined'); | |
102 } | |
103 | |
104 /** | |
105 * Runs |callback(args)| with last error args as in set(). | |
106 * | |
107 * The target chrome object is the global object's of the callback, so this | |
108 * method won't work if the real callback has been wrapped (etc). | |
109 */ | |
110 function run(name, message, stack, callback, args) { | |
111 var targetChrome = GetGlobal(callback).chrome; | |
112 set(name, message, stack, targetChrome); | |
113 try { | |
114 $Function.apply(callback, undefined, args); | |
115 } finally { | |
116 clear(targetChrome); | |
117 } | |
118 } | |
119 | |
120 exports.clear = clear; | |
121 exports.hasAccessed = hasAccessed; | |
122 exports.hasError = hasError; | |
123 exports.set = set; | |
124 exports.run = run; | |
OLD | NEW |