refactor: process event emitting for sandboxed renderers (#37109)
Co-authored-by: Milan Burda <miburda@microsoft.com>
This commit is contained in:
parent
6e0d63c356
commit
446c7809cc
3 changed files with 47 additions and 65 deletions
|
@ -41,25 +41,15 @@ const loadableModules = new Map<string, Function>([
|
||||||
['url', () => require('url')]
|
['url', () => require('url')]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// ElectronSandboxedRendererClient will look for the "lifecycle" hidden object when
|
|
||||||
v8Util.setHiddenValue(global, 'lifecycle', {
|
|
||||||
onLoaded () {
|
|
||||||
(process as events.EventEmitter).emit('loaded');
|
|
||||||
},
|
|
||||||
onExit () {
|
|
||||||
(process as events.EventEmitter).emit('exit');
|
|
||||||
},
|
|
||||||
onDocumentStart () {
|
|
||||||
(process as events.EventEmitter).emit('document-start');
|
|
||||||
},
|
|
||||||
onDocumentEnd () {
|
|
||||||
(process as events.EventEmitter).emit('document-end');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Pass different process object to the preload script.
|
// Pass different process object to the preload script.
|
||||||
const preloadProcess: NodeJS.Process = new EventEmitter() as any;
|
const preloadProcess: NodeJS.Process = new EventEmitter() as any;
|
||||||
|
|
||||||
|
// InvokeEmitProcessEvent in ElectronSandboxedRendererClient will look for this
|
||||||
|
v8Util.setHiddenValue(global, 'emit-process-event', (event: string) => {
|
||||||
|
(process as events.EventEmitter).emit(event);
|
||||||
|
(preloadProcess as events.EventEmitter).emit(event);
|
||||||
|
});
|
||||||
|
|
||||||
Object.assign(preloadProcess, binding.process);
|
Object.assign(preloadProcess, binding.process);
|
||||||
Object.assign(preloadProcess, processProps);
|
Object.assign(preloadProcess, processProps);
|
||||||
|
|
||||||
|
@ -79,11 +69,6 @@ Object.defineProperty(preloadProcess, 'noDeprecation', {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
process.on('loaded', () => (preloadProcess as events.EventEmitter).emit('loaded'));
|
|
||||||
process.on('exit', () => (preloadProcess as events.EventEmitter).emit('exit'));
|
|
||||||
(process as events.EventEmitter).on('document-start', () => (preloadProcess as events.EventEmitter).emit('document-start'));
|
|
||||||
(process as events.EventEmitter).on('document-end', () => (preloadProcess as events.EventEmitter).emit('document-end'));
|
|
||||||
|
|
||||||
// This is the `require` function that will be visible to the preload script
|
// This is the `require` function that will be visible to the preload script
|
||||||
function preloadRequire (module: string) {
|
function preloadRequire (module: string) {
|
||||||
if (loadedModules.has(module)) {
|
if (loadedModules.has(module)) {
|
||||||
|
|
|
@ -4,11 +4,13 @@
|
||||||
|
|
||||||
#include "shell/renderer/electron_sandboxed_renderer_client.h"
|
#include "shell/renderer/electron_sandboxed_renderer_client.h"
|
||||||
|
|
||||||
|
#include <iterator>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "base/base_paths.h"
|
#include "base/base_paths.h"
|
||||||
#include "base/command_line.h"
|
#include "base/command_line.h"
|
||||||
|
#include "base/containers/contains.h"
|
||||||
#include "base/files/file_path.h"
|
#include "base/files/file_path.h"
|
||||||
#include "base/path_service.h"
|
#include "base/path_service.h"
|
||||||
#include "base/process/process_handle.h"
|
#include "base/process/process_handle.h"
|
||||||
|
@ -33,7 +35,7 @@ namespace electron {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
const char kLifecycleKey[] = "lifecycle";
|
const char kEmitProcessEventKey[] = "emit-process-event";
|
||||||
const char kModuleCacheKey[] = "native-module-cache";
|
const char kModuleCacheKey[] = "native-module-cache";
|
||||||
|
|
||||||
v8::Local<v8::Object> GetModuleCache(v8::Isolate* isolate) {
|
v8::Local<v8::Object> GetModuleCache(v8::Isolate* isolate) {
|
||||||
|
@ -94,27 +96,25 @@ double Uptime() {
|
||||||
.InSecondsF();
|
.InSecondsF();
|
||||||
}
|
}
|
||||||
|
|
||||||
void InvokeHiddenCallback(v8::Handle<v8::Context> context,
|
void InvokeEmitProcessEvent(v8::Handle<v8::Context> context,
|
||||||
const std::string& hidden_key,
|
const std::string& event_name) {
|
||||||
const std::string& callback_name) {
|
|
||||||
auto* isolate = context->GetIsolate();
|
auto* isolate = context->GetIsolate();
|
||||||
auto binding_key =
|
// set by sandboxed_renderer/init.js
|
||||||
gin::ConvertToV8(isolate, hidden_key)->ToString(context).ToLocalChecked();
|
auto binding_key = gin::ConvertToV8(isolate, kEmitProcessEventKey)
|
||||||
|
->ToString(context)
|
||||||
|
.ToLocalChecked();
|
||||||
auto private_binding_key = v8::Private::ForApi(isolate, binding_key);
|
auto private_binding_key = v8::Private::ForApi(isolate, binding_key);
|
||||||
auto global_object = context->Global();
|
auto global_object = context->Global();
|
||||||
v8::Local<v8::Value> value;
|
v8::Local<v8::Value> callback_value;
|
||||||
if (!global_object->GetPrivate(context, private_binding_key).ToLocal(&value))
|
if (!global_object->GetPrivate(context, private_binding_key)
|
||||||
|
.ToLocal(&callback_value))
|
||||||
return;
|
return;
|
||||||
if (value.IsEmpty() || !value->IsObject())
|
if (callback_value.IsEmpty() || !callback_value->IsFunction())
|
||||||
return;
|
return;
|
||||||
auto binding = value->ToObject(context).ToLocalChecked();
|
|
||||||
auto callback_key = gin::ConvertToV8(isolate, callback_name)
|
|
||||||
->ToString(context)
|
|
||||||
.ToLocalChecked();
|
|
||||||
auto callback_value = binding->Get(context, callback_key).ToLocalChecked();
|
|
||||||
DCHECK(callback_value->IsFunction()); // set by sandboxed_renderer/init.js
|
|
||||||
auto callback = callback_value.As<v8::Function>();
|
auto callback = callback_value.As<v8::Function>();
|
||||||
std::ignore = callback->Call(context, binding, 0, nullptr);
|
v8::Local<v8::Value> args[] = {gin::ConvertToV8(isolate, event_name)};
|
||||||
|
std::ignore =
|
||||||
|
callback->Call(context, callback, std::size(args), std::data(args));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -158,37 +158,13 @@ void ElectronSandboxedRendererClient::RenderFrameCreated(
|
||||||
void ElectronSandboxedRendererClient::RunScriptsAtDocumentStart(
|
void ElectronSandboxedRendererClient::RunScriptsAtDocumentStart(
|
||||||
content::RenderFrame* render_frame) {
|
content::RenderFrame* render_frame) {
|
||||||
RendererClientBase::RunScriptsAtDocumentStart(render_frame);
|
RendererClientBase::RunScriptsAtDocumentStart(render_frame);
|
||||||
if (injected_frames_.find(render_frame) == injected_frames_.end())
|
EmitProcessEvent(render_frame, "document-start");
|
||||||
return;
|
|
||||||
|
|
||||||
auto* isolate = blink::MainThreadIsolate();
|
|
||||||
v8::HandleScope handle_scope(isolate);
|
|
||||||
v8::Local<v8::Context> context =
|
|
||||||
GetContext(render_frame->GetWebFrame(), isolate);
|
|
||||||
gin_helper::MicrotasksScope microtasks_scope(
|
|
||||||
isolate, context->GetMicrotaskQueue(),
|
|
||||||
v8::MicrotasksScope::kDoNotRunMicrotasks);
|
|
||||||
v8::Context::Scope context_scope(context);
|
|
||||||
|
|
||||||
InvokeHiddenCallback(context, kLifecycleKey, "onDocumentStart");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ElectronSandboxedRendererClient::RunScriptsAtDocumentEnd(
|
void ElectronSandboxedRendererClient::RunScriptsAtDocumentEnd(
|
||||||
content::RenderFrame* render_frame) {
|
content::RenderFrame* render_frame) {
|
||||||
RendererClientBase::RunScriptsAtDocumentEnd(render_frame);
|
RendererClientBase::RunScriptsAtDocumentEnd(render_frame);
|
||||||
if (injected_frames_.find(render_frame) == injected_frames_.end())
|
EmitProcessEvent(render_frame, "document-end");
|
||||||
return;
|
|
||||||
|
|
||||||
auto* isolate = blink::MainThreadIsolate();
|
|
||||||
v8::HandleScope handle_scope(isolate);
|
|
||||||
v8::Local<v8::Context> context =
|
|
||||||
GetContext(render_frame->GetWebFrame(), isolate);
|
|
||||||
gin_helper::MicrotasksScope microtasks_scope(
|
|
||||||
isolate, context->GetMicrotaskQueue(),
|
|
||||||
v8::MicrotasksScope::kDoNotRunMicrotasks);
|
|
||||||
v8::Context::Scope context_scope(context);
|
|
||||||
|
|
||||||
InvokeHiddenCallback(context, kLifecycleKey, "onDocumentEnd");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ElectronSandboxedRendererClient::DidCreateScriptContext(
|
void ElectronSandboxedRendererClient::DidCreateScriptContext(
|
||||||
|
@ -219,7 +195,7 @@ void ElectronSandboxedRendererClient::DidCreateScriptContext(
|
||||||
|
|
||||||
v8::HandleScope handle_scope(isolate);
|
v8::HandleScope handle_scope(isolate);
|
||||||
v8::Context::Scope context_scope(context);
|
v8::Context::Scope context_scope(context);
|
||||||
InvokeHiddenCallback(context, kLifecycleKey, "onLoaded");
|
InvokeEmitProcessEvent(context, "loaded");
|
||||||
}
|
}
|
||||||
|
|
||||||
void ElectronSandboxedRendererClient::WillReleaseScriptContext(
|
void ElectronSandboxedRendererClient::WillReleaseScriptContext(
|
||||||
|
@ -234,7 +210,25 @@ void ElectronSandboxedRendererClient::WillReleaseScriptContext(
|
||||||
v8::MicrotasksScope::kDoNotRunMicrotasks);
|
v8::MicrotasksScope::kDoNotRunMicrotasks);
|
||||||
v8::HandleScope handle_scope(isolate);
|
v8::HandleScope handle_scope(isolate);
|
||||||
v8::Context::Scope context_scope(context);
|
v8::Context::Scope context_scope(context);
|
||||||
InvokeHiddenCallback(context, kLifecycleKey, "onExit");
|
InvokeEmitProcessEvent(context, "exit");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ElectronSandboxedRendererClient::EmitProcessEvent(
|
||||||
|
content::RenderFrame* render_frame,
|
||||||
|
const char* event_name) {
|
||||||
|
if (injected_frames_.find(render_frame) == injected_frames_.end())
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto* isolate = blink::MainThreadIsolate();
|
||||||
|
v8::HandleScope handle_scope(isolate);
|
||||||
|
v8::Local<v8::Context> context =
|
||||||
|
GetContext(render_frame->GetWebFrame(), isolate);
|
||||||
|
gin_helper::MicrotasksScope microtasks_scope(
|
||||||
|
isolate, context->GetMicrotaskQueue(),
|
||||||
|
v8::MicrotasksScope::kDoNotRunMicrotasks);
|
||||||
|
v8::Context::Scope context_scope(context);
|
||||||
|
|
||||||
|
InvokeEmitProcessEvent(context, event_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace electron
|
} // namespace electron
|
||||||
|
|
|
@ -45,6 +45,9 @@ class ElectronSandboxedRendererClient : public RendererClientBase {
|
||||||
void RunScriptsAtDocumentEnd(content::RenderFrame* render_frame) override;
|
void RunScriptsAtDocumentEnd(content::RenderFrame* render_frame) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void EmitProcessEvent(content::RenderFrame* render_frame,
|
||||||
|
const char* event_name);
|
||||||
|
|
||||||
std::unique_ptr<base::ProcessMetrics> metrics_;
|
std::unique_ptr<base::ProcessMetrics> metrics_;
|
||||||
|
|
||||||
// Getting main script context from web frame would lazily initializes
|
// Getting main script context from web frame would lazily initializes
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue