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