refactor: implement <webview> using contextBridge (#29037)
* refactor: implement <webview> using contextBridge * chore: address PR feedback * chore: address PR feedback * fix: check for HTMLIFrameElement instance in attachGuest
This commit is contained in:
parent
5e6f8349ec
commit
c68c65f383
17 changed files with 220 additions and 214 deletions
|
@ -130,18 +130,6 @@ bool SpellCheckWord(content::RenderFrame* render_frame,
|
|||
|
||||
#endif
|
||||
|
||||
class RenderFrameStatus final : public content::RenderFrameObserver {
|
||||
public:
|
||||
explicit RenderFrameStatus(content::RenderFrame* render_frame)
|
||||
: content::RenderFrameObserver(render_frame) {}
|
||||
~RenderFrameStatus() final = default;
|
||||
|
||||
bool is_ok() { return render_frame() != nullptr; }
|
||||
|
||||
// RenderFrameObserver implementation.
|
||||
void OnDestruct() final {}
|
||||
};
|
||||
|
||||
class ScriptExecutionCallback : public blink::WebScriptExecutionCallback {
|
||||
public:
|
||||
// for compatibility with the older version of this, error is after result
|
||||
|
@ -377,7 +365,7 @@ class WebFrameRenderer : public gin::Wrappable<WebFrameRenderer>,
|
|||
.SetMethod("setVisualZoomLevelLimits",
|
||||
&WebFrameRenderer::SetVisualZoomLevelLimits)
|
||||
.SetMethod("allowGuestViewElementDefinition",
|
||||
&WebFrameRenderer::AllowGuestViewElementDefinition)
|
||||
&RendererClientBase::AllowGuestViewElementDefinition)
|
||||
.SetMethod("insertText", &WebFrameRenderer::InsertText)
|
||||
.SetMethod("insertCSS", &WebFrameRenderer::InsertCSS)
|
||||
.SetMethod("removeInsertedCSS", &WebFrameRenderer::RemoveInsertedCSS)
|
||||
|
@ -541,31 +529,12 @@ class WebFrameRenderer : public gin::Wrappable<WebFrameRenderer>,
|
|||
web_frame->View()->SetDefaultPageScaleLimits(min_level, max_level);
|
||||
}
|
||||
|
||||
void AllowGuestViewElementDefinition(v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> context,
|
||||
v8::Local<v8::Function> register_cb) {
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
v8::Context::Scope context_scope(context->CreationContext());
|
||||
blink::WebCustomElement::EmbedderNamesAllowedScope embedder_names_scope;
|
||||
|
||||
content::RenderFrame* render_frame;
|
||||
if (!MaybeGetRenderFrame(isolate, "allowGuestViewElementDefinition",
|
||||
&render_frame))
|
||||
return;
|
||||
|
||||
render_frame->GetWebFrame()->RequestExecuteV8Function(
|
||||
context->CreationContext(), register_cb, v8::Null(isolate), 0, nullptr,
|
||||
nullptr);
|
||||
}
|
||||
|
||||
static int GetWebFrameId(v8::Local<v8::Object> content_window) {
|
||||
// Get the WebLocalFrame before (possibly) executing any user-space JS while
|
||||
// getting the |params|. We track the status of the RenderFrame via an
|
||||
// observer in case it is deleted during user code execution.
|
||||
content::RenderFrame* render_frame = GetRenderFrame(content_window);
|
||||
RenderFrameStatus render_frame_status(render_frame);
|
||||
|
||||
if (!render_frame_status.is_ok())
|
||||
if (!render_frame)
|
||||
return -1;
|
||||
|
||||
blink::WebLocalFrame* frame = render_frame->GetWebFrame();
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
#include "shell/common/gin_helper/event_emitter_caller.h"
|
||||
#include "shell/common/node_bindings.h"
|
||||
#include "shell/common/node_includes.h"
|
||||
#include "shell/common/node_util.h"
|
||||
#include "shell/common/options_switches.h"
|
||||
#include "shell/renderer/electron_render_frame_observer.h"
|
||||
#include "shell/renderer/web_worker_observer.h"
|
||||
|
@ -198,32 +197,6 @@ void ElectronRendererClient::WillDestroyWorkerContextOnWorkerThread(
|
|||
}
|
||||
}
|
||||
|
||||
void ElectronRendererClient::SetupMainWorldOverrides(
|
||||
v8::Handle<v8::Context> context,
|
||||
content::RenderFrame* render_frame) {
|
||||
auto prefs = render_frame->GetBlinkPreferences();
|
||||
// We only need to run the isolated bundle if webview is enabled
|
||||
if (!prefs.webview_tag)
|
||||
return;
|
||||
// Setup window overrides in the main world context
|
||||
// Wrap the bundle into a function that receives the isolatedWorld as
|
||||
// an argument.
|
||||
auto* isolate = context->GetIsolate();
|
||||
std::vector<v8::Local<v8::String>> isolated_bundle_params = {
|
||||
node::FIXED_ONE_BYTE_STRING(isolate, "nodeProcess"),
|
||||
node::FIXED_ONE_BYTE_STRING(isolate, "isolatedWorld")};
|
||||
|
||||
auto* env = GetEnvironment(render_frame);
|
||||
DCHECK(env);
|
||||
|
||||
std::vector<v8::Local<v8::Value>> isolated_bundle_args = {
|
||||
env->process_object(),
|
||||
GetContext(render_frame->GetWebFrame(), isolate)->Global()};
|
||||
|
||||
util::CompileAndCall(context, "electron/js2c/isolated_bundle",
|
||||
&isolated_bundle_params, &isolated_bundle_args, nullptr);
|
||||
}
|
||||
|
||||
node::Environment* ElectronRendererClient::GetEnvironment(
|
||||
content::RenderFrame* render_frame) const {
|
||||
if (injected_frames_.find(render_frame) == injected_frames_.end())
|
||||
|
|
|
@ -31,8 +31,6 @@ class ElectronRendererClient : public RendererClientBase {
|
|||
content::RenderFrame* render_frame) override;
|
||||
void WillReleaseScriptContext(v8::Handle<v8::Context> context,
|
||||
content::RenderFrame* render_frame) override;
|
||||
void SetupMainWorldOverrides(v8::Handle<v8::Context> context,
|
||||
content::RenderFrame* render_frame) override;
|
||||
|
||||
private:
|
||||
// content::ContentRendererClient:
|
||||
|
|
|
@ -241,34 +241,6 @@ void ElectronSandboxedRendererClient::DidCreateScriptContext(
|
|||
InvokeHiddenCallback(context, kLifecycleKey, "onLoaded");
|
||||
}
|
||||
|
||||
void ElectronSandboxedRendererClient::SetupMainWorldOverrides(
|
||||
v8::Handle<v8::Context> context,
|
||||
content::RenderFrame* render_frame) {
|
||||
auto prefs = render_frame->GetBlinkPreferences();
|
||||
// We only need to run the isolated bundle if webview is enabled
|
||||
if (!prefs.webview_tag)
|
||||
return;
|
||||
|
||||
// Setup window overrides in the main world context
|
||||
// Wrap the bundle into a function that receives the isolatedWorld as
|
||||
// an argument.
|
||||
auto* isolate = context->GetIsolate();
|
||||
|
||||
gin_helper::Dictionary process = gin::Dictionary::CreateEmpty(isolate);
|
||||
process.SetMethod("_linkedBinding", GetBinding);
|
||||
|
||||
std::vector<v8::Local<v8::String>> isolated_bundle_params = {
|
||||
node::FIXED_ONE_BYTE_STRING(isolate, "nodeProcess"),
|
||||
node::FIXED_ONE_BYTE_STRING(isolate, "isolatedWorld")};
|
||||
|
||||
std::vector<v8::Local<v8::Value>> isolated_bundle_args = {
|
||||
process.GetHandle(),
|
||||
GetContext(render_frame->GetWebFrame(), isolate)->Global()};
|
||||
|
||||
util::CompileAndCall(context, "electron/js2c/isolated_bundle",
|
||||
&isolated_bundle_params, &isolated_bundle_args, nullptr);
|
||||
}
|
||||
|
||||
void ElectronSandboxedRendererClient::WillReleaseScriptContext(
|
||||
v8::Handle<v8::Context> context,
|
||||
content::RenderFrame* render_frame) {
|
||||
|
|
|
@ -27,8 +27,6 @@ class ElectronSandboxedRendererClient : public RendererClientBase {
|
|||
content::RenderFrame* render_frame) override;
|
||||
void WillReleaseScriptContext(v8::Handle<v8::Context> context,
|
||||
content::RenderFrame* render_frame) override;
|
||||
void SetupMainWorldOverrides(v8::Handle<v8::Context> context,
|
||||
content::RenderFrame* render_frame) override;
|
||||
// content::ContentRendererClient:
|
||||
void RenderFrameCreated(content::RenderFrame*) override;
|
||||
void RenderViewCreated(content::RenderView*) override;
|
||||
|
|
|
@ -22,10 +22,15 @@
|
|||
#include "electron/buildflags/buildflags.h"
|
||||
#include "media/blink/multibuffer_data_source.h"
|
||||
#include "printing/buildflags/buildflags.h"
|
||||
#include "shell/common/api/electron_api_native_image.h"
|
||||
#include "shell/common/color_util.h"
|
||||
#include "shell/common/gin_helper/dictionary.h"
|
||||
#include "shell/common/node_includes.h"
|
||||
#include "shell/common/node_util.h"
|
||||
#include "shell/common/options_switches.h"
|
||||
#include "shell/common/world_ids.h"
|
||||
#include "shell/renderer/api/context_bridge/object_cache.h"
|
||||
#include "shell/renderer/api/electron_api_context_bridge.h"
|
||||
#include "shell/renderer/browser_exposed_renderer_interfaces.h"
|
||||
#include "shell/renderer/content_settings_observer.h"
|
||||
#include "shell/renderer/electron_api_service_impl.h"
|
||||
|
@ -85,6 +90,21 @@ namespace electron {
|
|||
|
||||
namespace {
|
||||
|
||||
content::RenderFrame* GetRenderFrame(v8::Local<v8::Object> value) {
|
||||
v8::Local<v8::Context> context = value->CreationContext();
|
||||
if (context.IsEmpty())
|
||||
return nullptr;
|
||||
blink::WebLocalFrame* frame = blink::WebLocalFrame::FrameForContext(context);
|
||||
if (!frame)
|
||||
return nullptr;
|
||||
return content::RenderFrame::FromWebFrame(frame);
|
||||
}
|
||||
|
||||
void SetIsWebView(v8::Isolate* isolate, v8::Local<v8::Object> object) {
|
||||
gin_helper::Dictionary dict(isolate, object);
|
||||
dict.SetHidden("isWebView", true);
|
||||
}
|
||||
|
||||
std::vector<std::string> ParseSchemesCLISwitch(base::CommandLine* command_line,
|
||||
const char* switch_name) {
|
||||
std::string custom_schemes = command_line->GetSwitchValueASCII(switch_name);
|
||||
|
@ -496,11 +516,70 @@ bool RendererClientBase::IsWebViewFrame(
|
|||
|
||||
gin_helper::Dictionary frame_element_dict(isolate, frame_element);
|
||||
|
||||
v8::Local<v8::Object> internal;
|
||||
if (!frame_element_dict.GetHidden("internal", &internal))
|
||||
return false;
|
||||
bool is_webview = false;
|
||||
return frame_element_dict.GetHidden("isWebView", &is_webview) && is_webview;
|
||||
}
|
||||
|
||||
return !internal.IsEmpty();
|
||||
void RendererClientBase::SetupMainWorldOverrides(
|
||||
v8::Handle<v8::Context> context,
|
||||
content::RenderFrame* render_frame) {
|
||||
auto prefs = render_frame->GetBlinkPreferences();
|
||||
// We only need to run the isolated bundle if webview is enabled
|
||||
if (!prefs.webview_tag)
|
||||
return;
|
||||
|
||||
// Setup window overrides in the main world context
|
||||
// Wrap the bundle into a function that receives the isolatedApi as
|
||||
// an argument.
|
||||
auto* isolate = context->GetIsolate();
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
v8::Context::Scope context_scope(context);
|
||||
|
||||
gin_helper::Dictionary isolated_api = gin::Dictionary::CreateEmpty(isolate);
|
||||
isolated_api.SetMethod("allowGuestViewElementDefinition",
|
||||
&AllowGuestViewElementDefinition);
|
||||
isolated_api.SetMethod("setIsWebView", &SetIsWebView);
|
||||
isolated_api.SetMethod("createNativeImage", &api::NativeImage::CreateEmpty);
|
||||
|
||||
auto source_context = GetContext(render_frame->GetWebFrame(), isolate);
|
||||
gin_helper::Dictionary global(isolate, source_context->Global());
|
||||
|
||||
v8::Local<v8::Value> guest_view_internal;
|
||||
if (global.GetHidden("guestViewInternal", &guest_view_internal)) {
|
||||
api::context_bridge::ObjectCache object_cache;
|
||||
auto result = api::PassValueToOtherContext(
|
||||
source_context, context, guest_view_internal, &object_cache, false, 0);
|
||||
if (!result.IsEmpty()) {
|
||||
isolated_api.Set("guestViewInternal", result.ToLocalChecked());
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<v8::Local<v8::String>> isolated_bundle_params = {
|
||||
node::FIXED_ONE_BYTE_STRING(isolate, "isolatedApi")};
|
||||
|
||||
std::vector<v8::Local<v8::Value>> isolated_bundle_args = {
|
||||
isolated_api.GetHandle()};
|
||||
|
||||
util::CompileAndCall(context, "electron/js2c/isolated_bundle",
|
||||
&isolated_bundle_params, &isolated_bundle_args, nullptr);
|
||||
}
|
||||
|
||||
// static
|
||||
void RendererClientBase::AllowGuestViewElementDefinition(
|
||||
v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> context,
|
||||
v8::Local<v8::Function> register_cb) {
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
v8::Context::Scope context_scope(context->CreationContext());
|
||||
blink::WebCustomElement::EmbedderNamesAllowedScope embedder_names_scope;
|
||||
|
||||
content::RenderFrame* render_frame = GetRenderFrame(context);
|
||||
if (!render_frame)
|
||||
return;
|
||||
|
||||
render_frame->GetWebFrame()->RequestExecuteV8Function(
|
||||
context->CreationContext(), register_cb, v8::Null(isolate), 0, nullptr,
|
||||
nullptr);
|
||||
}
|
||||
|
||||
} // namespace electron
|
||||
|
|
|
@ -74,7 +74,7 @@ class RendererClientBase : public content::ContentRendererClient
|
|||
content::RenderFrame* render_frame) = 0;
|
||||
virtual void DidClearWindowObject(content::RenderFrame* render_frame);
|
||||
virtual void SetupMainWorldOverrides(v8::Handle<v8::Context> context,
|
||||
content::RenderFrame* render_frame) = 0;
|
||||
content::RenderFrame* render_frame);
|
||||
|
||||
std::unique_ptr<blink::WebPrescientNetworking> CreatePrescientNetworking(
|
||||
content::RenderFrame* render_frame) override;
|
||||
|
@ -86,7 +86,11 @@ class RendererClientBase : public content::ContentRendererClient
|
|||
static v8::Local<v8::Value> RunScript(v8::Local<v8::Context> context,
|
||||
v8::Local<v8::String> source);
|
||||
|
||||
// v8Util.getHiddenValue(window.frameElement, 'internal')
|
||||
static void AllowGuestViewElementDefinition(
|
||||
v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> context,
|
||||
v8::Local<v8::Function> register_cb);
|
||||
|
||||
bool IsWebViewFrame(v8::Handle<v8::Context> context,
|
||||
content::RenderFrame* render_frame) const;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue