fix: loading dedicated/shared worker scripts over custom protocol (#20625)

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
This commit is contained in:
Robo 2020-07-27 18:48:37 -07:00 committed by GitHub
parent 4829b0f816
commit 76e3ee6fe6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 136 additions and 5 deletions

View file

@ -103,3 +103,4 @@ fix_check_issecureeventinputenabled_in_constructor_before_setting.patch
skip_atk_toolchain_check.patch skip_atk_toolchain_check.patch
fix_missing_weakptr_check_in_preconnectmanager.patch fix_missing_weakptr_check_in_preconnectmanager.patch
revert_swiftshader_roll_in_deps.patch revert_swiftshader_roll_in_deps.patch
worker_feat_add_hook_to_notify_script_ready.patch

View file

@ -0,0 +1,92 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: deepak1556 <hop2deep@gmail.com>
Date: Thu, 17 Oct 2019 18:00:32 -0700
Subject: feat: add hook to notify script ready from WorkerScriptController
In Off-the-main-thread fetch, the WorkerGlobalScope will be in a half
initialized state until the script is finished downloading.
Doc: https://docs.google.com/document/d/1JCv8TD2nPLNC2iRCp_D1OM4I3uTS0HoEobuTymaMqgw/edit
During this stage if the global object is transformed for ex: copying properties
in DidInitializeWorkerContextOnWorkerThread hook then an access to property like
location will result in a crash WorkerGlobalScope::Url() because the script has
not been set with response URL yet.
This issue cannot happen in chromium with existing usage, but can surface when an
embedder tries to integrate Node.js in the worker. Hence, this new hook is proposed
that clearly establishes the worker script is ready for evaluation with the scope
initialized.
diff --git a/content/public/renderer/content_renderer_client.h b/content/public/renderer/content_renderer_client.h
index 8309bb7f3f284b0930c13a7e75a7f9de64fedb73..7c5c925cadc5caca5ef69eda80ccc04797b2c803 100644
--- a/content/public/renderer/content_renderer_client.h
+++ b/content/public/renderer/content_renderer_client.h
@@ -405,6 +405,11 @@ class CONTENT_EXPORT ContentRendererClient {
virtual void DidInitializeWorkerContextOnWorkerThread(
v8::Local<v8::Context> context) {}
+ // Notifies that a worker script has been downloaded, scope initialized and
+ // ready for evaluation. This function is called from the worker thread.
+ virtual void WorkerScriptReadyForEvaluationOnWorkerThread(
+ v8::Local<v8::Context> context) {}
+
// Notifies that a worker context will be destroyed. This function is called
// from the worker thread.
virtual void WillDestroyWorkerContextOnWorkerThread(
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc
index 906e86480872394d33608a954440cbc92273d0ff..27bf2e12e5f2a150fca992f1bfed88936c7cee35 100644
--- a/content/renderer/renderer_blink_platform_impl.cc
+++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -877,6 +877,12 @@ void RendererBlinkPlatformImpl::WorkerContextCreated(
worker);
}
+void RendererBlinkPlatformImpl::WorkerScriptReadyForEvaluation(
+ const v8::Local<v8::Context>& worker) {
+ GetContentClient()->renderer()->WorkerScriptReadyForEvaluationOnWorkerThread(
+ worker);
+}
+
bool RendererBlinkPlatformImpl::AllowScriptExtensionForServiceWorker(
const blink::WebSecurityOrigin& script_origin) {
return GetContentClient()->renderer()->AllowScriptExtensionForServiceWorker(
diff --git a/content/renderer/renderer_blink_platform_impl.h b/content/renderer/renderer_blink_platform_impl.h
index db58cb0be064b7944b17dd12f1d1e6c12cecfff7..5c80537e6020ae5845728130b46825f5db745a5e 100644
--- a/content/renderer/renderer_blink_platform_impl.h
+++ b/content/renderer/renderer_blink_platform_impl.h
@@ -191,6 +191,8 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
void DidStartWorkerThread() override;
void WillStopWorkerThread() override;
void WorkerContextCreated(const v8::Local<v8::Context>& worker) override;
+ void WorkerScriptReadyForEvaluation(
+ const v8::Local<v8::Context>& worker) override;
void WorkerContextWillDestroy(const v8::Local<v8::Context>& worker) override;
bool AllowScriptExtensionForServiceWorker(
const blink::WebSecurityOrigin& script_origin) override;
diff --git a/third_party/blink/public/platform/platform.h b/third_party/blink/public/platform/platform.h
index 754634fd4935cdf38168361f1491cf3aedaf8cdb..513cdea72aba0082d43268bdbfc5328fb21afb76 100644
--- a/third_party/blink/public/platform/platform.h
+++ b/third_party/blink/public/platform/platform.h
@@ -638,6 +638,8 @@ class BLINK_PLATFORM_EXPORT Platform {
virtual void DidStartWorkerThread() {}
virtual void WillStopWorkerThread() {}
virtual void WorkerContextCreated(const v8::Local<v8::Context>& worker) {}
+ virtual void WorkerScriptReadyForEvaluation(
+ const v8::Local<v8::Context>& worker) {}
virtual void WorkerContextWillDestroy(const v8::Local<v8::Context>& worker) {}
virtual bool AllowScriptExtensionForServiceWorker(
const WebSecurityOrigin& script_origin) {
diff --git a/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.cc b/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.cc
index 72b80a13cc7845236b58a4944be0ac8b314dc5fe..c227343c1c58acf94c7be2a9a2a12e921c1b5943 100644
--- a/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.cc
+++ b/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.cc
@@ -328,6 +328,8 @@ void WorkerOrWorkletScriptController::PrepareForEvaluation() {
wrapper_type_info->InstallConditionalFeatures(
context, *world_, global_object, v8::Local<v8::Object>(),
v8::Local<v8::Function>(), global_interface_template);
+
+ Platform::Current()->WorkerScriptReadyForEvaluation(context);
#endif // USE_BLINK_V8_BINDING_NEW_IDL_INTERFACE
}

View file

@ -1263,6 +1263,16 @@ void ElectronBrowserClient::RegisterNonNetworkNavigationURLLoaderFactories(
URLLoaderFactoryType::kNavigation, factories); URLLoaderFactoryType::kNavigation, factories);
} }
void ElectronBrowserClient::
RegisterNonNetworkWorkerMainResourceURLLoaderFactories(
content::BrowserContext* browser_context,
NonNetworkURLLoaderFactoryMap* factories) {
auto* protocol_registry =
ProtocolRegistry::FromBrowserContext(browser_context);
protocol_registry->RegisterURLLoaderFactories(
URLLoaderFactoryType::kWorkerMainResource, factories);
}
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS) #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
namespace { namespace {

View file

@ -178,6 +178,9 @@ class ElectronBrowserClient : public content::ContentBrowserClient,
void RegisterNonNetworkNavigationURLLoaderFactories( void RegisterNonNetworkNavigationURLLoaderFactories(
int frame_tree_node_id, int frame_tree_node_id,
NonNetworkURLLoaderFactoryMap* factories) override; NonNetworkURLLoaderFactoryMap* factories) override;
void RegisterNonNetworkWorkerMainResourceURLLoaderFactories(
content::BrowserContext* browser_context,
NonNetworkURLLoaderFactoryMap* factories) override;
void RegisterNonNetworkSubresourceURLLoaderFactories( void RegisterNonNetworkSubresourceURLLoaderFactories(
int render_process_id, int render_process_id,
int render_frame_id, int render_frame_id,

View file

@ -200,11 +200,11 @@ bool ElectronRendererClient::ShouldFork(blink::WebLocalFrame* frame,
return http_method == "GET"; return http_method == "GET";
} }
void ElectronRendererClient::DidInitializeWorkerContextOnWorkerThread( void ElectronRendererClient::WorkerScriptReadyForEvaluationOnWorkerThread(
v8::Local<v8::Context> context) { v8::Local<v8::Context> context) {
if (base::CommandLine::ForCurrentProcess()->HasSwitch( if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kNodeIntegrationInWorker)) { switches::kNodeIntegrationInWorker)) {
WebWorkerObserver::GetCurrent()->ContextCreated(context); WebWorkerObserver::GetCurrent()->WorkerScriptReadyForEvaluation(context);
} }
} }

View file

@ -47,7 +47,7 @@ class ElectronRendererClient : public RendererClientBase {
const std::string& http_method, const std::string& http_method,
bool is_initial_navigation, bool is_initial_navigation,
bool is_server_redirect) override; bool is_server_redirect) override;
void DidInitializeWorkerContextOnWorkerThread( void WorkerScriptReadyForEvaluationOnWorkerThread(
v8::Local<v8::Context> context) override; v8::Local<v8::Context> context) override;
void WillDestroyWorkerContextOnWorkerThread( void WillDestroyWorkerContextOnWorkerThread(
v8::Local<v8::Context> context) override; v8::Local<v8::Context> context) override;

View file

@ -42,7 +42,8 @@ WebWorkerObserver::~WebWorkerObserver() {
asar::ClearArchives(); asar::ClearArchives();
} }
void WebWorkerObserver::ContextCreated(v8::Local<v8::Context> worker_context) { void WebWorkerObserver::WorkerScriptReadyForEvaluation(
v8::Local<v8::Context> worker_context) {
v8::Context::Scope context_scope(worker_context); v8::Context::Scope context_scope(worker_context);
// Start the embed thread. // Start the embed thread.

View file

@ -21,7 +21,7 @@ class WebWorkerObserver {
// Returns the WebWorkerObserver for current worker thread. // Returns the WebWorkerObserver for current worker thread.
static WebWorkerObserver* GetCurrent(); static WebWorkerObserver* GetCurrent();
void ContextCreated(v8::Local<v8::Context> context); void WorkerScriptReadyForEvaluation(v8::Local<v8::Context> context);
void ContextWillDestroy(v8::Local<v8::Context> context); void ContextWillDestroy(v8::Local<v8::Context> context);
private: private:

View file

@ -441,6 +441,30 @@ describe('chromium features', () => {
w.webContents.on('crashed', () => done(new Error('WebContents crashed.'))); w.webContents.on('crashed', () => done(new Error('WebContents crashed.')));
w.loadFile(path.join(fixturesPath, 'pages', 'service-worker', 'index.html')); w.loadFile(path.join(fixturesPath, 'pages', 'service-worker', 'index.html'));
}); });
it('should not crash when nodeIntegration is enabled', (done) => {
const w = new BrowserWindow({
show: false,
webPreferences: {
nodeIntegration: true,
nodeIntegrationInWorker: true
}
});
w.webContents.on('ipc-message', (event, channel, message) => {
if (channel === 'reload') {
w.webContents.reload();
} else if (channel === 'error') {
done(`unexpected error : ${message}`);
} else if (channel === 'response') {
expect(message).to.equal('Hello from serviceWorker!');
done();
}
});
w.webContents.on('crashed', () => done(new Error('WebContents crashed.')));
w.loadFile(path.join(fixturesPath, 'pages', 'service-worker', 'index.html'));
});
}); });
describe('navigator.geolocation', () => { describe('navigator.geolocation', () => {