fix: window.open not overriding parent's webPreferences (#32057)

* fix: window.open not overriding parent's webPreferences

* test: remove "nativeWindowOpen: false" from renderer tests
This commit is contained in:
Cheng Zhao 2021-12-06 12:54:14 +09:00 committed by GitHub
parent 77287febf4
commit 35ac7fb8e6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 98 additions and 33 deletions

View file

@ -500,6 +500,14 @@ class WebFrameRenderer : public gin::Wrappable<WebFrameRenderer>,
// NOTE: openerId is internal-only.
return gin::ConvertToV8(isolate, prefs.opener_id);
} else if (pref_name == "isWebView") {
// FIXME(zcbenz): For child windows opened with window.open('') from
// webview, the WebPreferences is inherited from webview and the value
// of |is_webview| is wrong.
// Please check ElectronRenderFrameObserver::DidInstallConditionalFeatures
// for the background.
auto* web_frame = render_frame->GetWebFrame();
if (web_frame->Opener())
return gin::ConvertToV8(isolate, false);
return gin::ConvertToV8(isolate, prefs.is_webview);
} else if (pref_name == options::kHiddenPage) {
// NOTE: hiddenPage is internal-only.

View file

@ -31,6 +31,7 @@
#include "third_party/blink/public/web/web_element.h"
#include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/blink/public/web/web_script_source.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h" // nogncheck
#include "ui/base/resource/resource_bundle.h"
namespace electron {
@ -58,12 +59,57 @@ ElectronRenderFrameObserver::ElectronRenderFrameObserver(
}
void ElectronRenderFrameObserver::DidClearWindowObject() {
// Do a delayed Node.js initialization for child window.
// Check DidInstallConditionalFeatures below for the background.
auto* web_frame =
static_cast<blink::WebLocalFrameImpl*>(render_frame_->GetWebFrame());
if (has_delayed_node_initialization_ && web_frame->Opener() &&
!web_frame->IsOnInitialEmptyDocument()) {
v8::Isolate* isolate = blink::MainThreadIsolate();
v8::HandleScope handle_scope(isolate);
v8::MicrotasksScope microtasks_scope(
isolate, v8::MicrotasksScope::kDoNotRunMicrotasks);
v8::Handle<v8::Context> context = web_frame->MainWorldScriptContext();
v8::Context::Scope context_scope(context);
// DidClearWindowObject only emits for the main world.
DidInstallConditionalFeatures(context, MAIN_WORLD_ID);
}
renderer_client_->DidClearWindowObject(render_frame_);
}
void ElectronRenderFrameObserver::DidInstallConditionalFeatures(
v8::Handle<v8::Context> context,
int world_id) {
// When a child window is created with window.open, its WebPreferences will
// be copied from its parent, and Chromium will intialize JS context in it
// immediately.
// Normally the WebPreferences is overriden in browser before navigation,
// but this behavior bypasses the browser side navigation and the child
// window will get wrong WebPreferences in the initialization.
// This will end up initializing Node.js in the child window with wrong
// WebPreferences, leads to problem that child window having node integration
// while "nodeIntegration=no" is passed.
// We work around this issue by delaying the child window's initialization of
// Node.js if this is the initial empty document, and only do it when the
// acutal page has started to load.
auto* web_frame =
static_cast<blink::WebLocalFrameImpl*>(render_frame_->GetWebFrame());
if (web_frame->Opener() && web_frame->IsOnInitialEmptyDocument()) {
// FIXME(zcbenz): Chromium does not do any browser side navigation for
// window.open('about:blank'), so there is no way to override WebPreferences
// of it. We should not delay Node.js initialization as there will be no
// further loadings.
// Please check http://crbug.com/1215096 for updates which may help remove
// this hack.
GURL url = web_frame->GetDocument().Url();
if (!url.IsAboutBlank()) {
has_delayed_node_initialization_ = true;
return;
}
}
has_delayed_node_initialization_ = false;
auto* isolate = context->GetIsolate();
v8::MicrotasksScope microtasks_scope(
isolate, v8::MicrotasksScope::kDoNotRunMicrotasks);

View file

@ -44,6 +44,7 @@ class ElectronRenderFrameObserver : public content::RenderFrameObserver {
void OnTakeHeapSnapshot(IPC::PlatformFileForTransit file_handle,
const std::string& channel);
bool has_delayed_node_initialization_ = false;
content::RenderFrame* render_frame_;
RendererClientBase* renderer_client_;
};

View file

@ -157,6 +157,7 @@ void ElectronRendererClient::WillReleaseScriptContext(
// We also do this if we have disable electron site instance overrides to
// avoid memory leaks
auto prefs = render_frame->GetBlinkPreferences();
gin_helper::MicrotasksScope microtasks_scope(env->isolate());
node::FreeEnvironment(env);
if (env == node_bindings_->uv_env())
node::FreeIsolateData(node_bindings_->isolate_data());

View file

@ -37,6 +37,8 @@ WebWorkerObserver::WebWorkerObserver()
WebWorkerObserver::~WebWorkerObserver() {
lazy_tls.Pointer()->Set(nullptr);
gin_helper::MicrotasksScope microtasks_scope(
node_bindings_->uv_env()->isolate());
node::FreeEnvironment(node_bindings_->uv_env());
node::FreeIsolateData(node_bindings_->isolate_data());
}