diff --git a/shell/renderer/api/electron_api_context_bridge.cc b/shell/renderer/api/electron_api_context_bridge.cc index 030836ee9320..10a87a4f0463 100644 --- a/shell/renderer/api/electron_api_context_bridge.cc +++ b/shell/renderer/api/electron_api_context_bridge.cc @@ -112,26 +112,24 @@ bool IsPlainArray(const v8::Local& arr) { return !arr->IsTypedArray(); } -void SetPrivate(v8::Local context, +void SetPrivate(v8::Isolate* const isolate, + v8::Local context, v8::Local target, const std::string_view key, v8::Local value) { target - ->SetPrivate( - context, - v8::Private::ForApi(context->GetIsolate(), - gin::StringToV8(context->GetIsolate(), key)), - value) + ->SetPrivate(context, + v8::Private::ForApi(isolate, gin::StringToV8(isolate, key)), + value) .Check(); } -v8::MaybeLocal GetPrivate(v8::Local context, +v8::MaybeLocal GetPrivate(v8::Isolate* const isolate, + v8::Local context, v8::Local target, const std::string_view key) { return target->GetPrivate( - context, - v8::Private::ForApi(context->GetIsolate(), - gin::StringToV8(context->GetIsolate(), key))); + context, v8::Private::ForApi(isolate, gin::StringToV8(isolate, key))); } } // namespace @@ -140,8 +138,10 @@ v8::MaybeLocal GetPrivate(v8::Local context, void ProxyFunctionWrapper(const v8::FunctionCallbackInfo& info); v8::MaybeLocal CreateProxyForAPI( const v8::Local& api_object, + v8::Isolate* const source_isolate, const v8::Local& source_context, const blink::ExecutionContext* source_execution_context, + v8::Isolate* const destination_isolate, const v8::Local& destination_context, context_bridge::ObjectCache* object_cache, bool support_dynamic_properties, @@ -149,8 +149,10 @@ v8::MaybeLocal CreateProxyForAPI( BridgeErrorTarget error_target); v8::MaybeLocal PassValueToOtherContextInner( + v8::Isolate* const source_isolate, v8::Local source_context, const blink::ExecutionContext* source_execution_context, + v8::Isolate* const destination_isolate, v8::Local destination_context, v8::Local value, v8::Local parent_value, @@ -158,8 +160,6 @@ v8::MaybeLocal PassValueToOtherContextInner( bool support_dynamic_properties, int recursion_depth, BridgeErrorTarget error_target) { - v8::Isolate* const source_isolate = source_context->GetIsolate(); - TRACE_EVENT0("electron", "ContextBridge::PassValueToOtherContextInner"); if (recursion_depth >= kMaxRecursion) { v8::Context::Scope error_scope(error_target == BridgeErrorTarget::kSource @@ -193,8 +193,8 @@ v8::MaybeLocal PassValueToOtherContextInner( // the global handle at the right time. if (value->IsFunction()) { auto func = value.As(); - v8::MaybeLocal maybe_original_fn = - GetPrivate(source_context, func, kOriginalFunctionPrivateKey); + v8::MaybeLocal maybe_original_fn = GetPrivate( + source_isolate, source_context, func, kOriginalFunctionPrivateKey); { v8::Context::Scope destination_scope(destination_context); @@ -213,21 +213,22 @@ v8::MaybeLocal PassValueToOtherContextInner( return v8::MaybeLocal(proxy_func); } - v8::Local state = - v8::Object::New(destination_context->GetIsolate()); - SetPrivate(destination_context, state, kProxyFunctionPrivateKey, func); - SetPrivate(destination_context, state, kProxyFunctionReceiverPrivateKey, - parent_value); - SetPrivate(destination_context, state, - kSupportsDynamicPropertiesPrivateKey, - gin::ConvertToV8(destination_context->GetIsolate(), - support_dynamic_properties)); + v8::Local state = v8::Object::New(destination_isolate); + SetPrivate(destination_isolate, destination_context, state, + kProxyFunctionPrivateKey, func); + SetPrivate(destination_isolate, destination_context, state, + kProxyFunctionReceiverPrivateKey, parent_value); + SetPrivate( + destination_isolate, destination_context, state, + kSupportsDynamicPropertiesPrivateKey, + gin::ConvertToV8(destination_isolate, support_dynamic_properties)); if (!v8::Function::New(destination_context, ProxyFunctionWrapper, state) .ToLocal(&proxy_func)) return {}; - SetPrivate(destination_context, proxy_func.As(), - kOriginalFunctionPrivateKey, func); + SetPrivate(destination_isolate, destination_context, + proxy_func.As(), kOriginalFunctionPrivateKey, + func); object_cache->CacheProxiedObject(value, proxy_func); return v8::MaybeLocal(proxy_func); } @@ -242,14 +243,14 @@ v8::MaybeLocal PassValueToOtherContextInner( // left dangling auto proxied_promise = std::make_shared>>( - destination_context->GetIsolate()); + destination_isolate); v8::Local proxied_promise_handle = proxied_promise->GetHandle(); v8::Global global_then_source_context(source_isolate, source_context); v8::Global global_then_destination_context( - destination_context->GetIsolate(), destination_context); + destination_isolate, destination_context); global_then_source_context.SetWeak(); global_then_destination_context.SetWeak(); auto then_cb = base::BindOnce( @@ -289,14 +290,14 @@ v8::MaybeLocal PassValueToOtherContextInner( if (!val.IsEmpty()) proxied_promise->Resolve(val.ToLocalChecked()); }, - proxied_promise, destination_context->GetIsolate(), + proxied_promise, destination_isolate, std::move(global_then_source_context), std::move(global_then_destination_context)); v8::Global global_catch_source_context(source_isolate, source_context); v8::Global global_catch_destination_context( - destination_context->GetIsolate(), destination_context); + destination_isolate, destination_context); global_catch_source_context.SetWeak(); global_catch_destination_context.SetWeak(); auto catch_cb = base::BindOnce( @@ -335,15 +336,15 @@ v8::MaybeLocal PassValueToOtherContextInner( if (!val.IsEmpty()) proxied_promise->Reject(val.ToLocalChecked()); }, - proxied_promise, destination_context->GetIsolate(), + proxied_promise, destination_isolate, std::move(global_catch_source_context), std::move(global_catch_destination_context)); std::ignore = source_promise->Then( source_context, - gin::ConvertToV8(destination_context->GetIsolate(), std::move(then_cb)) + gin::ConvertToV8(destination_isolate, std::move(then_cb)) .As(), - gin::ConvertToV8(destination_context->GetIsolate(), std::move(catch_cb)) + gin::ConvertToV8(destination_isolate, std::move(catch_cb)) .As()); object_cache->CacheProxiedObject(value, proxied_promise_handle); @@ -366,8 +367,7 @@ v8::MaybeLocal PassValueToOtherContextInner( v8::Exception::Error(message.As())); } return v8::MaybeLocal(v8::Exception::Error( - v8::Exception::CreateMessage(destination_context->GetIsolate(), value) - ->Get())); + v8::Exception::CreateMessage(destination_isolate, value)->Get())); } // Manually go through the array and pass each value individually into a new @@ -378,10 +378,11 @@ v8::MaybeLocal PassValueToOtherContextInner( v8::Local arr = value.As(); size_t length = arr->Length(); v8::Local cloned_arr = - v8::Array::New(destination_context->GetIsolate(), length); + v8::Array::New(destination_isolate, length); for (size_t i = 0; i < length; i++) { auto value_for_array = PassValueToOtherContextInner( - source_context, source_execution_context, destination_context, + source_isolate, source_context, source_execution_context, + destination_isolate, destination_context, arr->Get(source_context, i).ToLocalChecked(), value, object_cache, support_dynamic_properties, recursion_depth + 1, error_target); if (value_for_array.IsEmpty()) @@ -399,21 +400,19 @@ v8::MaybeLocal PassValueToOtherContextInner( // Clone certain DOM APIs only within Window contexts. if (source_execution_context->IsWindow()) { // Custom logic to "clone" Element references - blink::WebElement elem = blink::WebElement::FromV8Value( - destination_context->GetIsolate(), value); + blink::WebElement elem = + blink::WebElement::FromV8Value(destination_isolate, value); if (!elem.IsNull()) { v8::Context::Scope destination_context_scope(destination_context); - return v8::MaybeLocal( - elem.ToV8Value(destination_context->GetIsolate())); + return v8::MaybeLocal(elem.ToV8Value(destination_isolate)); } // Custom logic to "clone" Blob references blink::WebBlob blob = - blink::WebBlob::FromV8Value(destination_context->GetIsolate(), value); + blink::WebBlob::FromV8Value(destination_isolate, value); if (!blob.IsNull()) { v8::Context::Scope destination_context_scope(destination_context); - return v8::MaybeLocal( - blob.ToV8Value(destination_context->GetIsolate())); + return v8::MaybeLocal(blob.ToV8Value(destination_isolate)); } } @@ -421,9 +420,9 @@ v8::MaybeLocal PassValueToOtherContextInner( if (IsPlainObject(value)) { auto object_value = value.As(); auto passed_value = CreateProxyForAPI( - object_value, source_context, source_execution_context, - destination_context, object_cache, support_dynamic_properties, - recursion_depth + 1, error_target); + object_value, source_isolate, source_context, source_execution_context, + destination_isolate, destination_context, object_cache, + support_dynamic_properties, recursion_depth + 1, error_target); if (passed_value.IsEmpty()) return {}; return v8::MaybeLocal(passed_value.ToLocalChecked()); @@ -435,9 +434,12 @@ v8::MaybeLocal PassValueToOtherContextInner( v8::Local error_context = error_target == BridgeErrorTarget::kSource ? source_context : destination_context; - v8::Context::Scope error_scope(error_context); + v8::Context::Scope error_scope{error_context}; // V8 serializer will throw an error if required - if (!gin::ConvertFromV8(error_context->GetIsolate(), value, &ret)) { + v8::Isolate* const error_isolate = + error_target == BridgeErrorTarget::kSource ? source_isolate + : destination_isolate; + if (!gin::ConvertFromV8(error_isolate, value, &ret)) { return {}; } } @@ -445,7 +447,7 @@ v8::MaybeLocal PassValueToOtherContextInner( { v8::Context::Scope destination_context_scope(destination_context); v8::Local cloned_value = - gin::ConvertToV8(destination_context->GetIsolate(), ret); + gin::ConvertToV8(destination_isolate, ret); object_cache->CacheProxiedObject(value, cloned_value); return v8::MaybeLocal(cloned_value); } @@ -469,7 +471,8 @@ v8::MaybeLocal PassValueToOtherContext( blink::ExecutionContext::From(source_context); DCHECK(source_execution_context); return PassValueToOtherContextInner( - source_context, source_execution_context, destination_context, value, + source_context->GetIsolate(), source_context, source_execution_context, + destination_context->GetIsolate(), destination_context, value, parent_value, object_cache, support_dynamic_properties, 0, error_target); } @@ -478,27 +481,28 @@ void ProxyFunctionWrapper(const v8::FunctionCallbackInfo& info) { CHECK(info.Data()->IsObject()); v8::Local data = info.Data().As(); bool support_dynamic_properties = false; - gin::Arguments args(info); + gin::Arguments args{info}; + v8::Isolate* const isolate = args.isolate(); // Context the proxy function was called from - v8::Local calling_context = args.isolate()->GetCurrentContext(); + v8::Local calling_context = isolate->GetCurrentContext(); // Pull the original function and its context off of the data private key - v8::MaybeLocal sdp_value = - GetPrivate(calling_context, data, kSupportsDynamicPropertiesPrivateKey); + v8::MaybeLocal sdp_value = GetPrivate( + isolate, calling_context, data, kSupportsDynamicPropertiesPrivateKey); v8::MaybeLocal maybe_func = - GetPrivate(calling_context, data, kProxyFunctionPrivateKey); - v8::MaybeLocal maybe_recv = - GetPrivate(calling_context, data, kProxyFunctionReceiverPrivateKey); + GetPrivate(isolate, calling_context, data, kProxyFunctionPrivateKey); + v8::MaybeLocal maybe_recv = GetPrivate( + isolate, calling_context, data, kProxyFunctionReceiverPrivateKey); v8::Local func_value; if (sdp_value.IsEmpty() || maybe_func.IsEmpty() || maybe_recv.IsEmpty() || - !gin::ConvertFromV8(args.isolate(), sdp_value.ToLocalChecked(), + !gin::ConvertFromV8(isolate, sdp_value.ToLocalChecked(), &support_dynamic_properties) || !maybe_func.ToLocal(&func_value)) return; v8::Local func = func_value.As(); v8::Local func_owning_context = - func->GetCreationContextChecked(args.isolate()); + func->GetCreationContextChecked(isolate); { v8::Context::Scope func_owning_context_scope(func_owning_context); @@ -524,7 +528,7 @@ void ProxyFunctionWrapper(const v8::FunctionCallbackInfo& info) { bool did_error = false; v8::Local error_message; { - v8::TryCatch try_catch(args.isolate()); + v8::TryCatch try_catch(isolate); maybe_return_value = func->Call(func_owning_context, maybe_recv.ToLocalChecked(), proxied_args.size(), proxied_args.data()); @@ -539,22 +543,21 @@ void ProxyFunctionWrapper(const v8::FunctionCallbackInfo& info) { if (!exception->IsNull() && exception->IsObject()) { v8::MaybeLocal maybe_message = exception.As()->Get( - func_owning_context, - gin::ConvertToV8(args.isolate(), "message")); + func_owning_context, gin::ConvertToV8(isolate, "message")); if (!maybe_message.ToLocal(&error_message) || !error_message->IsString()) { - error_message = gin::StringToV8(args.isolate(), err_msg); + error_message = gin::StringToV8(isolate, err_msg); } } else { - error_message = gin::StringToV8(args.isolate(), err_msg); + error_message = gin::StringToV8(isolate, err_msg); } } } if (did_error) { v8::Context::Scope calling_context_scope(calling_context); - args.isolate()->ThrowException( + isolate->ThrowException( v8::Exception::Error(error_message.As())); return; } @@ -579,7 +582,7 @@ void ProxyFunctionWrapper(const v8::FunctionCallbackInfo& info) { v8::MaybeLocal ret; v8::Local exception; { - v8::TryCatch try_catch(args.isolate()); + v8::TryCatch try_catch(isolate); ret = PassValueToOtherContext( func_owning_context, calling_context, maybe_return_value.ToLocalChecked(), func_owning_context->Global(), @@ -598,10 +601,10 @@ void ProxyFunctionWrapper(const v8::FunctionCallbackInfo& info) { "An unknown exception occurred while sending a function return " "value over the context bridge, an error " "occurred but a valid exception was not thrown."; - args.isolate()->ThrowException(v8::Exception::Error( - gin::StringToV8(args.isolate(), err_msg).As())); + isolate->ThrowException(v8::Exception::Error( + gin::StringToV8(isolate, err_msg).As())); } else { - args.isolate()->ThrowException(v8::Exception::Error(exception)); + isolate->ThrowException(v8::Exception::Error(exception)); } return; } @@ -614,19 +617,20 @@ void ProxyFunctionWrapper(const v8::FunctionCallbackInfo& info) { v8::MaybeLocal CreateProxyForAPI( const v8::Local& api_object, + v8::Isolate* const source_isolate, const v8::Local& source_context, const blink::ExecutionContext* source_execution_context, + v8::Isolate* const destination_isolate, const v8::Local& destination_context, context_bridge::ObjectCache* object_cache, bool support_dynamic_properties, int recursion_depth, BridgeErrorTarget error_target) { - gin_helper::Dictionary api(source_context->GetIsolate(), api_object); + gin_helper::Dictionary api{source_isolate, api_object}; { v8::Context::Scope destination_context_scope(destination_context); - auto proxy = - gin_helper::Dictionary::CreateEmpty(destination_context->GetIsolate()); + auto proxy = gin_helper::Dictionary::CreateEmpty(destination_isolate); object_cache->CacheProxiedObject(api.GetHandle(), proxy.GetHandle()); auto maybe_keys = api.GetHandle()->GetOwnPropertyNames( source_context, static_cast(v8::ONLY_ENUMERABLE)); @@ -660,19 +664,19 @@ v8::MaybeLocal CreateProxyForAPI( v8::Local setter_proxy; if (!getter.IsEmpty()) { if (!PassValueToOtherContextInner( - source_context, source_execution_context, - destination_context, getter, api.GetHandle(), - object_cache, support_dynamic_properties, 1, - error_target) + source_isolate, source_context, source_execution_context, + destination_isolate, destination_context, getter, + api.GetHandle(), object_cache, + support_dynamic_properties, 1, error_target) .ToLocal(&getter_proxy)) continue; } if (!setter.IsEmpty()) { if (!PassValueToOtherContextInner( - source_context, source_execution_context, - destination_context, setter, api.GetHandle(), - object_cache, support_dynamic_properties, 1, - error_target) + source_isolate, source_context, source_execution_context, + destination_isolate, destination_context, setter, + api.GetHandle(), object_cache, + support_dynamic_properties, 1, error_target) .ToLocal(&setter_proxy)) continue; } @@ -692,9 +696,10 @@ v8::MaybeLocal CreateProxyForAPI( continue; auto passed_value = PassValueToOtherContextInner( - source_context, source_execution_context, destination_context, - value, api.GetHandle(), object_cache, support_dynamic_properties, - recursion_depth + 1, error_target); + source_isolate, source_context, source_execution_context, + destination_isolate, destination_context, value, api.GetHandle(), + object_cache, support_dynamic_properties, recursion_depth + 1, + error_target); if (passed_value.IsEmpty()) return {};