mirror of
https://github.com/electron/electron.git
synced 2026-10-29 04:04:54 +08:00
* chore: bump chromium in DEPS to 157.0.8091.0 * chore: update siso revision * 8518399: [Fullscreen] Reject requestFullscreen() when FullscreenAllowed is false Upstream moved the kFullscreenAllowed pref check into a new IsFullscreenAllowedByPref() helper that is now consulted from both CanEnterFullscreenModeForTab() and EnterFullscreenModeInternal(). Electron has no Profile (ExclusiveAccessContext::GetProfile() returns nullptr), so guarding only the old call site would now reject every fullscreen request on non-Mac platforms. Disable the pref lookup inside the helper instead so it always allows fullscreen. Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8518399 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * 7867823: [android] Add a feature to propagate occlusion to viz DisplayPrivate::SetDisplayVisible() now takes a viz::mojom::DisplayVisibility enum instead of a bool. Keep the display kVisible whenever background throttling is disabled, and kInvisible only when throttling is enabled and the compositor is hidden. Ref: https://chromium-review.googlesource.com/c/chromium/src/+/7867823 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * 8510323: Use C++20 std::numbers::e and std::numbers::sqrt2 in blink Remove the cherry-pick patch now that the upstream change has rolled in. Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8510323 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * 8403316: [content] Add ContentClient::Schemes::code_cache_schemes Upstream landed the embedder code cache scheme list that feat_allow_code_cache_in_custom_schemes.patch added (it cites the patch's earlier CL 5019665), so the patch is removed. The upstream version records the schemes in blink::CommonSchemeRegistry rather than in url::SchemeRegistry, so: - RegisterSchemesAsPrivileged() now calls CommonSchemeRegistry::RegisterURLSchemeAsSupportingCodeCache() for custom schemes with codeCache enabled. The browser process registers these after RegisterContentSchemes() has already run, so it cannot rely on ContentClient::Schemes for them. Renderers keep registering them as CodeCacheWithHashing from the --code-cache-schemes switch. - ElectronContentClient lists chrome-extension in Schemes::code_cache_schemes, matching ChromeContentClient, since the browser-side checks no longer special-case IsExtensionScheme(). - feat_allow_enabling_extensions_on_custom_protocols.patch loses the removed url::AddCodeCacheScheme() lines from its context. Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8403316 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * chore: update patches * 8362417: content: Add CopyFromSurfaceSecure and plumb is_secure to capturer RenderWidgetHostViewBase::CopyFromSurface() is now final and dispatches to CopyFromSurfaceImpl(), which takes is_copy_request_secure and must pass it on to DelegatedFrameHost::CopyFromCompositingSurface(). Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8362417 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * 8499040: Decisions API: Add Blink IDL, Mojo interfaces, Echo impl, and WPTs Stub the new AIManager decision model methods as unavailable, like the other unsupported AI APIs. Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8499040 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * 8349225: Decouple Cookies API from Profile via CookiesApiDelegate ExtensionsBrowserClient::GetBrowserContextLifetimeTracker() is now pure virtual. Electron has no off-the-record sibling contexts to track, so return nullptr, which the cookies API handles. Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8349225 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * 8285500: hid: Restrict WebHID access in guest and partitioned contexts HidDelegate::IsHidAllowedForFrame() is now pure virtual and gates HidService creation. Mirror ElectronUsbDelegate::PageMayUseUsb(): deny WebViewGuests and HTTP(S) pages in non-default storage partitions. Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8285500 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * 8488316: [Linux] Query XDG portal versions per interface RequestXdgDesktopPortal() now takes the portal interface whose version to report; pass the FileChooser interface. Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8488316 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * 8508466: Remove duplicate DownloadManager::CreateDownloadItem() overload Pass an empty display_name, as the removed overload did. Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8508466 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * 8357569: Move Cookies API implementation to //extensions Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8357569 * 8485746: gin: Use v8::CppHeapExternal for CallbackHolderBase Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8485746 * fix: re-enable v8 metagen Skip-Lint: enabling a feature with cherry picked CL. * fixup! 8499040: Decisions API: Add Blink IDL, Mojo interfaces, Echo impl, and WPTs * 8526928: Reland "Mac: Activate the widget when focusing a View in an inactive widget" FocusManager::SetFocusedViewWithReason() now activates an inactive widget before focusing a View in it on macOS, and NativeWidgetMacNSWindowHost::OnIsFirstResponderChanged() no longer restores focus while the window is not key. Forward both notifications to super so the views host tracks the window's key status. Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8526928 * fix: stop the remote debugging HTTP server on shutdown DevToolsHttpHandler keeps a raw_ptr to the DevToolsManagerDelegate owned by the DevToolsManager singleton, which is destroyed at exit. Electron never stopped the HTTP server, so the delegate was freed while the handler still pointed at it. Skip-Lint: raw_ptr shutdown crash fix --------- Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com> Co-authored-by: electron-claude[bot] <279139701+electron-claude[bot]@users.noreply.github.com> Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com> Co-authored-by: deepak1556 <hop2deep@gmail.com>
408 lines
15 KiB
C++
408 lines
15 KiB
C++
// Copyright (c) 2019 GitHub, Inc.
|
|
// Use of this source code is governed by the MIT license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "shell/browser/api/electron_api_protocol.h"
|
|
|
|
#include <string_view>
|
|
#include <vector>
|
|
|
|
#include "base/command_line.h"
|
|
#include "base/no_destructor.h"
|
|
#include "content/common/url_schemes.h"
|
|
#include "content/public/browser/child_process_security_policy.h"
|
|
#include "gin/converter.h"
|
|
#include "gin/object_template_builder.h"
|
|
#include "shell/browser/browser.h"
|
|
#include "shell/browser/javascript_environment.h"
|
|
#include "shell/browser/net/protocol_source.h"
|
|
#include "shell/browser/protocol_registry.h"
|
|
#include "shell/common/gin_converters/callback_converter.h"
|
|
#include "shell/common/gin_converters/net_converter.h"
|
|
#include "shell/common/gin_converters/value_converter.h"
|
|
#include "shell/common/gin_helper/dictionary.h"
|
|
#include "shell/common/gin_helper/object_template_builder.h"
|
|
#include "shell/common/gin_helper/wrappable_pointer_tags.h"
|
|
#include "shell/common/node_includes.h"
|
|
#include "shell/common/node_util.h"
|
|
#include "shell/common/options_switches.h"
|
|
#include "third_party/blink/public/common/scheme_registry.h"
|
|
#include "url/url_util.h"
|
|
#include "v8/include/cppgc/allocation.h"
|
|
|
|
namespace {
|
|
|
|
struct SchemeOptions {
|
|
bool standard = false;
|
|
bool secure = false;
|
|
bool bypassCSP = false;
|
|
bool allowServiceWorkers = false;
|
|
bool supportFetchAPI = false;
|
|
bool corsEnabled = false;
|
|
bool stream = false;
|
|
bool codeCache = false;
|
|
bool allowExtensions = false;
|
|
};
|
|
|
|
struct CustomScheme {
|
|
std::string scheme;
|
|
SchemeOptions options;
|
|
};
|
|
|
|
} // namespace
|
|
|
|
namespace gin {
|
|
|
|
template <>
|
|
struct Converter<CustomScheme> {
|
|
static bool FromV8(v8::Isolate* isolate,
|
|
v8::Local<v8::Value> val,
|
|
CustomScheme* out) {
|
|
gin::Dictionary dict(isolate);
|
|
if (!ConvertFromV8(isolate, val, &dict))
|
|
return false;
|
|
if (!dict.Get("scheme", &(out->scheme)))
|
|
return false;
|
|
gin::Dictionary opt(isolate);
|
|
// options are optional. Default values specified in SchemeOptions are used
|
|
if (dict.Get("privileges", &opt)) {
|
|
opt.Get("standard", &(out->options.standard));
|
|
opt.Get("secure", &(out->options.secure));
|
|
opt.Get("bypassCSP", &(out->options.bypassCSP));
|
|
opt.Get("allowServiceWorkers", &(out->options.allowServiceWorkers));
|
|
opt.Get("supportFetchAPI", &(out->options.supportFetchAPI));
|
|
opt.Get("corsEnabled", &(out->options.corsEnabled));
|
|
opt.Get("stream", &(out->options.stream));
|
|
opt.Get("codeCache", &(out->options.codeCache));
|
|
opt.Get("allowExtensions", &(out->options.allowExtensions));
|
|
}
|
|
return true;
|
|
}
|
|
};
|
|
|
|
} // namespace gin
|
|
|
|
namespace electron::api {
|
|
|
|
const gin::WrapperInfo Protocol::kWrapperInfo =
|
|
electron::MakeWrapperInfo(electron::kElectronProtocol);
|
|
|
|
std::vector<std::string>& GetStandardSchemes() {
|
|
static base::NoDestructor<std::vector<std::string>> g_standard_schemes;
|
|
return *g_standard_schemes;
|
|
}
|
|
|
|
std::vector<std::string>& GetCodeCacheSchemes() {
|
|
static base::NoDestructor<std::vector<std::string>> g_code_cache_schemes;
|
|
return *g_code_cache_schemes;
|
|
}
|
|
|
|
std::vector<std::string>& GetStreamingSchemes() {
|
|
static base::NoDestructor<std::vector<std::string>> g_streaming_schemes;
|
|
return *g_streaming_schemes;
|
|
}
|
|
|
|
void AddServiceWorkerScheme(const std::string& scheme) {
|
|
// There is no API to add service worker scheme, but there is an API to
|
|
// return const reference to the schemes vector.
|
|
// If in future the API is changed to return a copy instead of reference,
|
|
// the compilation will fail, and we should add a patch at that time.
|
|
auto& mutable_schemes =
|
|
const_cast<std::vector<std::string>&>(content::GetServiceWorkerSchemes());
|
|
mutable_schemes.push_back(scheme);
|
|
}
|
|
|
|
void RegisterSchemesAsPrivileged(gin_helper::ErrorThrower thrower,
|
|
v8::Local<v8::Value> val) {
|
|
std::vector<CustomScheme> custom_schemes;
|
|
if (!gin::ConvertFromV8(thrower.isolate(), val, &custom_schemes)) {
|
|
thrower.ThrowError("Argument must be an array of custom schemes.");
|
|
return;
|
|
}
|
|
|
|
for (const auto& custom_scheme : custom_schemes) {
|
|
// Schemes are comma-separated for --*-schemes. Sanitize names so
|
|
// extra commas don't trick child processes into splitting one
|
|
// scheme into many.
|
|
if (!Browser::IsValidProtocolScheme(custom_scheme.scheme)) {
|
|
thrower.ThrowError(
|
|
"Invalid scheme name '" + custom_scheme.scheme +
|
|
"'. Scheme names must start with an ASCII letter and contain only "
|
|
"ASCII letters, digits, '+', '-', or '.'.");
|
|
return;
|
|
}
|
|
if (custom_scheme.options.codeCache && !custom_scheme.options.standard) {
|
|
thrower.ThrowError(
|
|
"Code cache can only be enabled when the custom scheme is registered "
|
|
"as standard scheme.");
|
|
return;
|
|
}
|
|
}
|
|
|
|
std::vector<std::string> secure_schemes, cspbypassing_schemes, fetch_schemes,
|
|
service_worker_schemes, cors_schemes, extension_schemes;
|
|
for (const auto& custom_scheme : custom_schemes) {
|
|
// Register scheme to privileged list (https, wss, data, chrome-extension)
|
|
if (custom_scheme.options.standard) {
|
|
auto* policy = content::ChildProcessSecurityPolicy::GetInstance();
|
|
url::AddStandardScheme(custom_scheme.scheme.c_str(),
|
|
url::SCHEME_WITH_HOST);
|
|
GetStandardSchemes().push_back(custom_scheme.scheme);
|
|
policy->RegisterWebSafeScheme(custom_scheme.scheme);
|
|
}
|
|
if (custom_scheme.options.secure) {
|
|
secure_schemes.push_back(custom_scheme.scheme);
|
|
url::AddSecureScheme(custom_scheme.scheme.c_str());
|
|
}
|
|
if (custom_scheme.options.bypassCSP) {
|
|
cspbypassing_schemes.push_back(custom_scheme.scheme);
|
|
url::AddCSPBypassingScheme(custom_scheme.scheme.c_str());
|
|
}
|
|
if (custom_scheme.options.corsEnabled) {
|
|
cors_schemes.push_back(custom_scheme.scheme);
|
|
url::AddCorsEnabledScheme(custom_scheme.scheme.c_str());
|
|
}
|
|
if (custom_scheme.options.supportFetchAPI) {
|
|
fetch_schemes.push_back(custom_scheme.scheme);
|
|
}
|
|
if (custom_scheme.options.allowServiceWorkers) {
|
|
service_worker_schemes.push_back(custom_scheme.scheme);
|
|
AddServiceWorkerScheme(custom_scheme.scheme);
|
|
}
|
|
if (custom_scheme.options.stream) {
|
|
GetStreamingSchemes().push_back(custom_scheme.scheme);
|
|
}
|
|
if (custom_scheme.options.codeCache) {
|
|
GetCodeCacheSchemes().push_back(custom_scheme.scheme);
|
|
blink::CommonSchemeRegistry::RegisterURLSchemeAsSupportingCodeCache(
|
|
custom_scheme.scheme);
|
|
}
|
|
if (custom_scheme.options.allowExtensions) {
|
|
extension_schemes.push_back(custom_scheme.scheme);
|
|
url::AddExtensionScheme(custom_scheme.scheme.c_str());
|
|
}
|
|
}
|
|
|
|
const auto AppendSchemesToCmdLine = [](const std::string_view switch_name,
|
|
std::vector<std::string> schemes) {
|
|
if (schemes.empty())
|
|
return;
|
|
// Add the schemes to command line switches, so child processes can also
|
|
// register them.
|
|
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
|
|
switch_name, base::JoinString(schemes, ","));
|
|
};
|
|
|
|
AppendSchemesToCmdLine(electron::switches::kSecureSchemes, secure_schemes);
|
|
AppendSchemesToCmdLine(electron::switches::kBypassCSPSchemes,
|
|
cspbypassing_schemes);
|
|
AppendSchemesToCmdLine(electron::switches::kCORSSchemes, cors_schemes);
|
|
AppendSchemesToCmdLine(electron::switches::kFetchSchemes, fetch_schemes);
|
|
AppendSchemesToCmdLine(electron::switches::kServiceWorkerSchemes,
|
|
service_worker_schemes);
|
|
AppendSchemesToCmdLine(electron::switches::kExtensionSchemes,
|
|
extension_schemes);
|
|
AppendSchemesToCmdLine(electron::switches::kStandardSchemes,
|
|
GetStandardSchemes());
|
|
AppendSchemesToCmdLine(electron::switches::kStreamingSchemes,
|
|
GetStreamingSchemes());
|
|
AppendSchemesToCmdLine(electron::switches::kCodeCacheSchemes,
|
|
GetCodeCacheSchemes());
|
|
}
|
|
|
|
Protocol::Protocol(ProtocolRegistry* protocol_registry)
|
|
: protocol_registry_{protocol_registry} {}
|
|
|
|
Protocol::~Protocol() = default;
|
|
|
|
// Convert error code to string.
|
|
// static
|
|
std::string_view Protocol::ErrorCodeToString(Error error) {
|
|
switch (error) {
|
|
case Error::kRegistered:
|
|
return "The scheme has been registered";
|
|
case Error::kNotRegistered:
|
|
return "The scheme has not been registered";
|
|
case Error::kIntercepted:
|
|
return "The scheme has been intercepted";
|
|
case Error::kNotIntercepted:
|
|
return "The scheme has not been intercepted";
|
|
default:
|
|
return "Unexpected error";
|
|
}
|
|
}
|
|
|
|
Protocol::Error Protocol::RegisterProtocol(ProtocolType type,
|
|
const std::string& scheme,
|
|
const ProtocolHandler& handler) {
|
|
bool added = protocol_registry_->RegisterProtocol(type, scheme, handler);
|
|
return added ? Error::kOK : Error::kRegistered;
|
|
}
|
|
|
|
bool Protocol::UnregisterProtocol(const std::string& scheme,
|
|
gin::Arguments* args) {
|
|
bool removed = protocol_registry_->UnregisterProtocol(scheme);
|
|
HandleOptionalCallback(args, removed ? Error::kOK : Error::kNotRegistered);
|
|
return removed;
|
|
}
|
|
|
|
bool Protocol::IsProtocolRegistered(const std::string& scheme) {
|
|
return protocol_registry_->FindRegistered(scheme) != nullptr;
|
|
}
|
|
|
|
void Protocol::RegisterSource(gin_helper::ErrorThrower thrower,
|
|
const std::string& scheme,
|
|
const base::DictValue& options) {
|
|
if (ProtocolRegistry::IsBuiltinScheme(scheme)) {
|
|
thrower.ThrowError("Cannot register a source for built-in scheme " +
|
|
scheme);
|
|
return;
|
|
}
|
|
std::string error;
|
|
scoped_refptr<const ProtocolSource> source =
|
|
ProtocolSource::Create(options, &error);
|
|
if (!source) {
|
|
thrower.ThrowTypeError(error);
|
|
return;
|
|
}
|
|
if (!protocol_registry_->RegisterSource(scheme, std::move(source)))
|
|
thrower.ThrowError("Scheme " + scheme + " is already handled");
|
|
}
|
|
|
|
bool Protocol::UnregisterSource(const std::string& scheme) {
|
|
return protocol_registry_->UnregisterSource(scheme);
|
|
}
|
|
|
|
v8::Local<v8::Value> Protocol::GetSource(v8::Isolate* isolate,
|
|
const std::string& scheme) {
|
|
const ProtocolSource* source = protocol_registry_->FindSource(scheme);
|
|
if (!source)
|
|
return v8::Null(isolate);
|
|
return gin::ConvertToV8(isolate, base::ValueView(source->spec()));
|
|
}
|
|
|
|
Protocol::Error Protocol::InterceptProtocol(ProtocolType type,
|
|
const std::string& scheme,
|
|
const ProtocolHandler& handler) {
|
|
bool added = protocol_registry_->InterceptProtocol(type, scheme, handler);
|
|
return added ? Error::kOK : Error::kIntercepted;
|
|
}
|
|
|
|
bool Protocol::UninterceptProtocol(const std::string& scheme,
|
|
gin::Arguments* args) {
|
|
bool removed = protocol_registry_->UninterceptProtocol(scheme);
|
|
HandleOptionalCallback(args, removed ? Error::kOK : Error::kNotIntercepted);
|
|
return removed;
|
|
}
|
|
|
|
bool Protocol::IsProtocolIntercepted(const std::string& scheme) {
|
|
return protocol_registry_->FindIntercepted(scheme) != nullptr;
|
|
}
|
|
|
|
void Protocol::HandleOptionalCallback(gin::Arguments* args, Error error) {
|
|
base::RepeatingCallback<void(v8::Local<v8::Value>)> callback;
|
|
if (args->GetNext(&callback)) {
|
|
util::EmitWarning(
|
|
args->isolate(),
|
|
"The callback argument of protocol module APIs is no longer needed.",
|
|
"ProtocolDeprecateCallback");
|
|
if (error == Error::kOK)
|
|
callback.Run(v8::Null(args->isolate()));
|
|
else
|
|
callback.Run(v8::Exception::Error(
|
|
gin::StringToV8(args->isolate(), ErrorCodeToString(error))));
|
|
}
|
|
}
|
|
|
|
// static
|
|
Protocol* Protocol::Create(v8::Isolate* isolate,
|
|
ProtocolRegistry* protocol_registry) {
|
|
return cppgc::MakeGarbageCollected<Protocol>(
|
|
isolate->GetCppHeap()->GetAllocationHandle(), protocol_registry);
|
|
}
|
|
|
|
// static
|
|
Protocol* Protocol::New(gin_helper::ErrorThrower thrower) {
|
|
thrower.ThrowError("Protocol cannot be created from JS");
|
|
return {};
|
|
}
|
|
|
|
// static
|
|
void Protocol::FillObjectTemplate(v8::Isolate* isolate,
|
|
v8::Local<v8::ObjectTemplate> tmpl) {
|
|
gin::ObjectTemplateBuilder(isolate, GetClassName(), tmpl)
|
|
.SetMethod("registerStringProtocol",
|
|
&Protocol::RegisterProtocolFor<ProtocolType::kString>)
|
|
.SetMethod("registerBufferProtocol",
|
|
&Protocol::RegisterProtocolFor<ProtocolType::kBuffer>)
|
|
.SetMethod("registerFileProtocol",
|
|
&Protocol::RegisterProtocolFor<ProtocolType::kFile>)
|
|
.SetMethod("registerHttpProtocol",
|
|
&Protocol::RegisterProtocolFor<ProtocolType::kHttp>)
|
|
.SetMethod("registerStreamProtocol",
|
|
&Protocol::RegisterProtocolFor<ProtocolType::kStream>)
|
|
.SetMethod("registerProtocol",
|
|
&Protocol::RegisterProtocolFor<ProtocolType::kFree>)
|
|
.SetMethod("unregisterProtocol", &Protocol::UnregisterProtocol)
|
|
.SetMethod("isProtocolRegistered", &Protocol::IsProtocolRegistered)
|
|
.SetMethod("registerSource", &Protocol::RegisterSource)
|
|
.SetMethod("unregisterSource", &Protocol::UnregisterSource)
|
|
.SetMethod("getSource", &Protocol::GetSource)
|
|
.SetMethod("interceptStringProtocol",
|
|
&Protocol::InterceptProtocolFor<ProtocolType::kString>)
|
|
.SetMethod("interceptBufferProtocol",
|
|
&Protocol::InterceptProtocolFor<ProtocolType::kBuffer>)
|
|
.SetMethod("interceptFileProtocol",
|
|
&Protocol::InterceptProtocolFor<ProtocolType::kFile>)
|
|
.SetMethod("interceptHttpProtocol",
|
|
&Protocol::InterceptProtocolFor<ProtocolType::kHttp>)
|
|
.SetMethod("interceptStreamProtocol",
|
|
&Protocol::InterceptProtocolFor<ProtocolType::kStream>)
|
|
.SetMethod("interceptProtocol",
|
|
&Protocol::InterceptProtocolFor<ProtocolType::kFree>)
|
|
.SetMethod("uninterceptProtocol", &Protocol::UninterceptProtocol)
|
|
.SetMethod("isProtocolIntercepted", &Protocol::IsProtocolIntercepted)
|
|
.Build();
|
|
}
|
|
|
|
const gin::WrapperInfo* Protocol::wrapper_info() const {
|
|
return &kWrapperInfo;
|
|
}
|
|
|
|
const char* Protocol::GetHumanReadableName() const {
|
|
return "Electron / Protocol";
|
|
}
|
|
|
|
} // namespace electron::api
|
|
|
|
namespace {
|
|
|
|
void RegisterSchemesAsPrivileged(gin_helper::ErrorThrower thrower,
|
|
v8::Local<v8::Value> val) {
|
|
if (electron::Browser::Get()->is_ready()) {
|
|
thrower.ThrowError(
|
|
"protocol.registerSchemesAsPrivileged should be called before "
|
|
"app is ready");
|
|
return;
|
|
}
|
|
|
|
electron::api::RegisterSchemesAsPrivileged(thrower, val);
|
|
}
|
|
|
|
void Initialize(v8::Local<v8::Object> exports,
|
|
v8::Local<v8::Value> unused,
|
|
v8::Local<v8::Context> context,
|
|
void* priv) {
|
|
v8::Isolate* const isolate = electron::JavascriptEnvironment::GetIsolate();
|
|
gin_helper::Dictionary dict{isolate, exports};
|
|
dict.Set("Protocol",
|
|
electron::api::Protocol::GetConstructor(
|
|
isolate, context, &electron::api::Protocol::kWrapperInfo));
|
|
dict.SetMethod<&RegisterSchemesAsPrivileged>("registerSchemesAsPrivileged");
|
|
dict.SetMethod<&electron::api::GetStandardSchemes>("getStandardSchemes");
|
|
}
|
|
|
|
} // namespace
|
|
|
|
NODE_LINKED_BINDING_CONTEXT_AWARE(electron_browser_protocol, Initialize)
|