Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / renderer / resources / extensions / last_error.js
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   var errorObject = { message: message };
31   if (targetChrome && targetChrome.extension)
32     targetChrome.extension.lastError = errorObject;
33
34   assertRuntimeIsAvailable();
35
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       }});
48 };
49
50 /**
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.
54  */
55 function hasAccessed(targetChrome) {
56   assertRuntimeIsAvailable();
57   return privates(targetChrome.runtime).accessedLastError === true;
58 }
59
60 /**
61  * Clears the last error on |targetChrome|.
62  */
63 function clear(targetChrome) {
64   if (!targetChrome)
65     throw new Error('No target chrome to clear error');
66
67   if (targetChrome && targetChrome.extension)
68    delete targetChrome.extension.lastError;
69
70   assertRuntimeIsAvailable();
71   delete targetChrome.runtime.lastError;
72   delete privates(targetChrome.runtime).accessedLastError;
73 };
74
75 function assertRuntimeIsAvailable() {
76   // chrome.runtime should always be available, but maybe it's disappeared for
77   // some reason? Add debugging for http://crbug.com/258526.
78   var runtimeAvailability = GetAvailability('runtime.lastError');
79   if (!runtimeAvailability.is_available) {
80     throw new Error('runtime.lastError is not available: ' +
81                     runtimeAvailability.message);
82   }
83   if (!chrome.runtime)
84     throw new Error('runtime namespace is null or undefined');
85 }
86
87 /**
88  * Runs |callback(args)| with last error args as in set().
89  *
90  * The target chrome object is the global object's of the callback, so this
91  * method won't work if the real callback has been wrapped (etc).
92  */
93 function run(name, message, stack, callback, args) {
94   var targetChrome = GetGlobal(callback).chrome;
95   set(name, message, stack, targetChrome);
96   try {
97     $Function.apply(callback, undefined, args);
98   } finally {
99     clear(targetChrome);
100   }
101 }
102
103 exports.clear = clear;
104 exports.hasAccessed = hasAccessed;
105 exports.set = set;
106 exports.run = run;