1 // Copyright 2014 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.
5 var GetAvailability
= requireNative('v8_context').GetAvailability
;
6 var GetGlobal
= requireNative('sendRequest').GetGlobal
;
8 // Utility for setting chrome.*.lastError.
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.
18 * Sets the last error for |name| on |targetChrome| to |message| with an
21 function set(name
, message
, stack
, targetChrome
) {
22 var errorMessage
= name
+ ': ' + message
;
23 if (stack
!= null && stack
!= '')
24 errorMessage
+= '\n' + stack
;
27 throw new Error('No chrome object to set error: ' + errorMessage
);
28 clear(targetChrome
); // in case somebody has set a sneaky getter/setter
30 var errorObject
= { message
: message
};
31 if (GetAvailability('extension.lastError').is_available
)
32 targetChrome
.extension
.lastError
= errorObject
;
34 assertRuntimeIsAvailable();
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', {
42 privates(targetChrome
.runtime
).accessedLastError
= true;
45 set: function(error
) {
46 errorObject
= errorObject
;
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.
55 function hasAccessed(targetChrome
) {
56 assertRuntimeIsAvailable();
57 return privates(targetChrome
.runtime
).accessedLastError
=== true;
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.
66 function hasError(targetChrome
) {
68 throw new Error('No target chrome to check');
70 assertRuntimeIsAvailable();
71 if ('lastError' in targetChrome
.runtime
)
78 * Clears the last error on |targetChrome|.
80 function clear(targetChrome
) {
82 throw new Error('No target chrome to clear error');
84 if (GetAvailability('extension.lastError').is_available
)
85 delete targetChrome
.extension
.lastError
;
87 assertRuntimeIsAvailable();
88 delete targetChrome
.runtime
.lastError
;
89 delete privates(targetChrome
.runtime
).accessedLastError
;
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
);
101 throw new Error('runtime namespace is null or undefined');
105 * Runs |callback(args)| with last error args as in set().
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).
110 function run(name
, message
, stack
, callback
, args
) {
111 var targetChrome
= GetGlobal(callback
).chrome
;
112 set(name
, message
, stack
, targetChrome
);
114 $Function
.apply(callback
, undefined, args
);
120 exports
.clear
= clear
;
121 exports
.hasAccessed
= hasAccessed
;
122 exports
.hasError
= hasError
;