Upstream version 7.35.144.0
[platform/framework/web/crosswalk.git] / src / chrome / renderer / extensions / module_system.h
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 #ifndef CHROME_RENDERER_EXTENSIONS_MODULE_SYSTEM_H_
6 #define CHROME_RENDERER_EXTENSIONS_MODULE_SYSTEM_H_
7
8 #include "base/compiler_specific.h"
9 #include "base/memory/linked_ptr.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "chrome/renderer/extensions/native_handler.h"
12 #include "chrome/renderer/extensions/object_backed_native_handler.h"
13 #include "v8/include/v8.h"
14
15 #include <map>
16 #include <set>
17 #include <string>
18 #include <vector>
19
20 namespace extensions {
21
22 class ChromeV8Context;
23
24 // A module system for JS similar to node.js' require() function.
25 // Each module has three variables in the global scope:
26 //   - exports, an object returned to dependencies who require() this
27 //     module.
28 //   - require, a function that takes a module name as an argument and returns
29 //     that module's exports object.
30 //   - requireNative, a function that takes the name of a registered
31 //     NativeHandler and returns an object that contains the functions the
32 //     NativeHandler defines.
33 //
34 // Each module in a ModuleSystem is executed at most once and its exports
35 // object cached.
36 //
37 // Note that a ModuleSystem must be used only in conjunction with a single
38 // v8::Context.
39 // TODO(koz): Rename this to JavaScriptModuleSystem.
40 class ModuleSystem : public ObjectBackedNativeHandler {
41  public:
42   class SourceMap {
43    public:
44     virtual ~SourceMap() {}
45     virtual v8::Handle<v8::Value> GetSource(v8::Isolate* isolate,
46                                             const std::string& name) = 0;
47     virtual bool Contains(const std::string& name) = 0;
48   };
49
50   class ExceptionHandler {
51    public:
52     virtual ~ExceptionHandler() {}
53     virtual void HandleUncaughtException(const v8::TryCatch& try_catch) = 0;
54
55    protected:
56     // Formats |try_catch| as a nice string.
57     std::string CreateExceptionString(const v8::TryCatch& try_catch);
58   };
59
60   // Enables native bindings for the duration of its lifetime.
61   class NativesEnabledScope {
62    public:
63     explicit NativesEnabledScope(ModuleSystem* module_system);
64     ~NativesEnabledScope();
65
66    private:
67     ModuleSystem* module_system_;
68     DISALLOW_COPY_AND_ASSIGN(NativesEnabledScope);
69   };
70
71   // |source_map| is a weak pointer.
72   ModuleSystem(ChromeV8Context* context, SourceMap* source_map);
73   virtual ~ModuleSystem();
74
75   // Require the specified module. This is the equivalent of calling
76   // require('module_name') from the loaded JS files.
77   v8::Handle<v8::Value> Require(const std::string& module_name);
78   void Require(const v8::FunctionCallbackInfo<v8::Value>& args);
79
80   // Run |code| in the current context with the name |name| used for stack
81   // traces.
82   v8::Handle<v8::Value> RunString(v8::Handle<v8::String> code,
83                                   v8::Handle<v8::String> name);
84
85   // Calls the specified method exported by the specified module. This is
86   // equivalent to calling require('module_name').method_name() from JS.
87   v8::Local<v8::Value> CallModuleMethod(const std::string& module_name,
88                                         const std::string& method_name);
89   v8::Local<v8::Value> CallModuleMethod(
90       const std::string& module_name,
91       const std::string& method_name,
92       std::vector<v8::Handle<v8::Value> >* args);
93   v8::Local<v8::Value> CallModuleMethod(
94       const std::string& module_name,
95       const std::string& method_name,
96       int argc,
97       v8::Handle<v8::Value> argv[]);
98
99   // Register |native_handler| as a potential target for requireNative(), so
100   // calls to requireNative(|name|) from JS will return a new object created by
101   // |native_handler|.
102   void RegisterNativeHandler(const std::string& name,
103                              scoped_ptr<NativeHandler> native_handler);
104
105   // Causes requireNative(|name|) to look for its module in |source_map_|
106   // instead of using a registered native handler. This can be used in unit
107   // tests to mock out native modules.
108   void OverrideNativeHandlerForTest(const std::string& name);
109
110   // Executes |code| in the current context with |name| as the filename.
111   void RunString(const std::string& code, const std::string& name);
112
113   // Make |object|.|field| lazily evaluate to the result of
114   // require(|module_name|)[|module_field|].
115   //
116   // TODO(kalman): All targets for this method are ObjectBackedNativeHandlers,
117   //               move this logic into those classes (in fact, the chrome
118   //               object is the only client, only that needs to implement it).
119   void SetLazyField(v8::Handle<v8::Object> object,
120                     const std::string& field,
121                     const std::string& module_name,
122                     const std::string& module_field);
123
124   void SetLazyField(v8::Handle<v8::Object> object,
125                     const std::string& field,
126                     const std::string& module_name,
127                     const std::string& module_field,
128                     v8::AccessorGetterCallback getter);
129
130   // Make |object|.|field| lazily evaluate to the result of
131   // requireNative(|module_name|)[|module_field|].
132   // TODO(kalman): Same as above.
133   void SetNativeLazyField(v8::Handle<v8::Object> object,
134                           const std::string& field,
135                           const std::string& module_name,
136                           const std::string& module_field);
137
138   // Passes exceptions to |handler| rather than console::Fatal.
139   void SetExceptionHandlerForTest(scoped_ptr<ExceptionHandler> handler) {
140     exception_handler_ = handler.Pass();
141   }
142
143  protected:
144   friend class ChromeV8Context;
145   virtual void Invalidate() OVERRIDE;
146
147  private:
148   typedef std::map<std::string, linked_ptr<NativeHandler> > NativeHandlerMap;
149
150   // Retrieves the lazily defined field specified by |property|.
151   static void LazyFieldGetter(v8::Local<v8::String> property,
152                               const v8::PropertyCallbackInfo<v8::Value>& info);
153   // Retrieves the lazily defined field specified by |property| on a native
154   // object.
155   static void NativeLazyFieldGetter(
156       v8::Local<v8::String> property,
157       const v8::PropertyCallbackInfo<v8::Value>& info);
158
159   // Called when an exception is thrown but not caught.
160   void HandleException(const v8::TryCatch& try_catch);
161
162   // Ensure that require_ has been evaluated from require.js.
163   void EnsureRequireLoaded();
164
165   void RequireForJs(const v8::FunctionCallbackInfo<v8::Value>& args);
166   v8::Local<v8::Value> RequireForJsInner(v8::Handle<v8::String> module_name);
167
168   typedef v8::Handle<v8::Value> (ModuleSystem::*RequireFunction)(
169       const std::string&);
170   // Base implementation of a LazyFieldGetter which uses |require_fn| to require
171   // modules.
172   static void LazyFieldGetterInner(
173       v8::Local<v8::String> property,
174       const v8::PropertyCallbackInfo<v8::Value>& info,
175       RequireFunction require_function);
176
177   // Return the named source file stored in the source map.
178   // |args[0]| - the name of a source file in source_map_.
179   v8::Handle<v8::Value> GetSource(const std::string& module_name);
180
181   // Return an object that contains the native methods defined by the named
182   // NativeHandler.
183   // |args[0]| - the name of a native handler object.
184   v8::Handle<v8::Value> RequireNativeFromString(const std::string& native_name);
185   void RequireNative(const v8::FunctionCallbackInfo<v8::Value>& args);
186
187   // Wraps |source| in a (function(require, requireNative, exports) {...}).
188   v8::Handle<v8::String> WrapSource(v8::Handle<v8::String> source);
189
190   // NativeHandler implementation which returns the private area of an Object.
191   void Private(const v8::FunctionCallbackInfo<v8::Value>& args);
192
193   // NativeHandler implementation which returns a function wrapper for a
194   // provided function.
195   void CreateFunctionWrapper(const v8::FunctionCallbackInfo<v8::Value>& args);
196
197   ChromeV8Context* context_;
198
199   // A map from module names to the JS source for that module. GetSource()
200   // performs a lookup on this map.
201   SourceMap* source_map_;
202
203   // A map from native handler names to native handlers.
204   NativeHandlerMap native_handler_map_;
205
206   // When 0, natives are disabled, otherwise indicates how many callers have
207   // pinned natives as enabled.
208   int natives_enabled_;
209
210   // Called when an exception is thrown but not caught in JS. Overridable by
211   // tests.
212   scoped_ptr<ExceptionHandler> exception_handler_;
213
214   std::set<std::string> overridden_native_handlers_;
215
216   DISALLOW_COPY_AND_ASSIGN(ModuleSystem);
217 };
218
219 }  // namespace extensions
220
221 #endif  // CHROME_RENDERER_EXTENSIONS_MODULE_SYSTEM_H_