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