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 5var GetAvailability = requireNative('v8_context').GetAvailability; 6var 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 */ 21function 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 targetChrome.runtime.lastError = errorObject; 36}; 37 38/** 39 * Clears the last error on |targetChrome|. 40 */ 41function clear(targetChrome) { 42 if (!targetChrome) 43 throw new Error('No target chrome to clear error'); 44 45 if (GetAvailability('extension.lastError').is_available) 46 delete targetChrome.extension.lastError; 47 48 assertRuntimeIsAvailable(); 49 delete targetChrome.runtime.lastError; 50}; 51 52function assertRuntimeIsAvailable() { 53 // chrome.runtime should always be available, but maybe it's disappeared for 54 // some reason? Add debugging for http://crbug.com/258526. 55 var runtimeAvailability = GetAvailability('runtime.lastError'); 56 if (!runtimeAvailability.is_available) { 57 throw new Error('runtime.lastError is not available: ' + 58 runtimeAvailability.message); 59 } 60 if (!chrome.runtime) 61 throw new Error('runtime namespace is null or undefined'); 62} 63 64/** 65 * Runs |callback(args)| with last error args as in set(). 66 * 67 * The target chrome object is the global object's of the callback, so this 68 * method won't work if the real callback has been wrapped (etc). 69 */ 70function run(name, message, stack, callback, args) { 71 var targetChrome = GetGlobal(callback).chrome; 72 set(name, message, stack, targetChrome); 73 try { 74 $Function.apply(callback, undefined, args); 75 } finally { 76 clear(targetChrome); 77 } 78} 79 80exports.clear = clear; 81exports.set = set; 82exports.run = run; 83