refactor: clean up webFrame implementation to use gin wrappers (#28497)
* refactor: clean up webFrame implementation to use gin wrappers The previous implementation of webFrame in the renderer process leaked sub-frame contexts and global objects across the context boundaries thus making it possible for apps to either maliciously or accidentally violate the contextIsolation boundary. This re-implementation binds all methods in native code directly to content::RenderFrame instances instead of relying on JS to provide a "window" with every method request. This is much more consistent with the rest of the Electron codebase and is substantially safer. * chore: un-re-order for ease of review * chore: pass isolate around instead of ErrorThrower * chore: fix rebase typo * chore: remove unused variables
This commit is contained in:
parent
e775467e9c
commit
6df2680cb6
8 changed files with 604 additions and 632 deletions
|
@ -1,7 +1,7 @@
|
||||||
const { getWebPreference } = process._linkedBinding('electron_renderer_web_frame');
|
const { mainFrame } = process._linkedBinding('electron_renderer_web_frame');
|
||||||
const binding = process._linkedBinding('electron_renderer_context_bridge');
|
const binding = process._linkedBinding('electron_renderer_context_bridge');
|
||||||
|
|
||||||
const contextIsolationEnabled = getWebPreference(window, 'contextIsolation');
|
const contextIsolationEnabled = mainFrame.getWebPreference('contextIsolation');
|
||||||
|
|
||||||
const checkContextIsolationEnabled = () => {
|
const checkContextIsolationEnabled = () => {
|
||||||
if (!contextIsolationEnabled) throw new Error('contextBridge API can only be used when contextIsolation is enabled');
|
if (!contextIsolationEnabled) throw new Error('contextBridge API can only be used when contextIsolation is enabled');
|
||||||
|
|
|
@ -1,69 +1,3 @@
|
||||||
import { EventEmitter } from 'events';
|
const { mainFrame } = process._linkedBinding('electron_renderer_web_frame');
|
||||||
|
|
||||||
const binding = process._linkedBinding('electron_renderer_web_frame');
|
export default mainFrame;
|
||||||
|
|
||||||
class WebFrame extends EventEmitter {
|
|
||||||
constructor (public context: Window) {
|
|
||||||
super();
|
|
||||||
|
|
||||||
// Lots of webview would subscribe to webFrame's events.
|
|
||||||
this.setMaxListeners(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
findFrameByRoutingId (routingId: number) {
|
|
||||||
return getWebFrame(binding._findFrameByRoutingId(this.context, routingId));
|
|
||||||
}
|
|
||||||
|
|
||||||
getFrameForSelector (selector: string) {
|
|
||||||
return getWebFrame(binding._getFrameForSelector(this.context, selector));
|
|
||||||
}
|
|
||||||
|
|
||||||
findFrameByName (name: string) {
|
|
||||||
return getWebFrame(binding._findFrameByName(this.context, name));
|
|
||||||
}
|
|
||||||
|
|
||||||
get opener () {
|
|
||||||
return getWebFrame(binding._getOpener(this.context));
|
|
||||||
}
|
|
||||||
|
|
||||||
get parent () {
|
|
||||||
return getWebFrame(binding._getParent(this.context));
|
|
||||||
}
|
|
||||||
|
|
||||||
get top () {
|
|
||||||
return getWebFrame(binding._getTop(this.context));
|
|
||||||
}
|
|
||||||
|
|
||||||
get firstChild () {
|
|
||||||
return getWebFrame(binding._getFirstChild(this.context));
|
|
||||||
}
|
|
||||||
|
|
||||||
get nextSibling () {
|
|
||||||
return getWebFrame(binding._getNextSibling(this.context));
|
|
||||||
}
|
|
||||||
|
|
||||||
get routingId () {
|
|
||||||
return binding._getRoutingId(this.context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Populate the methods.
|
|
||||||
for (const name in binding) {
|
|
||||||
if (!name.startsWith('_')) { // some methods are manually populated above
|
|
||||||
// TODO(felixrieseberg): Once we can type web_frame natives, we could
|
|
||||||
// use a neat `keyof` here
|
|
||||||
(WebFrame as any).prototype[name] = function (...args: Array<any>) {
|
|
||||||
return (binding as any)[name](this.context, ...args);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper to return WebFrame or null depending on context.
|
|
||||||
// TODO(zcbenz): Consider returning same WebFrame for the same frame.
|
|
||||||
function getWebFrame (context: Window) {
|
|
||||||
return context ? new WebFrame(context) : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const _webFrame = new WebFrame(window);
|
|
||||||
|
|
||||||
export default _webFrame;
|
|
||||||
|
|
|
@ -63,18 +63,18 @@ webFrameInit();
|
||||||
|
|
||||||
// Process command line arguments.
|
// Process command line arguments.
|
||||||
const { hasSwitch, getSwitchValue } = process._linkedBinding('electron_common_command_line');
|
const { hasSwitch, getSwitchValue } = process._linkedBinding('electron_common_command_line');
|
||||||
const { getWebPreference } = process._linkedBinding('electron_renderer_web_frame');
|
const { mainFrame } = process._linkedBinding('electron_renderer_web_frame');
|
||||||
|
|
||||||
const contextIsolation = getWebPreference(window, 'contextIsolation');
|
const contextIsolation = mainFrame.getWebPreference('contextIsolation');
|
||||||
const nodeIntegration = getWebPreference(window, 'nodeIntegration');
|
const nodeIntegration = mainFrame.getWebPreference('nodeIntegration');
|
||||||
const webviewTag = getWebPreference(window, 'webviewTag');
|
const webviewTag = mainFrame.getWebPreference('webviewTag');
|
||||||
const isHiddenPage = getWebPreference(window, 'hiddenPage');
|
const isHiddenPage = mainFrame.getWebPreference('hiddenPage');
|
||||||
const usesNativeWindowOpen = getWebPreference(window, 'nativeWindowOpen');
|
const usesNativeWindowOpen = mainFrame.getWebPreference('nativeWindowOpen');
|
||||||
const rendererProcessReuseEnabled = getWebPreference(window, 'disableElectronSiteInstanceOverrides');
|
const rendererProcessReuseEnabled = mainFrame.getWebPreference('disableElectronSiteInstanceOverrides');
|
||||||
const preloadScript = getWebPreference(window, 'preload');
|
const preloadScript = mainFrame.getWebPreference('preload');
|
||||||
const preloadScripts = getWebPreference(window, 'preloadScripts');
|
const preloadScripts = mainFrame.getWebPreference('preloadScripts');
|
||||||
const guestInstanceId = getWebPreference(window, 'guestInstanceId') || null;
|
const guestInstanceId = mainFrame.getWebPreference('guestInstanceId') || null;
|
||||||
const openerId = getWebPreference(window, 'openerId') || null;
|
const openerId = mainFrame.getWebPreference('openerId') || null;
|
||||||
const appPath = hasSwitch('app-path') ? getSwitchValue('app-path') : null;
|
const appPath = hasSwitch('app-path') ? getSwitchValue('app-path') : null;
|
||||||
|
|
||||||
// The webContents preload script is loaded after the session preload scripts.
|
// The webContents preload script is loaded after the session preload scripts.
|
||||||
|
|
|
@ -113,7 +113,7 @@ function preloadRequire (module: string) {
|
||||||
|
|
||||||
// Process command line arguments.
|
// Process command line arguments.
|
||||||
const { hasSwitch } = process._linkedBinding('electron_common_command_line');
|
const { hasSwitch } = process._linkedBinding('electron_common_command_line');
|
||||||
const { getWebPreference } = process._linkedBinding('electron_renderer_web_frame');
|
const { mainFrame } = process._linkedBinding('electron_renderer_web_frame');
|
||||||
|
|
||||||
// Similar to nodes --expose-internals flag, this exposes _linkedBinding so
|
// Similar to nodes --expose-internals flag, this exposes _linkedBinding so
|
||||||
// that tests can call it to get access to some test only bindings
|
// that tests can call it to get access to some test only bindings
|
||||||
|
@ -121,13 +121,13 @@ if (hasSwitch('unsafely-expose-electron-internals-for-testing')) {
|
||||||
preloadProcess._linkedBinding = process._linkedBinding;
|
preloadProcess._linkedBinding = process._linkedBinding;
|
||||||
}
|
}
|
||||||
|
|
||||||
const contextIsolation = getWebPreference(window, 'contextIsolation');
|
const contextIsolation = mainFrame.getWebPreference('contextIsolation');
|
||||||
const webviewTag = getWebPreference(window, 'webviewTag');
|
const webviewTag = mainFrame.getWebPreference('webviewTag');
|
||||||
const isHiddenPage = getWebPreference(window, 'hiddenPage');
|
const isHiddenPage = mainFrame.getWebPreference('hiddenPage');
|
||||||
const rendererProcessReuseEnabled = getWebPreference(window, 'disableElectronSiteInstanceOverrides');
|
const rendererProcessReuseEnabled = mainFrame.getWebPreference('disableElectronSiteInstanceOverrides');
|
||||||
const usesNativeWindowOpen = true;
|
const usesNativeWindowOpen = true;
|
||||||
const guestInstanceId = getWebPreference(window, 'guestInstanceId') || null;
|
const guestInstanceId = mainFrame.getWebPreference('guestInstanceId') || null;
|
||||||
const openerId = getWebPreference(window, 'openerId') || null;
|
const openerId = mainFrame.getWebPreference('openerId') || null;
|
||||||
|
|
||||||
switch (window.location.protocol) {
|
switch (window.location.protocol) {
|
||||||
case 'devtools:': {
|
case 'devtools:': {
|
||||||
|
|
|
@ -17,27 +17,27 @@ ErrorThrower::ErrorThrower() : isolate_(v8::Isolate::GetCurrent()) {}
|
||||||
|
|
||||||
ErrorThrower::~ErrorThrower() = default;
|
ErrorThrower::~ErrorThrower() = default;
|
||||||
|
|
||||||
void ErrorThrower::ThrowError(base::StringPiece err_msg) {
|
void ErrorThrower::ThrowError(base::StringPiece err_msg) const {
|
||||||
Throw(v8::Exception::Error, err_msg);
|
Throw(v8::Exception::Error, err_msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ErrorThrower::ThrowTypeError(base::StringPiece err_msg) {
|
void ErrorThrower::ThrowTypeError(base::StringPiece err_msg) const {
|
||||||
Throw(v8::Exception::TypeError, err_msg);
|
Throw(v8::Exception::TypeError, err_msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ErrorThrower::ThrowRangeError(base::StringPiece err_msg) {
|
void ErrorThrower::ThrowRangeError(base::StringPiece err_msg) const {
|
||||||
Throw(v8::Exception::RangeError, err_msg);
|
Throw(v8::Exception::RangeError, err_msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ErrorThrower::ThrowReferenceError(base::StringPiece err_msg) {
|
void ErrorThrower::ThrowReferenceError(base::StringPiece err_msg) const {
|
||||||
Throw(v8::Exception::ReferenceError, err_msg);
|
Throw(v8::Exception::ReferenceError, err_msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ErrorThrower::ThrowSyntaxError(base::StringPiece err_msg) {
|
void ErrorThrower::ThrowSyntaxError(base::StringPiece err_msg) const {
|
||||||
Throw(v8::Exception::SyntaxError, err_msg);
|
Throw(v8::Exception::SyntaxError, err_msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ErrorThrower::Throw(ErrorGenerator gen, base::StringPiece err_msg) {
|
void ErrorThrower::Throw(ErrorGenerator gen, base::StringPiece err_msg) const {
|
||||||
v8::Local<v8::Value> exception = gen(gin::StringToV8(isolate_, err_msg));
|
v8::Local<v8::Value> exception = gen(gin::StringToV8(isolate_, err_msg));
|
||||||
if (!isolate_->IsExecutionTerminating())
|
if (!isolate_->IsExecutionTerminating())
|
||||||
isolate_->ThrowException(exception);
|
isolate_->ThrowException(exception);
|
||||||
|
|
|
@ -17,18 +17,18 @@ class ErrorThrower {
|
||||||
|
|
||||||
~ErrorThrower();
|
~ErrorThrower();
|
||||||
|
|
||||||
void ThrowError(base::StringPiece err_msg);
|
void ThrowError(base::StringPiece err_msg) const;
|
||||||
void ThrowTypeError(base::StringPiece err_msg);
|
void ThrowTypeError(base::StringPiece err_msg) const;
|
||||||
void ThrowRangeError(base::StringPiece err_msg);
|
void ThrowRangeError(base::StringPiece err_msg) const;
|
||||||
void ThrowReferenceError(base::StringPiece err_msg);
|
void ThrowReferenceError(base::StringPiece err_msg) const;
|
||||||
void ThrowSyntaxError(base::StringPiece err_msg);
|
void ThrowSyntaxError(base::StringPiece err_msg) const;
|
||||||
|
|
||||||
v8::Isolate* isolate() const { return isolate_; }
|
v8::Isolate* isolate() const { return isolate_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using ErrorGenerator =
|
using ErrorGenerator =
|
||||||
v8::Local<v8::Value> (*)(v8::Local<v8::String> err_msg);
|
v8::Local<v8::Value> (*)(v8::Local<v8::String> err_msg);
|
||||||
void Throw(ErrorGenerator gen, base::StringPiece err_msg);
|
void Throw(ErrorGenerator gen, base::StringPiece err_msg) const;
|
||||||
|
|
||||||
v8::Isolate* isolate_;
|
v8::Isolate* isolate_;
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,6 +16,9 @@
|
||||||
#include "content/public/renderer/render_frame_observer.h"
|
#include "content/public/renderer/render_frame_observer.h"
|
||||||
#include "content/public/renderer/render_frame_visitor.h"
|
#include "content/public/renderer/render_frame_visitor.h"
|
||||||
#include "content/public/renderer/render_view.h"
|
#include "content/public/renderer/render_view.h"
|
||||||
|
#include "gin/handle.h"
|
||||||
|
#include "gin/object_template_builder.h"
|
||||||
|
#include "gin/wrappable.h"
|
||||||
#include "services/service_manager/public/cpp/interface_provider.h"
|
#include "services/service_manager/public/cpp/interface_provider.h"
|
||||||
#include "shell/common/api/api.mojom.h"
|
#include "shell/common/api/api.mojom.h"
|
||||||
#include "shell/common/gin_converters/blink_converter.h"
|
#include "shell/common/gin_converters/blink_converter.h"
|
||||||
|
@ -23,6 +26,7 @@
|
||||||
#include "shell/common/gin_converters/file_path_converter.h"
|
#include "shell/common/gin_converters/file_path_converter.h"
|
||||||
#include "shell/common/gin_helper/dictionary.h"
|
#include "shell/common/gin_helper/dictionary.h"
|
||||||
#include "shell/common/gin_helper/error_thrower.h"
|
#include "shell/common/gin_helper/error_thrower.h"
|
||||||
|
#include "shell/common/gin_helper/function_template_extensions.h"
|
||||||
#include "shell/common/gin_helper/promise.h"
|
#include "shell/common/gin_helper/promise.h"
|
||||||
#include "shell/common/node_includes.h"
|
#include "shell/common/node_includes.h"
|
||||||
#include "shell/common/options_switches.h"
|
#include "shell/common/options_switches.h"
|
||||||
|
@ -111,17 +115,13 @@ content::RenderFrame* GetRenderFrame(v8::Local<v8::Value> value) {
|
||||||
|
|
||||||
#if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
|
#if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
|
||||||
|
|
||||||
bool SpellCheckWord(v8::Isolate* isolate,
|
bool SpellCheckWord(content::RenderFrame* render_frame,
|
||||||
v8::Local<v8::Value> window,
|
|
||||||
const std::string& word,
|
const std::string& word,
|
||||||
std::vector<std::u16string>* optional_suggestions) {
|
std::vector<std::u16string>* optional_suggestions) {
|
||||||
size_t start;
|
size_t start;
|
||||||
size_t length;
|
size_t length;
|
||||||
|
|
||||||
ElectronRendererClient* client = ElectronRendererClient::Get();
|
ElectronRendererClient* client = ElectronRendererClient::Get();
|
||||||
auto* render_frame = GetRenderFrame(window);
|
|
||||||
if (!render_frame)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
std::u16string w = base::UTF8ToUTF16(word);
|
std::u16string w = base::UTF8ToUTF16(word);
|
||||||
int id = render_frame->GetRoutingID();
|
int id = render_frame->GetRoutingID();
|
||||||
|
@ -206,9 +206,9 @@ class ScriptExecutionCallback : public blink::WebScriptExecutionCallback {
|
||||||
if (!result.empty()) {
|
if (!result.empty()) {
|
||||||
if (!result[0].IsEmpty()) {
|
if (!result[0].IsEmpty()) {
|
||||||
v8::Local<v8::Value> value = result[0];
|
v8::Local<v8::Value> value = result[0];
|
||||||
// Either world safe results are disabled or the result was created in
|
// Either the result was created in the same world as the caller
|
||||||
// the same world as the caller or the result is not an object and
|
// or the result is not an object and therefore does not have a
|
||||||
// therefore does not have a prototype chain to protect
|
// prototype chain to protect
|
||||||
bool should_clone_value =
|
bool should_clone_value =
|
||||||
!(value->IsObject() &&
|
!(value->IsObject() &&
|
||||||
promise_.GetContext() ==
|
promise_.GetContext() ==
|
||||||
|
@ -344,41 +344,121 @@ class SpellCheckerHolder final : public content::RenderFrameObserver {
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
// static
|
class WebFrameRenderer : public gin::Wrappable<WebFrameRenderer>,
|
||||||
std::set<SpellCheckerHolder*> SpellCheckerHolder::instances_;
|
public content::RenderFrameObserver {
|
||||||
|
public:
|
||||||
|
static gin::WrapperInfo kWrapperInfo;
|
||||||
|
|
||||||
void SetName(v8::Local<v8::Value> window, const std::string& name) {
|
static gin::Handle<WebFrameRenderer> Create(
|
||||||
GetRenderFrame(window)->GetWebFrame()->SetName(
|
v8::Isolate* isolate,
|
||||||
blink::WebString::FromUTF8(name));
|
content::RenderFrame* render_frame) {
|
||||||
|
return gin::CreateHandle(isolate, new WebFrameRenderer(render_frame));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetZoomLevel(gin_helper::ErrorThrower thrower,
|
explicit WebFrameRenderer(content::RenderFrame* render_frame)
|
||||||
v8::Local<v8::Value> window,
|
: content::RenderFrameObserver(render_frame) {
|
||||||
double level) {
|
DCHECK(render_frame);
|
||||||
content::RenderFrame* render_frame = GetRenderFrame(window);
|
}
|
||||||
if (!render_frame) {
|
|
||||||
thrower.ThrowError(
|
// gin::Wrappable:
|
||||||
"Render frame was torn down before webFrame.setZoomLevel could be "
|
gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
|
||||||
"executed");
|
v8::Isolate* isolate) override {
|
||||||
|
return gin::Wrappable<WebFrameRenderer>::GetObjectTemplateBuilder(isolate)
|
||||||
|
.SetMethod("getWebFrameId", &WebFrameRenderer::GetWebFrameId)
|
||||||
|
.SetMethod("setName", &WebFrameRenderer::SetName)
|
||||||
|
.SetMethod("setZoomLevel", &WebFrameRenderer::SetZoomLevel)
|
||||||
|
.SetMethod("getZoomLevel", &WebFrameRenderer::GetZoomLevel)
|
||||||
|
.SetMethod("setZoomFactor", &WebFrameRenderer::SetZoomFactor)
|
||||||
|
.SetMethod("getZoomFactor", &WebFrameRenderer::GetZoomFactor)
|
||||||
|
.SetMethod("getWebPreference", &WebFrameRenderer::GetWebPreference)
|
||||||
|
#if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
|
||||||
|
.SetMethod("isWordMisspelled", &WebFrameRenderer::IsWordMisspelled)
|
||||||
|
.SetMethod("getWordSuggestions", &WebFrameRenderer::GetWordSuggestions)
|
||||||
|
#endif
|
||||||
|
.SetMethod("setVisualZoomLevelLimits",
|
||||||
|
&WebFrameRenderer::SetVisualZoomLevelLimits)
|
||||||
|
.SetMethod("allowGuestViewElementDefinition",
|
||||||
|
&WebFrameRenderer::AllowGuestViewElementDefinition)
|
||||||
|
.SetMethod("insertText", &WebFrameRenderer::InsertText)
|
||||||
|
.SetMethod("insertCSS", &WebFrameRenderer::InsertCSS)
|
||||||
|
.SetMethod("removeInsertedCSS", &WebFrameRenderer::RemoveInsertedCSS)
|
||||||
|
.SetMethod("executeJavaScript", &WebFrameRenderer::ExecuteJavaScript)
|
||||||
|
.SetMethod("executeJavaScriptInIsolatedWorld",
|
||||||
|
&WebFrameRenderer::ExecuteJavaScriptInIsolatedWorld)
|
||||||
|
.SetMethod("setIsolatedWorldInfo",
|
||||||
|
&WebFrameRenderer::SetIsolatedWorldInfo)
|
||||||
|
.SetMethod("getResourceUsage", &WebFrameRenderer::GetResourceUsage)
|
||||||
|
.SetMethod("clearCache", &WebFrameRenderer::ClearCache)
|
||||||
|
.SetMethod("setSpellCheckProvider",
|
||||||
|
&WebFrameRenderer::SetSpellCheckProvider)
|
||||||
|
// Frame navigators
|
||||||
|
.SetMethod("findFrameByRoutingId",
|
||||||
|
&WebFrameRenderer::FindFrameByRoutingId)
|
||||||
|
.SetMethod("getFrameForSelector",
|
||||||
|
&WebFrameRenderer::GetFrameForSelector)
|
||||||
|
.SetMethod("findFrameByName", &WebFrameRenderer::FindFrameByName)
|
||||||
|
.SetProperty("opener", &WebFrameRenderer::GetOpener)
|
||||||
|
.SetProperty("parent", &WebFrameRenderer::GetFrameParent)
|
||||||
|
.SetProperty("top", &WebFrameRenderer::GetTop)
|
||||||
|
.SetProperty("firstChild", &WebFrameRenderer::GetFirstChild)
|
||||||
|
.SetProperty("nextSibling", &WebFrameRenderer::GetNextSibling)
|
||||||
|
.SetProperty("routingId", &WebFrameRenderer::GetRoutingId);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* GetTypeName() override { return "WebFrameRenderer"; }
|
||||||
|
|
||||||
|
void OnDestruct() override {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool MaybeGetRenderFrame(v8::Isolate* isolate,
|
||||||
|
const std::string& method_name,
|
||||||
|
content::RenderFrame** render_frame_ptr) {
|
||||||
|
std::string error_msg;
|
||||||
|
if (!MaybeGetRenderFrame(&error_msg, method_name, render_frame_ptr)) {
|
||||||
|
gin_helper::ErrorThrower(isolate).ThrowError(error_msg);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MaybeGetRenderFrame(std::string* error_msg,
|
||||||
|
const std::string& method_name,
|
||||||
|
content::RenderFrame** render_frame_ptr) {
|
||||||
|
auto* frame = render_frame();
|
||||||
|
if (!frame) {
|
||||||
|
*error_msg = "Render frame was torn down before webFrame." + method_name +
|
||||||
|
" could be "
|
||||||
|
"executed";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*render_frame_ptr = frame;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetName(v8::Isolate* isolate, const std::string& name) {
|
||||||
|
content::RenderFrame* render_frame;
|
||||||
|
if (!MaybeGetRenderFrame(isolate, "setName", &render_frame))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
render_frame->GetWebFrame()->SetName(blink::WebString::FromUTF8(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetZoomLevel(v8::Isolate* isolate, double level) {
|
||||||
|
content::RenderFrame* render_frame;
|
||||||
|
if (!MaybeGetRenderFrame(isolate, "setZoomLevel", &render_frame))
|
||||||
|
return;
|
||||||
|
|
||||||
mojo::Remote<mojom::ElectronBrowser> browser_remote;
|
mojo::Remote<mojom::ElectronBrowser> browser_remote;
|
||||||
render_frame->GetBrowserInterfaceBroker()->GetInterface(
|
render_frame->GetBrowserInterfaceBroker()->GetInterface(
|
||||||
browser_remote.BindNewPipeAndPassReceiver());
|
browser_remote.BindNewPipeAndPassReceiver());
|
||||||
browser_remote->SetTemporaryZoomLevel(level);
|
browser_remote->SetTemporaryZoomLevel(level);
|
||||||
}
|
}
|
||||||
|
|
||||||
double GetZoomLevel(gin_helper::ErrorThrower thrower,
|
double GetZoomLevel(v8::Isolate* isolate) {
|
||||||
v8::Local<v8::Value> window) {
|
|
||||||
double result = 0.0;
|
double result = 0.0;
|
||||||
content::RenderFrame* render_frame = GetRenderFrame(window);
|
content::RenderFrame* render_frame;
|
||||||
if (!render_frame) {
|
if (!MaybeGetRenderFrame(isolate, "getZoomLevel", &render_frame))
|
||||||
thrower.ThrowError(
|
|
||||||
"Render frame was torn down before webFrame.getZoomLevel could be "
|
|
||||||
"executed");
|
|
||||||
return result;
|
return result;
|
||||||
}
|
|
||||||
|
|
||||||
mojo::Remote<mojom::ElectronBrowser> browser_remote;
|
mojo::Remote<mojom::ElectronBrowser> browser_remote;
|
||||||
render_frame->GetBrowserInterfaceBroker()->GetInterface(
|
render_frame->GetBrowserInterfaceBroker()->GetInterface(
|
||||||
|
@ -387,27 +467,26 @@ double GetZoomLevel(gin_helper::ErrorThrower thrower,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetZoomFactor(gin_helper::ErrorThrower thrower,
|
void SetZoomFactor(gin_helper::ErrorThrower thrower, double factor) {
|
||||||
v8::Local<v8::Value> window,
|
|
||||||
double factor) {
|
|
||||||
if (factor < std::numeric_limits<double>::epsilon()) {
|
if (factor < std::numeric_limits<double>::epsilon()) {
|
||||||
thrower.ThrowError("'zoomFactor' must be a double greater than 0.0");
|
thrower.ThrowError("'zoomFactor' must be a double greater than 0.0");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetZoomLevel(thrower, window, blink::PageZoomFactorToZoomLevel(factor));
|
SetZoomLevel(thrower.isolate(), blink::PageZoomFactorToZoomLevel(factor));
|
||||||
}
|
}
|
||||||
|
|
||||||
double GetZoomFactor(gin_helper::ErrorThrower thrower,
|
double GetZoomFactor(v8::Isolate* isolate) {
|
||||||
v8::Local<v8::Value> window) {
|
double zoom_level = GetZoomLevel(isolate);
|
||||||
double zoom_level = GetZoomLevel(thrower, window);
|
|
||||||
return blink::PageZoomLevelToZoomFactor(zoom_level);
|
return blink::PageZoomLevelToZoomFactor(zoom_level);
|
||||||
}
|
}
|
||||||
|
|
||||||
v8::Local<v8::Value> GetWebPreference(v8::Isolate* isolate,
|
v8::Local<v8::Value> GetWebPreference(v8::Isolate* isolate,
|
||||||
v8::Local<v8::Value> window,
|
|
||||||
std::string pref_name) {
|
std::string pref_name) {
|
||||||
content::RenderFrame* render_frame = GetRenderFrame(window);
|
content::RenderFrame* render_frame;
|
||||||
|
if (!MaybeGetRenderFrame(isolate, "getWebPreference", &render_frame))
|
||||||
|
return v8::Undefined(isolate);
|
||||||
|
|
||||||
const auto& prefs = render_frame->GetBlinkPreferences();
|
const auto& prefs = render_frame->GetBlinkPreferences();
|
||||||
|
|
||||||
if (pref_name == options::kPreloadScripts) {
|
if (pref_name == options::kPreloadScripts) {
|
||||||
|
@ -457,45 +536,36 @@ v8::Local<v8::Value> GetWebPreference(v8::Isolate* isolate,
|
||||||
return v8::Null(isolate);
|
return v8::Null(isolate);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetVisualZoomLevelLimits(gin_helper::ErrorThrower thrower,
|
void SetVisualZoomLevelLimits(v8::Isolate* isolate,
|
||||||
v8::Local<v8::Value> window,
|
|
||||||
double min_level,
|
double min_level,
|
||||||
double max_level) {
|
double max_level) {
|
||||||
auto* render_frame = GetRenderFrame(window);
|
content::RenderFrame* render_frame;
|
||||||
if (!render_frame) {
|
if (!MaybeGetRenderFrame(isolate, "setVisualZoomLevelLimits",
|
||||||
thrower.ThrowError(
|
&render_frame))
|
||||||
"Render frame was torn down before webFrame.setVisualZoomLevelLimits "
|
|
||||||
"could be executed");
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
blink::WebFrame* web_frame = render_frame->GetWebFrame();
|
blink::WebFrame* web_frame = render_frame->GetWebFrame();
|
||||||
web_frame->View()->SetDefaultPageScaleLimits(min_level, max_level);
|
web_frame->View()->SetDefaultPageScaleLimits(min_level, max_level);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AllowGuestViewElementDefinition(gin_helper::ErrorThrower thrower,
|
void AllowGuestViewElementDefinition(v8::Isolate* isolate,
|
||||||
v8::Local<v8::Value> window,
|
|
||||||
v8::Local<v8::Object> context,
|
v8::Local<v8::Object> context,
|
||||||
v8::Local<v8::Function> register_cb) {
|
v8::Local<v8::Function> register_cb) {
|
||||||
v8::HandleScope handle_scope(thrower.isolate());
|
v8::HandleScope handle_scope(isolate);
|
||||||
v8::Context::Scope context_scope(context->CreationContext());
|
v8::Context::Scope context_scope(context->CreationContext());
|
||||||
blink::WebCustomElement::EmbedderNamesAllowedScope embedder_names_scope;
|
blink::WebCustomElement::EmbedderNamesAllowedScope embedder_names_scope;
|
||||||
|
|
||||||
auto* render_frame = GetRenderFrame(window);
|
content::RenderFrame* render_frame;
|
||||||
if (!render_frame) {
|
if (!MaybeGetRenderFrame(isolate, "allowGuestViewElementDefinition",
|
||||||
thrower.ThrowError(
|
&render_frame))
|
||||||
"Render frame was torn down before "
|
|
||||||
"webFrame.allowGuestViewElementDefinition could be executed");
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
render_frame->GetWebFrame()->RequestExecuteV8Function(
|
render_frame->GetWebFrame()->RequestExecuteV8Function(
|
||||||
context->CreationContext(), register_cb, v8::Null(thrower.isolate()), 0,
|
context->CreationContext(), register_cb, v8::Null(isolate), 0, nullptr,
|
||||||
nullptr, nullptr);
|
nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetWebFrameId(v8::Local<v8::Value> window,
|
static int GetWebFrameId(v8::Local<v8::Value> content_window) {
|
||||||
v8::Local<v8::Value> content_window) {
|
|
||||||
// Get the WebLocalFrame before (possibly) executing any user-space JS while
|
// Get the WebLocalFrame before (possibly) executing any user-space JS while
|
||||||
// getting the |params|. We track the status of the RenderFrame via an
|
// getting the |params|. We track the status of the RenderFrame via an
|
||||||
// observer in case it is deleted during user code execution.
|
// observer in case it is deleted during user code execution.
|
||||||
|
@ -514,25 +584,21 @@ int GetWebFrameId(v8::Local<v8::Value> window,
|
||||||
return render_frame->GetRoutingID();
|
return render_frame->GetRoutingID();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetSpellCheckProvider(gin_helper::Arguments* args,
|
void SetSpellCheckProvider(gin_helper::ErrorThrower thrower,
|
||||||
v8::Local<v8::Value> window,
|
v8::Isolate* isolate,
|
||||||
const std::string& language,
|
const std::string& language,
|
||||||
v8::Local<v8::Object> provider) {
|
v8::Local<v8::Object> provider) {
|
||||||
auto context = args->isolate()->GetCurrentContext();
|
auto context = isolate->GetCurrentContext();
|
||||||
if (!provider->Has(context, gin::StringToV8(args->isolate(), "spellCheck"))
|
if (!provider->Has(context, gin::StringToV8(isolate, "spellCheck"))
|
||||||
.ToChecked()) {
|
.ToChecked()) {
|
||||||
args->ThrowError("\"spellCheck\" has to be defined");
|
thrower.ThrowError("\"spellCheck\" has to be defined");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the old client.
|
// Remove the old client.
|
||||||
content::RenderFrame* render_frame = GetRenderFrame(window);
|
content::RenderFrame* render_frame;
|
||||||
if (!render_frame) {
|
if (!MaybeGetRenderFrame(isolate, "setSpellCheckProvider", &render_frame))
|
||||||
args->ThrowError(
|
|
||||||
"Render frame was torn down before webFrame.setSpellCheckProvider "
|
|
||||||
"could be executed");
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
auto* existing = SpellCheckerHolder::FromRenderFrame(render_frame);
|
auto* existing = SpellCheckerHolder::FromRenderFrame(render_frame);
|
||||||
if (existing)
|
if (existing)
|
||||||
|
@ -541,23 +607,17 @@ void SetSpellCheckProvider(gin_helper::Arguments* args,
|
||||||
// Set spellchecker for all live frames in the same process or
|
// Set spellchecker for all live frames in the same process or
|
||||||
// in the sandbox mode for all live sub frames to this WebFrame.
|
// in the sandbox mode for all live sub frames to this WebFrame.
|
||||||
auto spell_check_client =
|
auto spell_check_client =
|
||||||
std::make_unique<SpellCheckClient>(language, args->isolate(), provider);
|
std::make_unique<SpellCheckClient>(language, isolate, provider);
|
||||||
FrameSetSpellChecker spell_checker(spell_check_client.get(), render_frame);
|
FrameSetSpellChecker spell_checker(spell_check_client.get(), render_frame);
|
||||||
|
|
||||||
// Attach the spell checker to RenderFrame.
|
// Attach the spell checker to RenderFrame.
|
||||||
new SpellCheckerHolder(render_frame, std::move(spell_check_client));
|
new SpellCheckerHolder(render_frame, std::move(spell_check_client));
|
||||||
}
|
}
|
||||||
|
|
||||||
void InsertText(gin_helper::ErrorThrower thrower,
|
void InsertText(v8::Isolate* isolate, const std::string& text) {
|
||||||
v8::Local<v8::Value> window,
|
content::RenderFrame* render_frame;
|
||||||
const std::string& text) {
|
if (!MaybeGetRenderFrame(isolate, "insertText", &render_frame))
|
||||||
auto* render_frame = GetRenderFrame(window);
|
|
||||||
if (!render_frame) {
|
|
||||||
thrower.ThrowError(
|
|
||||||
"Render frame was torn down before webFrame.insertText could be "
|
|
||||||
"executed");
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
blink::WebFrame* web_frame = render_frame->GetWebFrame();
|
blink::WebFrame* web_frame = render_frame->GetWebFrame();
|
||||||
if (web_frame->IsWebLocalFrame()) {
|
if (web_frame->IsWebLocalFrame()) {
|
||||||
|
@ -565,13 +625,14 @@ void InsertText(gin_helper::ErrorThrower thrower,
|
||||||
->FrameWidget()
|
->FrameWidget()
|
||||||
->GetActiveWebInputMethodController()
|
->GetActiveWebInputMethodController()
|
||||||
->CommitText(blink::WebString::FromUTF8(text),
|
->CommitText(blink::WebString::FromUTF8(text),
|
||||||
blink::WebVector<ui::ImeTextSpan>(), blink::WebRange(), 0);
|
blink::WebVector<ui::ImeTextSpan>(), blink::WebRange(),
|
||||||
|
0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::u16string InsertCSS(v8::Local<v8::Value> window,
|
std::u16string InsertCSS(v8::Isolate* isolate,
|
||||||
const std::string& css,
|
const std::string& css,
|
||||||
gin_helper::Arguments* args) {
|
gin::Arguments* args) {
|
||||||
blink::WebDocument::CSSOrigin css_origin =
|
blink::WebDocument::CSSOrigin css_origin =
|
||||||
blink::WebDocument::CSSOrigin::kAuthorOrigin;
|
blink::WebDocument::CSSOrigin::kAuthorOrigin;
|
||||||
|
|
||||||
|
@ -579,34 +640,25 @@ std::u16string InsertCSS(v8::Local<v8::Value> window,
|
||||||
if (args->GetNext(&options))
|
if (args->GetNext(&options))
|
||||||
options.Get("cssOrigin", &css_origin);
|
options.Get("cssOrigin", &css_origin);
|
||||||
|
|
||||||
auto* render_frame = GetRenderFrame(window);
|
content::RenderFrame* render_frame;
|
||||||
if (!render_frame) {
|
if (!MaybeGetRenderFrame(isolate, "insertCSS", &render_frame))
|
||||||
args->ThrowError(
|
|
||||||
"Render frame was torn down before webFrame.insertCSS could be "
|
|
||||||
"executed");
|
|
||||||
return std::u16string();
|
return std::u16string();
|
||||||
}
|
|
||||||
|
|
||||||
blink::WebFrame* web_frame = render_frame->GetWebFrame();
|
blink::WebFrame* web_frame = render_frame->GetWebFrame();
|
||||||
if (web_frame->IsWebLocalFrame()) {
|
if (web_frame->IsWebLocalFrame()) {
|
||||||
return web_frame->ToWebLocalFrame()
|
return web_frame->ToWebLocalFrame()
|
||||||
->GetDocument()
|
->GetDocument()
|
||||||
.InsertStyleSheet(blink::WebString::FromUTF8(css), nullptr, css_origin)
|
.InsertStyleSheet(blink::WebString::FromUTF8(css), nullptr,
|
||||||
|
css_origin)
|
||||||
.Utf16();
|
.Utf16();
|
||||||
}
|
}
|
||||||
return std::u16string();
|
return std::u16string();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoveInsertedCSS(gin_helper::ErrorThrower thrower,
|
void RemoveInsertedCSS(v8::Isolate* isolate, const std::u16string& key) {
|
||||||
v8::Local<v8::Value> window,
|
content::RenderFrame* render_frame;
|
||||||
const std::u16string& key) {
|
if (!MaybeGetRenderFrame(isolate, "removeInsertedCSS", &render_frame))
|
||||||
auto* render_frame = GetRenderFrame(window);
|
|
||||||
if (!render_frame) {
|
|
||||||
thrower.ThrowError(
|
|
||||||
"Render frame was torn down before webFrame.removeInsertedCSS could be "
|
|
||||||
"executed");
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
blink::WebFrame* web_frame = render_frame->GetWebFrame();
|
blink::WebFrame* web_frame = render_frame->GetWebFrame();
|
||||||
if (web_frame->IsWebLocalFrame()) {
|
if (web_frame->IsWebLocalFrame()) {
|
||||||
|
@ -615,18 +667,18 @@ void RemoveInsertedCSS(gin_helper::ErrorThrower thrower,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
v8::Local<v8::Promise> ExecuteJavaScript(gin_helper::Arguments* args,
|
v8::Local<v8::Promise> ExecuteJavaScript(gin::Arguments* gin_args,
|
||||||
v8::Local<v8::Value> window,
|
|
||||||
const std::u16string& code) {
|
const std::u16string& code) {
|
||||||
|
gin_helper::Arguments* args = static_cast<gin_helper::Arguments*>(gin_args);
|
||||||
|
|
||||||
v8::Isolate* isolate = args->isolate();
|
v8::Isolate* isolate = args->isolate();
|
||||||
gin_helper::Promise<v8::Local<v8::Value>> promise(isolate);
|
gin_helper::Promise<v8::Local<v8::Value>> promise(isolate);
|
||||||
v8::Local<v8::Promise> handle = promise.GetHandle();
|
v8::Local<v8::Promise> handle = promise.GetHandle();
|
||||||
|
|
||||||
auto* render_frame = GetRenderFrame(window);
|
content::RenderFrame* render_frame;
|
||||||
if (!render_frame) {
|
std::string error_msg;
|
||||||
promise.RejectWithErrorMessage(
|
if (!MaybeGetRenderFrame(&error_msg, "executeJavaScript", &render_frame)) {
|
||||||
"Render frame was torn down before webFrame.executeJavaScript could be "
|
promise.RejectWithErrorMessage(error_msg);
|
||||||
"executed");
|
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -646,19 +698,20 @@ v8::Local<v8::Promise> ExecuteJavaScript(gin_helper::Arguments* args,
|
||||||
}
|
}
|
||||||
|
|
||||||
v8::Local<v8::Promise> ExecuteJavaScriptInIsolatedWorld(
|
v8::Local<v8::Promise> ExecuteJavaScriptInIsolatedWorld(
|
||||||
gin_helper::Arguments* args,
|
gin::Arguments* gin_args,
|
||||||
v8::Local<v8::Value> window,
|
|
||||||
int world_id,
|
int world_id,
|
||||||
const std::vector<gin_helper::Dictionary>& scripts) {
|
const std::vector<gin_helper::Dictionary>& scripts) {
|
||||||
|
gin_helper::Arguments* args = static_cast<gin_helper::Arguments*>(gin_args);
|
||||||
|
|
||||||
v8::Isolate* isolate = args->isolate();
|
v8::Isolate* isolate = args->isolate();
|
||||||
gin_helper::Promise<v8::Local<v8::Value>> promise(isolate);
|
gin_helper::Promise<v8::Local<v8::Value>> promise(isolate);
|
||||||
v8::Local<v8::Promise> handle = promise.GetHandle();
|
v8::Local<v8::Promise> handle = promise.GetHandle();
|
||||||
|
|
||||||
auto* render_frame = GetRenderFrame(window);
|
content::RenderFrame* render_frame;
|
||||||
if (!render_frame) {
|
std::string error_msg;
|
||||||
promise.RejectWithErrorMessage(
|
if (!MaybeGetRenderFrame(&error_msg, "executeJavaScriptInIsolatedWorld",
|
||||||
"Render frame was torn down before "
|
&render_frame)) {
|
||||||
"webFrame.executeJavaScriptInIsolatedWorld could be executed");
|
promise.RejectWithErrorMessage(error_msg);
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -708,17 +761,12 @@ v8::Local<v8::Promise> ExecuteJavaScriptInIsolatedWorld(
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetIsolatedWorldInfo(v8::Local<v8::Value> window,
|
void SetIsolatedWorldInfo(v8::Isolate* isolate,
|
||||||
int world_id,
|
int world_id,
|
||||||
const gin_helper::Dictionary& options,
|
const gin_helper::Dictionary& options) {
|
||||||
gin_helper::Arguments* args) {
|
content::RenderFrame* render_frame;
|
||||||
auto* render_frame = GetRenderFrame(window);
|
if (!MaybeGetRenderFrame(isolate, "setIsolatedWorldInfo", &render_frame))
|
||||||
if (!render_frame) {
|
|
||||||
args->ThrowError(
|
|
||||||
"Render frame was torn down before webFrame.setIsolatedWorldInfo could "
|
|
||||||
"be executed");
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
std::string origin_url, security_policy, name;
|
std::string origin_url, security_policy, name;
|
||||||
options.Get("securityOrigin", &origin_url);
|
options.Get("securityOrigin", &origin_url);
|
||||||
|
@ -726,7 +774,7 @@ void SetIsolatedWorldInfo(v8::Local<v8::Value> window,
|
||||||
options.Get("name", &name);
|
options.Get("name", &name);
|
||||||
|
|
||||||
if (!security_policy.empty() && origin_url.empty()) {
|
if (!security_policy.empty() && origin_url.empty()) {
|
||||||
args->ThrowError(
|
gin_helper::ErrorThrower(isolate).ThrowError(
|
||||||
"If csp is specified, securityOrigin should also be specified");
|
"If csp is specified, securityOrigin should also be specified");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -746,21 +794,24 @@ blink::WebCacheResourceTypeStats GetResourceUsage(v8::Isolate* isolate) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
|
#if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
|
||||||
|
bool IsWordMisspelled(v8::Isolate* isolate, const std::string& word) {
|
||||||
|
content::RenderFrame* render_frame;
|
||||||
|
if (!MaybeGetRenderFrame(isolate, "isWordMisspelled", &render_frame))
|
||||||
|
return false;
|
||||||
|
|
||||||
bool IsWordMisspelled(v8::Isolate* isolate,
|
return !SpellCheckWord(render_frame, word, nullptr);
|
||||||
v8::Local<v8::Value> window,
|
|
||||||
const std::string& word) {
|
|
||||||
return !SpellCheckWord(isolate, window, word, nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::u16string> GetWordSuggestions(v8::Isolate* isolate,
|
std::vector<std::u16string> GetWordSuggestions(v8::Isolate* isolate,
|
||||||
v8::Local<v8::Value> window,
|
|
||||||
const std::string& word) {
|
const std::string& word) {
|
||||||
|
content::RenderFrame* render_frame;
|
||||||
std::vector<std::u16string> suggestions;
|
std::vector<std::u16string> suggestions;
|
||||||
SpellCheckWord(isolate, window, word, &suggestions);
|
if (!MaybeGetRenderFrame(isolate, "getWordSuggestions", &render_frame))
|
||||||
|
return suggestions;
|
||||||
|
|
||||||
|
SpellCheckWord(render_frame, word, &suggestions);
|
||||||
return suggestions;
|
return suggestions;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void ClearCache(v8::Isolate* isolate) {
|
void ClearCache(v8::Isolate* isolate) {
|
||||||
|
@ -771,120 +822,143 @@ void ClearCache(v8::Isolate* isolate) {
|
||||||
}
|
}
|
||||||
|
|
||||||
v8::Local<v8::Value> FindFrameByRoutingId(v8::Isolate* isolate,
|
v8::Local<v8::Value> FindFrameByRoutingId(v8::Isolate* isolate,
|
||||||
v8::Local<v8::Value> window,
|
|
||||||
int routing_id) {
|
int routing_id) {
|
||||||
content::RenderFrame* render_frame =
|
content::RenderFrame* render_frame =
|
||||||
content::RenderFrame::FromRoutingID(routing_id);
|
content::RenderFrame::FromRoutingID(routing_id);
|
||||||
if (render_frame)
|
if (render_frame)
|
||||||
return render_frame->GetWebFrame()->MainWorldScriptContext()->Global();
|
return WebFrameRenderer::Create(isolate, render_frame).ToV8();
|
||||||
else
|
else
|
||||||
return v8::Null(isolate);
|
return v8::Null(isolate);
|
||||||
}
|
}
|
||||||
|
|
||||||
v8::Local<v8::Value> GetOpener(v8::Isolate* isolate,
|
v8::Local<v8::Value> GetOpener(v8::Isolate* isolate) {
|
||||||
v8::Local<v8::Value> window) {
|
content::RenderFrame* render_frame;
|
||||||
auto* render_frame = GetRenderFrame(window);
|
if (!MaybeGetRenderFrame(isolate, "opener", &render_frame))
|
||||||
if (!render_frame)
|
|
||||||
return v8::Null(isolate);
|
return v8::Null(isolate);
|
||||||
|
|
||||||
blink::WebFrame* frame = render_frame->GetWebFrame()->Opener();
|
blink::WebFrame* frame = render_frame->GetWebFrame()->Opener();
|
||||||
if (frame && frame->IsWebLocalFrame())
|
if (frame && frame->IsWebLocalFrame())
|
||||||
return frame->ToWebLocalFrame()->MainWorldScriptContext()->Global();
|
return WebFrameRenderer::Create(
|
||||||
|
isolate,
|
||||||
|
content::RenderFrame::FromWebFrame(frame->ToWebLocalFrame()))
|
||||||
|
.ToV8();
|
||||||
else
|
else
|
||||||
return v8::Null(isolate);
|
return v8::Null(isolate);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't name it as GetParent, Windows has API with same name.
|
// Don't name it as GetParent, Windows has API with same name.
|
||||||
v8::Local<v8::Value> GetFrameParent(v8::Isolate* isolate,
|
v8::Local<v8::Value> GetFrameParent(v8::Isolate* isolate) {
|
||||||
v8::Local<v8::Value> window) {
|
content::RenderFrame* render_frame;
|
||||||
blink::WebFrame* frame = GetRenderFrame(window)->GetWebFrame()->Parent();
|
if (!MaybeGetRenderFrame(isolate, "parent", &render_frame))
|
||||||
|
return v8::Null(isolate);
|
||||||
|
|
||||||
|
blink::WebFrame* frame = render_frame->GetWebFrame()->Parent();
|
||||||
if (frame && frame->IsWebLocalFrame())
|
if (frame && frame->IsWebLocalFrame())
|
||||||
return frame->ToWebLocalFrame()->MainWorldScriptContext()->Global();
|
return WebFrameRenderer::Create(
|
||||||
|
isolate,
|
||||||
|
content::RenderFrame::FromWebFrame(frame->ToWebLocalFrame()))
|
||||||
|
.ToV8();
|
||||||
else
|
else
|
||||||
return v8::Null(isolate);
|
return v8::Null(isolate);
|
||||||
}
|
}
|
||||||
|
|
||||||
v8::Local<v8::Value> GetTop(v8::Isolate* isolate, v8::Local<v8::Value> window) {
|
v8::Local<v8::Value> GetTop(v8::Isolate* isolate) {
|
||||||
auto* render_frame = GetRenderFrame(window);
|
content::RenderFrame* render_frame;
|
||||||
if (!render_frame)
|
if (!MaybeGetRenderFrame(isolate, "top", &render_frame))
|
||||||
return v8::Null(isolate);
|
return v8::Null(isolate);
|
||||||
|
|
||||||
blink::WebFrame* frame = render_frame->GetWebFrame()->Top();
|
blink::WebFrame* frame = render_frame->GetWebFrame()->Top();
|
||||||
if (frame && frame->IsWebLocalFrame())
|
if (frame && frame->IsWebLocalFrame())
|
||||||
return frame->ToWebLocalFrame()->MainWorldScriptContext()->Global();
|
return WebFrameRenderer::Create(
|
||||||
|
isolate,
|
||||||
|
content::RenderFrame::FromWebFrame(frame->ToWebLocalFrame()))
|
||||||
|
.ToV8();
|
||||||
else
|
else
|
||||||
return v8::Null(isolate);
|
return v8::Null(isolate);
|
||||||
}
|
}
|
||||||
|
|
||||||
v8::Local<v8::Value> GetFirstChild(v8::Isolate* isolate,
|
v8::Local<v8::Value> GetFirstChild(v8::Isolate* isolate) {
|
||||||
v8::Local<v8::Value> window) {
|
content::RenderFrame* render_frame;
|
||||||
auto* render_frame = GetRenderFrame(window);
|
if (!MaybeGetRenderFrame(isolate, "firstChild", &render_frame))
|
||||||
if (!render_frame)
|
|
||||||
return v8::Null(isolate);
|
return v8::Null(isolate);
|
||||||
|
|
||||||
blink::WebFrame* frame = render_frame->GetWebFrame()->FirstChild();
|
blink::WebFrame* frame = render_frame->GetWebFrame()->FirstChild();
|
||||||
if (frame && frame->IsWebLocalFrame())
|
if (frame && frame->IsWebLocalFrame())
|
||||||
return frame->ToWebLocalFrame()->MainWorldScriptContext()->Global();
|
return WebFrameRenderer::Create(
|
||||||
|
isolate,
|
||||||
|
content::RenderFrame::FromWebFrame(frame->ToWebLocalFrame()))
|
||||||
|
.ToV8();
|
||||||
else
|
else
|
||||||
return v8::Null(isolate);
|
return v8::Null(isolate);
|
||||||
}
|
}
|
||||||
|
|
||||||
v8::Local<v8::Value> GetNextSibling(v8::Isolate* isolate,
|
v8::Local<v8::Value> GetNextSibling(v8::Isolate* isolate) {
|
||||||
v8::Local<v8::Value> window) {
|
content::RenderFrame* render_frame;
|
||||||
auto* render_frame = GetRenderFrame(window);
|
if (!MaybeGetRenderFrame(isolate, "nextSibling", &render_frame))
|
||||||
if (!render_frame)
|
|
||||||
return v8::Null(isolate);
|
return v8::Null(isolate);
|
||||||
|
|
||||||
blink::WebFrame* frame = render_frame->GetWebFrame()->NextSibling();
|
blink::WebFrame* frame = render_frame->GetWebFrame()->NextSibling();
|
||||||
if (frame && frame->IsWebLocalFrame())
|
if (frame && frame->IsWebLocalFrame())
|
||||||
return frame->ToWebLocalFrame()->MainWorldScriptContext()->Global();
|
return WebFrameRenderer::Create(
|
||||||
|
isolate,
|
||||||
|
content::RenderFrame::FromWebFrame(frame->ToWebLocalFrame()))
|
||||||
|
.ToV8();
|
||||||
else
|
else
|
||||||
return v8::Null(isolate);
|
return v8::Null(isolate);
|
||||||
}
|
}
|
||||||
|
|
||||||
v8::Local<v8::Value> GetFrameForSelector(v8::Isolate* isolate,
|
v8::Local<v8::Value> GetFrameForSelector(v8::Isolate* isolate,
|
||||||
v8::Local<v8::Value> window,
|
|
||||||
const std::string& selector) {
|
const std::string& selector) {
|
||||||
|
content::RenderFrame* render_frame;
|
||||||
|
if (!MaybeGetRenderFrame(isolate, "getFrameForSelector", &render_frame))
|
||||||
|
return v8::Null(isolate);
|
||||||
|
|
||||||
blink::WebElement element =
|
blink::WebElement element =
|
||||||
GetRenderFrame(window)->GetWebFrame()->GetDocument().QuerySelector(
|
render_frame->GetWebFrame()->GetDocument().QuerySelector(
|
||||||
blink::WebString::FromUTF8(selector));
|
blink::WebString::FromUTF8(selector));
|
||||||
if (element.IsNull()) // not found
|
if (element.IsNull()) // not found
|
||||||
return v8::Null(isolate);
|
return v8::Null(isolate);
|
||||||
|
|
||||||
blink::WebFrame* frame = blink::WebFrame::FromFrameOwnerElement(element);
|
blink::WebFrame* frame = blink::WebFrame::FromFrameOwnerElement(element);
|
||||||
if (frame && frame->IsWebLocalFrame())
|
if (frame && frame->IsWebLocalFrame())
|
||||||
return frame->ToWebLocalFrame()->MainWorldScriptContext()->Global();
|
return WebFrameRenderer::Create(
|
||||||
|
isolate,
|
||||||
|
content::RenderFrame::FromWebFrame(frame->ToWebLocalFrame()))
|
||||||
|
.ToV8();
|
||||||
else
|
else
|
||||||
return v8::Null(isolate);
|
return v8::Null(isolate);
|
||||||
}
|
}
|
||||||
|
|
||||||
v8::Local<v8::Value> FindFrameByName(v8::Isolate* isolate,
|
v8::Local<v8::Value> FindFrameByName(v8::Isolate* isolate,
|
||||||
v8::Local<v8::Value> window,
|
|
||||||
const std::string& name) {
|
const std::string& name) {
|
||||||
auto* render_frame = GetRenderFrame(window);
|
content::RenderFrame* render_frame;
|
||||||
if (!render_frame)
|
if (!MaybeGetRenderFrame(isolate, "getFrameForSelector", &render_frame))
|
||||||
return v8::Null(isolate);
|
return v8::Null(isolate);
|
||||||
|
|
||||||
blink::WebFrame* frame = render_frame->GetWebFrame()->FindFrameByName(
|
blink::WebFrame* frame = render_frame->GetWebFrame()->FindFrameByName(
|
||||||
blink::WebString::FromUTF8(name));
|
blink::WebString::FromUTF8(name));
|
||||||
if (frame && frame->IsWebLocalFrame())
|
if (frame && frame->IsWebLocalFrame())
|
||||||
return frame->ToWebLocalFrame()->MainWorldScriptContext()->Global();
|
return WebFrameRenderer::Create(
|
||||||
|
isolate,
|
||||||
|
content::RenderFrame::FromWebFrame(frame->ToWebLocalFrame()))
|
||||||
|
.ToV8();
|
||||||
else
|
else
|
||||||
return v8::Null(isolate);
|
return v8::Null(isolate);
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetRoutingId(gin_helper::ErrorThrower thrower,
|
int GetRoutingId(v8::Isolate* isolate) {
|
||||||
v8::Local<v8::Value> window) {
|
content::RenderFrame* render_frame;
|
||||||
auto* render_frame = GetRenderFrame(window);
|
if (!MaybeGetRenderFrame(isolate, "routingId", &render_frame))
|
||||||
if (!render_frame) {
|
|
||||||
thrower.ThrowError(
|
|
||||||
"Render frame was torn down before webFrame.getRoutingId could be "
|
|
||||||
"executed");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
return render_frame->GetRoutingID();
|
return render_frame->GetRoutingID();
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
gin::WrapperInfo WebFrameRenderer::kWrapperInfo = {gin::kEmbedderNativeGin};
|
||||||
|
|
||||||
|
// static
|
||||||
|
std::set<SpellCheckerHolder*> SpellCheckerHolder::instances_;
|
||||||
|
|
||||||
} // namespace api
|
} // namespace api
|
||||||
|
|
||||||
|
@ -900,39 +974,8 @@ void Initialize(v8::Local<v8::Object> exports,
|
||||||
|
|
||||||
v8::Isolate* isolate = context->GetIsolate();
|
v8::Isolate* isolate = context->GetIsolate();
|
||||||
gin_helper::Dictionary dict(isolate, exports);
|
gin_helper::Dictionary dict(isolate, exports);
|
||||||
dict.SetMethod("setName", &SetName);
|
dict.Set("mainFrame",
|
||||||
dict.SetMethod("setZoomLevel", &SetZoomLevel);
|
WebFrameRenderer::Create(isolate, GetRenderFrame(exports)));
|
||||||
dict.SetMethod("getZoomLevel", &GetZoomLevel);
|
|
||||||
dict.SetMethod("setZoomFactor", &SetZoomFactor);
|
|
||||||
dict.SetMethod("getZoomFactor", &GetZoomFactor);
|
|
||||||
dict.SetMethod("setVisualZoomLevelLimits", &SetVisualZoomLevelLimits);
|
|
||||||
dict.SetMethod("allowGuestViewElementDefinition",
|
|
||||||
&AllowGuestViewElementDefinition);
|
|
||||||
dict.SetMethod("getWebFrameId", &GetWebFrameId);
|
|
||||||
dict.SetMethod("getWebPreference", &GetWebPreference);
|
|
||||||
dict.SetMethod("setSpellCheckProvider", &SetSpellCheckProvider);
|
|
||||||
dict.SetMethod("insertText", &InsertText);
|
|
||||||
dict.SetMethod("insertCSS", &InsertCSS);
|
|
||||||
dict.SetMethod("removeInsertedCSS", &RemoveInsertedCSS);
|
|
||||||
dict.SetMethod("executeJavaScript", &ExecuteJavaScript);
|
|
||||||
dict.SetMethod("executeJavaScriptInIsolatedWorld",
|
|
||||||
&ExecuteJavaScriptInIsolatedWorld);
|
|
||||||
dict.SetMethod("setIsolatedWorldInfo", &SetIsolatedWorldInfo);
|
|
||||||
dict.SetMethod("getResourceUsage", &GetResourceUsage);
|
|
||||||
#if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
|
|
||||||
dict.SetMethod("isWordMisspelled", &IsWordMisspelled);
|
|
||||||
dict.SetMethod("getWordSuggestions", &GetWordSuggestions);
|
|
||||||
#endif
|
|
||||||
dict.SetMethod("clearCache", &ClearCache);
|
|
||||||
dict.SetMethod("_findFrameByRoutingId", &FindFrameByRoutingId);
|
|
||||||
dict.SetMethod("_getFrameForSelector", &GetFrameForSelector);
|
|
||||||
dict.SetMethod("_findFrameByName", &FindFrameByName);
|
|
||||||
dict.SetMethod("_getOpener", &GetOpener);
|
|
||||||
dict.SetMethod("_getParent", &GetFrameParent);
|
|
||||||
dict.SetMethod("_getTop", &GetTop);
|
|
||||||
dict.SetMethod("_getFirstChild", &GetFirstChild);
|
|
||||||
dict.SetMethod("_getNextSibling", &GetNextSibling);
|
|
||||||
dict.SetMethod("_getRoutingId", &GetRoutingId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
15
typings/internal-ambient.d.ts
vendored
15
typings/internal-ambient.d.ts
vendored
|
@ -114,17 +114,12 @@ declare namespace NodeJS {
|
||||||
webviewTag: boolean;
|
webviewTag: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface InternalWebFrame extends Electron.WebFrame {
|
||||||
|
getWebPreference<K extends keyof InternalWebPreferences>(name: K): InternalWebPreferences[K];
|
||||||
|
}
|
||||||
|
|
||||||
interface WebFrameBinding {
|
interface WebFrameBinding {
|
||||||
_findFrameByRoutingId(window: Window, routingId: number): Window;
|
mainFrame: InternalWebFrame;
|
||||||
_getFrameForSelector(window: Window, selector: string): Window;
|
|
||||||
_findFrameByName(window: Window, name: string): Window;
|
|
||||||
_getOpener(window: Window): Window;
|
|
||||||
_getParent(window: Window): Window;
|
|
||||||
_getTop(window: Window): Window;
|
|
||||||
_getFirstChild(window: Window): Window;
|
|
||||||
_getNextSibling(window: Window): Window;
|
|
||||||
_getRoutingId(window: Window): number;
|
|
||||||
getWebPreference<K extends keyof InternalWebPreferences>(window: Window, name: K): InternalWebPreferences[K];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type DataPipe = {
|
type DataPipe = {
|
||||||
|
|
Loading…
Reference in a new issue