• 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/task/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   using handleType = v8::Local<v8class>;
133   using persistentType = v8::Persistent<v8class>;
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 
140   CefV8Handle(const CefV8Handle&) = delete;
141   CefV8Handle& operator=(const CefV8Handle&) = delete;
142 
GetNewV8Handle()143   handleType GetNewV8Handle() {
144     DCHECK(IsValid());
145     return handleType::New(isolate(), handle_);
146   }
147 
GetPersistentV8Handle()148   persistentType& GetPersistentV8Handle() { return handle_; }
149 
150  protected:
~CefV8Handle()151   ~CefV8Handle() override { handle_.Reset(); }
152 
153   persistentType handle_;
154 };
155 
156 // Specialization for v8::Value with empty implementation to avoid incorrect
157 // usage.
158 template <>
159 class CefV8Handle<v8::Value> {};
160 
161 class CefV8ContextImpl : public CefV8Context {
162  public:
163   CefV8ContextImpl(v8::Isolate* isolate, v8::Local<v8::Context> context);
164 
165   CefV8ContextImpl(const CefV8ContextImpl&) = delete;
166   CefV8ContextImpl& operator=(const CefV8ContextImpl&) = delete;
167 
168   ~CefV8ContextImpl() override;
169 
170   CefRefPtr<CefTaskRunner> GetTaskRunner() override;
171   bool IsValid() override;
172   CefRefPtr<CefBrowser> GetBrowser() override;
173   CefRefPtr<CefFrame> GetFrame() override;
174   CefRefPtr<CefV8Value> GetGlobal() override;
175   bool Enter() override;
176   bool Exit() override;
177   bool IsSame(CefRefPtr<CefV8Context> that) override;
178   bool Eval(const CefString& code,
179             const CefString& script_url,
180             int start_line,
181             CefRefPtr<CefV8Value>& retval,
182             CefRefPtr<CefV8Exception>& exception) override;
183 
184   v8::Local<v8::Context> GetV8Context();
185   blink::WebLocalFrame* GetWebFrame();
186 
187  private:
188   using Handle = CefV8Handle<v8::Context>;
189   scoped_refptr<Handle> handle_;
190 
191   int enter_count_;
192   std::unique_ptr<v8::MicrotasksScope> microtasks_scope_;
193 
194   IMPLEMENT_REFCOUNTING(CefV8ContextImpl);
195 };
196 
197 class CefV8ValueImpl : public CefV8Value {
198  public:
199   explicit CefV8ValueImpl(v8::Isolate* isolate);
200   CefV8ValueImpl(v8::Isolate* isolate,
201                  v8::Local<v8::Context> context,
202                  v8::Local<v8::Value> value);
203 
204   CefV8ValueImpl(const CefV8ValueImpl&) = delete;
205   CefV8ValueImpl& operator=(const CefV8ValueImpl&) = delete;
206 
207   ~CefV8ValueImpl() override;
208 
209   // Used for initializing the CefV8ValueImpl. Should be called a single time
210   // after the CefV8ValueImpl is created.
211   void InitFromV8Value(v8::Local<v8::Context> context,
212                        v8::Local<v8::Value> value);
213   void InitUndefined();
214   void InitNull();
215   void InitBool(bool value);
216   void InitInt(int32 value);
217   void InitUInt(uint32 value);
218   void InitDouble(double value);
219   void InitDate(const CefTime& value);
220   void InitString(CefString& value);
221   void InitObject(v8::Local<v8::Value> value, CefTrackNode* tracker);
222 
223   // Creates a new V8 value for the underlying value or returns the existing
224   // object handle.
225   v8::Local<v8::Value> GetV8Value(bool should_persist);
226 
227   bool IsValid() override;
228   bool IsUndefined() override;
229   bool IsNull() override;
230   bool IsBool() override;
231   bool IsInt() override;
232   bool IsUInt() override;
233   bool IsDouble() override;
234   bool IsDate() override;
235   bool IsString() override;
236   bool IsObject() override;
237   bool IsArray() override;
238   bool IsArrayBuffer() override;
239   bool IsFunction() override;
240   bool IsSame(CefRefPtr<CefV8Value> value) override;
241   bool GetBoolValue() override;
242   int32 GetIntValue() override;
243   uint32 GetUIntValue() override;
244   double GetDoubleValue() override;
245   CefTime GetDateValue() override;
246   CefString GetStringValue() override;
247   bool IsUserCreated() override;
248   bool HasException() override;
249   CefRefPtr<CefV8Exception> GetException() override;
250   bool ClearException() override;
251   bool WillRethrowExceptions() override;
252   bool SetRethrowExceptions(bool rethrow) override;
253   bool HasValue(const CefString& key) override;
254   bool HasValue(int index) override;
255   bool DeleteValue(const CefString& key) override;
256   bool DeleteValue(int index) override;
257   CefRefPtr<CefV8Value> GetValue(const CefString& key) override;
258   CefRefPtr<CefV8Value> GetValue(int index) override;
259   bool SetValue(const CefString& key,
260                 CefRefPtr<CefV8Value> value,
261                 PropertyAttribute attribute) override;
262   bool SetValue(int index, CefRefPtr<CefV8Value> value) override;
263   bool SetValue(const CefString& key,
264                 AccessControl settings,
265                 PropertyAttribute attribute) override;
266   bool GetKeys(std::vector<CefString>& keys) override;
267   bool SetUserData(CefRefPtr<CefBaseRefCounted> user_data) override;
268   CefRefPtr<CefBaseRefCounted> GetUserData() override;
269   int GetExternallyAllocatedMemory() override;
270   int AdjustExternallyAllocatedMemory(int change_in_bytes) override;
271   int GetArrayLength() override;
272   CefRefPtr<CefV8ArrayBufferReleaseCallback> GetArrayBufferReleaseCallback()
273       override;
274   bool NeuterArrayBuffer() override;
275   CefString GetFunctionName() override;
276   CefRefPtr<CefV8Handler> GetFunctionHandler() override;
277   CefRefPtr<CefV8Value> ExecuteFunction(
278       CefRefPtr<CefV8Value> object,
279       const CefV8ValueList& arguments) override;
280   CefRefPtr<CefV8Value> ExecuteFunctionWithContext(
281       CefRefPtr<CefV8Context> context,
282       CefRefPtr<CefV8Value> object,
283       const CefV8ValueList& arguments) override;
284 
285  private:
286   // Test for and record any exception.
287   bool HasCaught(v8::Local<v8::Context> context, v8::TryCatch& try_catch);
288 
289   class Handle : public CefV8HandleBase {
290    public:
291     using handleType = v8::Local<v8::Value>;
292     using persistentType = v8::Persistent<v8::Value>;
293 
294     Handle(v8::Isolate* isolate,
295            v8::Local<v8::Context> context,
296            handleType v,
297            CefTrackNode* tracker);
298 
299     Handle(const Handle&) = delete;
300     Handle& operator=(const Handle&) = delete;
301 
302     handleType GetNewV8Handle(bool should_persist);
303 
304     persistentType& GetPersistentV8Handle();
305 
306     void SetWeakIfNecessary();
307 
308    private:
309     ~Handle() override;
310 
311    private:
312     // Callbacks for weak persistent reference destruction.
313     static void FirstWeakCallback(const v8::WeakCallbackInfo<Handle>& data);
314     static void SecondWeakCallback(const v8::WeakCallbackInfo<Handle>& data);
315 
316     persistentType handle_;
317 
318     // For Object and Function types, we need to hold on to a reference to their
319     // internal data or function handler objects that are reference counted.
320     CefTrackNode* tracker_;
321 
322     // True if the handle needs to persist due to it being passed into V8.
323     bool should_persist_;
324 
325     // True if the handle has been set as weak.
326     bool is_set_weak_;
327   };
328 
329   v8::Isolate* isolate_;
330 
331   enum {
332     TYPE_INVALID = 0,
333     TYPE_UNDEFINED,
334     TYPE_NULL,
335     TYPE_BOOL,
336     TYPE_INT,
337     TYPE_UINT,
338     TYPE_DOUBLE,
339     TYPE_DATE,
340     TYPE_STRING,
341     TYPE_OBJECT,
342   } type_;
343 
344   union {
345     bool bool_value_;
346     int32 int_value_;
347     uint32 uint_value_;
348     double double_value_;
349     cef_time_t date_value_;
350     cef_string_t string_value_;
351   };
352 
353   // Used with Object, Function and Array types.
354   scoped_refptr<Handle> handle_;
355 
356   CefRefPtr<CefV8Exception> last_exception_;
357   bool rethrow_exceptions_;
358 
359   IMPLEMENT_REFCOUNTING(CefV8ValueImpl);
360 };
361 
362 class CefV8StackTraceImpl : public CefV8StackTrace {
363  public:
364   CefV8StackTraceImpl(v8::Isolate* isolate, v8::Local<v8::StackTrace> handle);
365 
366   CefV8StackTraceImpl(const CefV8StackTraceImpl&) = delete;
367   CefV8StackTraceImpl& operator=(const CefV8StackTraceImpl&) = delete;
368 
369   ~CefV8StackTraceImpl() override;
370 
371   bool IsValid() override;
372   int GetFrameCount() override;
373   CefRefPtr<CefV8StackFrame> GetFrame(int index) override;
374 
375  private:
376   std::vector<CefRefPtr<CefV8StackFrame>> frames_;
377 
378   IMPLEMENT_REFCOUNTING(CefV8StackTraceImpl);
379 };
380 
381 class CefV8StackFrameImpl : public CefV8StackFrame {
382  public:
383   CefV8StackFrameImpl(v8::Isolate* isolate, v8::Local<v8::StackFrame> handle);
384 
385   CefV8StackFrameImpl(const CefV8StackFrameImpl&) = delete;
386   CefV8StackFrameImpl& operator=(const CefV8StackFrameImpl&) = delete;
387 
388   ~CefV8StackFrameImpl() override;
389 
390   bool IsValid() override;
391   CefString GetScriptName() override;
392   CefString GetScriptNameOrSourceURL() override;
393   CefString GetFunctionName() override;
394   int GetLineNumber() override;
395   int GetColumn() override;
396   bool IsEval() override;
397   bool IsConstructor() override;
398 
399  private:
400   CefString script_name_;
401   CefString script_name_or_source_url_;
402   CefString function_name_;
403   int line_number_;
404   int column_;
405   bool is_eval_;
406   bool is_constructor_;
407 
408   IMPLEMENT_REFCOUNTING(CefV8StackFrameImpl);
409 };
410 
411 #endif  // CEF_LIBCEF_RENDERER_V8_IMPL_H_
412