blob: 8d53371827acd01eeaa12840bd71497b5bb90120 [file] [log] [blame]
[email protected]8f857ef82014-06-04 23:46:161// Copyright 2014 The Chromium Authors. All rights reserved.
[email protected]120028b9c2012-07-03 01:32:242// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]4f1633f2013-03-09 14:26:245var GetAvailability = requireNative('v8_context').GetAvailability;
6var GetGlobal = requireNative('sendRequest').GetGlobal;
[email protected]b9c34c82012-07-10 22:03:557
[email protected]4f1633f2013-03-09 14:26:248// 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/**
[email protected]65cda75722013-04-06 04:51:3718 * Sets the last error for |name| on |targetChrome| to |message| with an
19 * optional |stack|.
[email protected]4f1633f2013-03-09 14:26:2420 */
[email protected]65cda75722013-04-06 04:51:3721function set(name, message, stack, targetChrome) {
[email protected]65cda75722013-04-06 04:51:3722 var errorMessage = name + ': ' + message;
23 if (stack != null && stack != '')
24 errorMessage += '\n' + stack;
[email protected]9c813da2013-07-19 20:35:2125
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
[email protected]65cda75722013-04-06 04:51:3730 var errorObject = { message: message };
[email protected]66296352014-05-31 03:45:4831 if (GetAvailability('extension.lastError').is_available)
[email protected]4f1633f2013-03-09 14:26:2432 targetChrome.extension.lastError = errorObject;
[email protected]9c813da2013-07-19 20:35:2133
34 assertRuntimeIsAvailable();
[email protected]52b062862014-04-23 00:31:4435
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 }});
[email protected]120028b9c2012-07-03 01:32:2448};
49
[email protected]4f1633f2013-03-09 14:26:2450/**
[email protected]52b062862014-04-23 00:31:4451 * 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 */
55function hasAccessed(targetChrome) {
56 assertRuntimeIsAvailable();
57 return privates(targetChrome.runtime).accessedLastError === true;
58}
59
60/**
[email protected]a33425c3c2014-05-15 19:22:3461 * 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 */
66function 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/**
[email protected]4f1633f2013-03-09 14:26:2478 * Clears the last error on |targetChrome|.
79 */
80function clear(targetChrome) {
[email protected]9c813da2013-07-19 20:35:2181 if (!targetChrome)
82 throw new Error('No target chrome to clear error');
83
[email protected]66296352014-05-31 03:45:4884 if (GetAvailability('extension.lastError').is_available)
[email protected]f0e9ac552014-05-07 14:26:5085 delete targetChrome.extension.lastError;
[email protected]9c813da2013-07-19 20:35:2186
87 assertRuntimeIsAvailable();
[email protected]4f1633f2013-03-09 14:26:2488 delete targetChrome.runtime.lastError;
[email protected]52b062862014-04-23 00:31:4489 delete privates(targetChrome.runtime).accessedLastError;
[email protected]120028b9c2012-07-03 01:32:2490};
91
[email protected]9c813da2013-07-19 20:35:2192function 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
[email protected]4f1633f2013-03-09 14:26:24104/**
[email protected]65cda75722013-04-06 04:51:37105 * Runs |callback(args)| with last error args as in set().
[email protected]4f1633f2013-03-09 14:26:24106 *
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 */
[email protected]65cda75722013-04-06 04:51:37110function run(name, message, stack, callback, args) {
[email protected]4f1633f2013-03-09 14:26:24111 var targetChrome = GetGlobal(callback).chrome;
[email protected]65cda75722013-04-06 04:51:37112 set(name, message, stack, targetChrome);
[email protected]4f1633f2013-03-09 14:26:24113 try {
[email protected]31bbfd72013-06-22 02:35:54114 $Function.apply(callback, undefined, args);
[email protected]4f1633f2013-03-09 14:26:24115 } finally {
116 clear(targetChrome);
117 }
118}
119
[email protected]120028b9c2012-07-03 01:32:24120exports.clear = clear;
[email protected]52b062862014-04-23 00:31:44121exports.hasAccessed = hasAccessed;
[email protected]a33425c3c2014-05-15 19:22:34122exports.hasError = hasError;
[email protected]120028b9c2012-07-03 01:32:24123exports.set = set;
[email protected]4f1633f2013-03-09 14:26:24124exports.run = run;