Home | History | Annotate | Download | only in extensions
      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