• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights
2 // reserved. Use of this source code is governed by a BSD-style license that
3 // can be found in the LICENSE file.
4 
5 #ifndef CEF_LIBCEF_RENDERER_V8_IMPL_H_
6 #define CEF_LIBCEF_RENDERER_V8_IMPL_H_
7 #pragma once
8 
9 #include <vector>
10 
11 #include "include/cef_v8.h"
12 #include "libcef/common/tracker.h"
13 
14 #include "base/location.h"
15 #include "base/logging.h"
16 #include "base/memory/ref_counted.h"
17 #include "base/single_thread_task_runner.h"
18 #include "v8/include/v8.h"
19 
20 class CefTrackNode;
21 class GURL;
22 
23 namespace blink {
24 class WebLocalFrame;
25 }
26 
27 // Call after a V8 Isolate has been created and entered for the first time.
28 void CefV8IsolateCreated();
29 
30 // Call before a V8 Isolate is exited and destroyed.
31 void CefV8IsolateDestroyed();
32 
33 // Call to detach all handles associated with the specified context.
34 void CefV8ReleaseContext(v8::Local<v8::Context> context);
35 
36 // Set the stack size for uncaught exceptions.
37 void CefV8SetUncaughtExceptionStackSize(int stack_size);
38 
39 // Set attributes associated with a WebWorker thread.
40 void CefV8SetWorkerAttributes(int worker_id, const GURL& worker_url);
41 
42 // Used to detach handles when the associated context is released.
43 class CefV8ContextState : public base::RefCounted<CefV8ContextState> {
44  public:
CefV8ContextState()45   CefV8ContextState() : valid_(true) {}
46 
IsValid()47   bool IsValid() { return valid_; }
Detach()48   void Detach() {
49     DCHECK(valid_);
50     valid_ = false;
51     track_manager_.DeleteAll();
52   }
53 
AddTrackObject(CefTrackNode * object)54   void AddTrackObject(CefTrackNode* object) {
55     DCHECK(valid_);
56     track_manager_.Add(object);
57   }
58 
DeleteTrackObject(CefTrackNode * object)59   void DeleteTrackObject(CefTrackNode* object) {
60     DCHECK(valid_);
61     track_manager_.Delete(object);
62   }
63 
64  private:
65   friend class base::RefCounted<CefV8ContextState>;
66 
~CefV8ContextState()67   ~CefV8ContextState() {}
68 
69   bool valid_;
70   CefTrackManager track_manager_;
71 };
72 
73 // Use this template in conjuction with RefCountedThreadSafe to ensure that a
74 // V8 object is deleted on the correct thread.
75 struct CefV8DeleteOnMessageLoopThread {
76   template <typename T>
DestructCefV8DeleteOnMessageLoopThread77   static void Destruct(const T* x) {
78     if (x->task_runner()->RunsTasksInCurrentSequence()) {
79       delete x;
80     } else {
81       if (!x->task_runner()->DeleteSoon(FROM_HERE, x)) {
82 #if defined(UNIT_TEST)
83         // Only logged under unit testing because leaks at shutdown
84         // are acceptable under normal circumstances.
85         LOG(ERROR) << "DeleteSoon failed on thread " << thread;
86 #endif  // UNIT_TEST
87       }
88     }
89   }
90 };
91 
92 // Base class for V8 Handle types.
93 class CefV8HandleBase
94     : public base::RefCountedThreadSafe<CefV8HandleBase,
95                                         CefV8DeleteOnMessageLoopThread> {
96  public:
97   // Returns true if there is no underlying context or if the underlying context
98   // is valid.
IsValid()99   bool IsValid() const {
100     return (!context_state_.get() || context_state_->IsValid());
101   }
102 
103   bool BelongsToCurrentThread() const;
104 
isolate()105   v8::Isolate* isolate() const { return isolate_; }
task_runner()106   scoped_refptr<base::SingleThreadTaskRunner> task_runner() const {
107     return task_runner_;
108   }
109 
110  protected:
111   friend class base::DeleteHelper<CefV8HandleBase>;
112   friend class base::RefCountedThreadSafe<CefV8HandleBase,
113                                           CefV8DeleteOnMessageLoopThread>;
114   friend struct CefV8DeleteOnMessageLoopThread;
115 
116   // |context| is the context that owns this handle. If empty the current
117   // context will be used.
118   CefV8HandleBase(v8::Isolate* isolate, v8::Local<v8::Context> context);
119   virtual ~CefV8HandleBase();
120 
121  protected:
122   v8::Isolate* isolate_;
123   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
124   scoped_refptr<CefV8ContextState> context_state_;
125 };
126 
127 // Template for V8 Handle types. This class is used to ensure that V8 objects
128 // are only released on the render thread.
129 template <typename v8class>
130 class CefV8Handle : public CefV8HandleBase {
131  public:
132   typedef v8::Local<v8class> handleType;
133   typedef v8::Persistent<v8class> persistentType;
134 
CefV8Handle(v8::Isolate * isolate,v8::Local<v8::Context> context,handleType v)135   CefV8Handle(v8::Isolate* isolate,
136               v8::Local<v8::Context> context,
137               handleType v)
138       : CefV8HandleBase(isolate, context), handle_(isolate, v) {}
139 
GetNewV8Handle()140   handleType GetNewV8Handle() {
141     DCHECK(IsValid());
142     return handleType::New(isolate(), handle_);
143   }
144 
GetPersistentV8Handle()145   persistentType& GetPersistentV8Handle() { return handle_; }
146 
147  protected:
~CefV8Handle()148   ~CefV8Handle() override { handle_.Reset(); }
149 
150   persistentType handle_;
151 
152   DISALLOW_COPY_AND_ASSIGN(CefV8Handle);
153 };
154 
155 // Specialization for v8::Value with empty implementation to avoid incorrect
156 // usage.
157 template <>
158 class CefV8Handle<v8::Value> {};
159 
160 class CefV8ContextImpl : public CefV8Context {
161  public:
162   CefV8ContextImpl(v8::Isolate* isolate, v8::Local<v8::Context> context);
163   ~CefV8ContextImpl() override;
164 
165   CefRefPtr<CefTaskRunner> GetTaskRunner() override;
166   bool IsValid() override;
167   CefRefPtr<CefBrowser> GetBrowser() override;
168   CefRefPtr<CefFrame> GetFrame() override;
169   CefRefPtr<CefV8Value> GetGlobal() override;
170   bool Enter() override;
171   bool Exit() override;
172   bool IsSame(CefRefPtr<CefV8Context> that) override;
173   bool Eval(const CefString& code,
174             const CefString& script_url,
175             int start_line,
176             CefRefPtr<CefV8Value>& retval,
177             CefRefPtr<CefV8Exception>& exception) override;
178 
179   v8::Local<v8::Context> GetV8Context();
180   blink::WebLocalFrame* GetWebFrame();
181 
182  private:
183   typedef CefV8Handle<v8::Context> Handle;
184   scoped_refptr<Handle> handle_;
185 
186   int enter_count_;
187   std::unique_ptr<v8::MicrotasksScope> microtasks_scope_;
188 
189   IMPLEMENT_REFCOUNTING(CefV8ContextImpl);
190   DISALLOW_COPY_AND_ASSIGN(CefV8ContextImpl);
191 };
192 
193 class CefV8ValueImpl : public CefV8Value {
194  public:
195   explicit CefV8ValueImpl(v8::Isolate* isolate);
196   CefV8ValueImpl(v8::Isolate* isolate,
197                  v8::Local<v8::Context> context,
198                  v8::Local<v8::Value> value);
199   ~CefV8ValueImpl() override;
200 
201   // Used for initializing the CefV8ValueImpl. Should be called a single time
202   // after the CefV8ValueImpl is created.
203   void InitFromV8Value(v8::Local<v8::Context> context,
204                        v8::Local<v8::Value> value);
205   void InitUndefined();
206   void InitNull();
207   void InitBool(bool value);
208   void InitInt(int32 value);
209   void InitUInt(uint32 value);
210   void InitDouble(double value);
211   void InitDate(const CefTime& value);
212   void InitString(CefString& value);
213   void InitObject(v8::Local<v8::Value> value, CefTrackNode* tracker);
214 
215   // Creates a new V8 value for the underlying value or returns the existing
216   // object handle.
217   v8::Local<v8::Value> GetV8Value(bool should_persist);
218 
219   bool IsValid() override;
220   bool IsUndefined() override;
221   bool IsNull() override;
222   bool IsBool() override;
223   bool IsInt() override;
224   bool IsUInt() override;
225   bool IsDouble() override;
226   bool IsDate() override;
227   bool IsString() override;
228   bool IsObject() override;
229   bool IsArray() override;
230   bool IsArrayBuffer() override;
231   bool IsFunction() override;
232   bool IsSame(CefRefPtr<CefV8Value> value) override;
233   bool GetBoolValue() override;
234   int32 GetIntValue() override;
235   uint32 GetUIntValue() override;
236   double GetDoubleValue() override;
237   CefTime GetDateValue() override;
238   CefString GetStringValue() override;
239   bool IsUserCreated() override;
240   bool HasException() override;
241   CefRefPtr<CefV8Exception> GetException() override;
242   bool ClearException() override;
243   bool WillRethrowExceptions() override;
244   bool SetRethrowExceptions(bool rethrow) override;
245   bool HasValue(const CefString& key) override;
246   bool HasValue(int index) override;
247   bool DeleteValue(const CefString& key) override;
248   bool DeleteValue(int index) override;
249   CefRefPtr<CefV8Value> GetValue(const CefString& key) override;
250   CefRefPtr<CefV8Value> GetValue(int index) override;
251   bool SetValue(const CefString& key,
252                 CefRefPtr<CefV8Value> value,
253                 PropertyAttribute attribute) override;
254   bool SetValue(int index, CefRefPtr<CefV8Value> value) override;
255   bool SetValue(const CefString& key,
256                 AccessControl settings,
257                 PropertyAttribute attribute) override;
258   bool GetKeys(std::vector<CefString>& keys) override;
259   bool SetUserData(CefRefPtr<CefBaseRefCounted> user_data) override;
260   CefRefPtr<CefBaseRefCounted> GetUserData() override;
261   int GetExternallyAllocatedMemory() override;
262   int AdjustExternallyAllocatedMemory(int change_in_bytes) override;
263   int GetArrayLength() override;
264   CefRefPtr<CefV8ArrayBufferReleaseCallback> GetArrayBufferReleaseCallback()
265       override;
266   bool NeuterArrayBuffer() override;
267   CefString GetFunctionName() override;
268   CefRefPtr<CefV8Handler> GetFunctionHandler() override;
269   CefRefPtr<CefV8Value> ExecuteFunction(
270       CefRefPtr<CefV8Value> object,
271       const CefV8ValueList& arguments) override;
272   CefRefPtr<CefV8Value> ExecuteFunctionWithContext(
273       CefRefPtr<CefV8Context> context,
274       CefRefPtr<CefV8Value> object,
275       const CefV8ValueList& arguments) override;
276 
277  private:
278   // Test for and record any exception.
279   bool HasCaught(v8::Local<v8::Context> context, v8::TryCatch& try_catch);
280 
281   class Handle : public CefV8HandleBase {
282    public:
283     typedef v8::Local<v8::Value> handleType;
284     typedef v8::Persistent<v8::Value> persistentType;
285 
286     Handle(v8::Isolate* isolate,
287            v8::Local<v8::Context> context,
288            handleType v,
289            CefTrackNode* tracker);
290 
291     handleType GetNewV8Handle(bool should_persist);
292 
293     persistentType& GetPersistentV8Handle();
294 
295     void SetWeakIfNecessary();
296 
297    private:
298     ~Handle() override;
299 
300    private:
301     // Callbacks for weak persistent reference destruction.
302     static void FirstWeakCallback(const v8::WeakCallbackInfo<Handle>& data);
303     static void SecondWeakCallback(const v8::WeakCallbackInfo<Handle>& data);
304 
305     persistentType handle_;
306 
307     // For Object and Function types, we need to hold on to a reference to their
308     // internal data or function handler objects that are reference counted.
309     CefTrackNode* tracker_;
310 
311     // True if the handle needs to persist due to it being passed into V8.
312     bool should_persist_;
313 
314     // True if the handle has been set as weak.
315     bool is_set_weak_;
316 
317     DISALLOW_COPY_AND_ASSIGN(Handle);
318   };
319 
320   v8::Isolate* isolate_;
321 
322   enum {
323     TYPE_INVALID = 0,
324     TYPE_UNDEFINED,
325     TYPE_NULL,
326     TYPE_BOOL,
327     TYPE_INT,
328     TYPE_UINT,
329     TYPE_DOUBLE,
330     TYPE_DATE,
331     TYPE_STRING,
332     TYPE_OBJECT,
333   } type_;
334 
335   union {
336     bool bool_value_;
337     int32 int_value_;
338     uint32 uint_value_;
339     double double_value_;
340     cef_time_t date_value_;
341     cef_string_t string_value_;
342   };
343 
344   // Used with Object, Function and Array types.
345   scoped_refptr<Handle> handle_;
346 
347   CefRefPtr<CefV8Exception> last_exception_;
348   bool rethrow_exceptions_;
349 
350   IMPLEMENT_REFCOUNTING(CefV8ValueImpl);
351   DISALLOW_COPY_AND_ASSIGN(CefV8ValueImpl);
352 };
353 
354 class CefV8StackTraceImpl : public CefV8StackTrace {
355  public:
356   CefV8StackTraceImpl(v8::Isolate* isolate, v8::Local<v8::StackTrace> handle);
357   ~CefV8StackTraceImpl() override;
358 
359   bool IsValid() override;
360   int GetFrameCount() override;
361   CefRefPtr<CefV8StackFrame> GetFrame(int index) override;
362 
363  private:
364   std::vector<CefRefPtr<CefV8StackFrame>> frames_;
365 
366   IMPLEMENT_REFCOUNTING(CefV8StackTraceImpl);
367   DISALLOW_COPY_AND_ASSIGN(CefV8StackTraceImpl);
368 };
369 
370 class CefV8StackFrameImpl : public CefV8StackFrame {
371  public:
372   CefV8StackFrameImpl(v8::Isolate* isolate, v8::Local<v8::StackFrame> handle);
373   ~CefV8StackFrameImpl() override;
374 
375   bool IsValid() override;
376   CefString GetScriptName() override;
377   CefString GetScriptNameOrSourceURL() override;
378   CefString GetFunctionName() override;
379   int GetLineNumber() override;
380   int GetColumn() override;
381   bool IsEval() override;
382   bool IsConstructor() override;
383 
384  private:
385   CefString script_name_;
386   CefString script_name_or_source_url_;
387   CefString function_name_;
388   int line_number_;
389   int column_;
390   bool is_eval_;
391   bool is_constructor_;
392 
393   IMPLEMENT_REFCOUNTING(CefV8StackFrameImpl);
394   DISALLOW_COPY_AND_ASSIGN(CefV8StackFrameImpl);
395 };
396 
397 #endif  // CEF_LIBCEF_RENDERER_V8_IMPL_H_
398