feat: move webFrame scheme privilege methods to main process (#16416)
* chore: deprecate webFrame.registerURLSchemeAsPrivileged * Add register schemes protocol api * update branch to enable browser process API * Revert deprecation changes * Fetch API support * Updated api to take an array, still working on tests * Update tests * Remove web frame API * Minor changes * update scheme registrations on browser and renderer process * fix: enable ses.getBlobData spec * Update breaking changes doc
This commit is contained in:
parent
257de6a963
commit
940c4c0787
19 changed files with 319 additions and 319 deletions
|
@ -213,18 +213,30 @@ base::RefCountedMemory* AtomContentClient::GetDataResourceBytes(
|
|||
}
|
||||
|
||||
void AtomContentClient::AddAdditionalSchemes(Schemes* schemes) {
|
||||
schemes->standard_schemes.push_back("chrome-extension");
|
||||
|
||||
std::vector<std::string> splited;
|
||||
ConvertStringWithSeparatorToVector(&splited, ",",
|
||||
switches::kRegisterServiceWorkerSchemes);
|
||||
switches::kServiceWorkerSchemes);
|
||||
for (const std::string& scheme : splited)
|
||||
schemes->service_worker_schemes.push_back(scheme);
|
||||
schemes->service_worker_schemes.push_back(url::kFileScheme);
|
||||
|
||||
ConvertStringWithSeparatorToVector(&splited, ",", switches::kStandardSchemes);
|
||||
for (const std::string& scheme : splited)
|
||||
schemes->standard_schemes.push_back(scheme);
|
||||
schemes->standard_schemes.push_back("chrome-extension");
|
||||
|
||||
ConvertStringWithSeparatorToVector(&splited, ",", switches::kSecureSchemes);
|
||||
for (const std::string& scheme : splited)
|
||||
schemes->secure_schemes.push_back(scheme);
|
||||
|
||||
ConvertStringWithSeparatorToVector(&splited, ",",
|
||||
switches::kBypassCSPSchemes);
|
||||
for (const std::string& scheme : splited)
|
||||
schemes->csp_bypassing_schemes.push_back(scheme);
|
||||
|
||||
ConvertStringWithSeparatorToVector(&splited, ",", switches::kCORSSchemes);
|
||||
for (const std::string& scheme : splited)
|
||||
schemes->cors_enabled_schemes.push_back(scheme);
|
||||
}
|
||||
|
||||
void AtomContentClient::AddPepperPlugins(
|
||||
|
|
|
@ -24,47 +24,119 @@
|
|||
|
||||
using content::BrowserThread;
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
namespace {
|
||||
|
||||
// List of registered custom standard schemes.
|
||||
std::vector<std::string> g_standard_schemes;
|
||||
|
||||
struct SchemeOptions {
|
||||
bool standard = false;
|
||||
bool secure = false;
|
||||
bool bypassCSP = false;
|
||||
bool allowServiceWorkers = false;
|
||||
bool supportFetchAPI = false;
|
||||
bool corsEnabled = false;
|
||||
};
|
||||
|
||||
struct CustomScheme {
|
||||
std::string scheme;
|
||||
SchemeOptions options;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace mate {
|
||||
|
||||
template <>
|
||||
struct Converter<CustomScheme> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
CustomScheme* out) {
|
||||
mate::Dictionary dict;
|
||||
if (!ConvertFromV8(isolate, val, &dict))
|
||||
return false;
|
||||
if (!dict.Get("scheme", &(out->scheme)))
|
||||
return false;
|
||||
mate::Dictionary opt;
|
||||
// options are optional. Default values specified in SchemeOptions are used
|
||||
if (dict.Get("options", &opt)) {
|
||||
opt.Get("standard", &(out->options.standard));
|
||||
opt.Get("supportFetchAPI", &(out->options.supportFetchAPI));
|
||||
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));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
std::vector<std::string> GetStandardSchemes() {
|
||||
return g_standard_schemes;
|
||||
}
|
||||
|
||||
void RegisterStandardSchemes(const std::vector<std::string>& schemes,
|
||||
mate::Arguments* args) {
|
||||
g_standard_schemes = schemes;
|
||||
void RegisterSchemesAsPrivileged(v8::Local<v8::Value> val,
|
||||
mate::Arguments* args) {
|
||||
std::vector<CustomScheme> custom_schemes;
|
||||
if (!mate::ConvertFromV8(args->isolate(), val, &custom_schemes)) {
|
||||
args->ThrowError("Argument must be an array of custom schemes.");
|
||||
return;
|
||||
}
|
||||
|
||||
mate::Dictionary opts;
|
||||
bool secure = false;
|
||||
args->GetNext(&opts) && opts.Get("secure", &secure);
|
||||
|
||||
// Dynamically register the schemes.
|
||||
auto* policy = content::ChildProcessSecurityPolicy::GetInstance();
|
||||
for (const std::string& scheme : schemes) {
|
||||
url::AddStandardScheme(scheme.c_str(), url::SCHEME_WITH_HOST);
|
||||
if (secure) {
|
||||
url::AddSecureScheme(scheme.c_str());
|
||||
std::vector<std::string> secure_schemes, cspbypassing_schemes, fetch_schemes,
|
||||
service_worker_schemes, cors_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);
|
||||
g_standard_schemes.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);
|
||||
}
|
||||
policy->RegisterWebSafeScheme(scheme);
|
||||
}
|
||||
|
||||
// Add the schemes to command line switches, so child processes can also
|
||||
// register them.
|
||||
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
|
||||
atom::switches::kStandardSchemes, base::JoinString(schemes, ","));
|
||||
if (secure) {
|
||||
const auto AppendSchemesToCmdLine = [](const char* switch_name,
|
||||
std::vector<std::string> schemes) {
|
||||
// Add the schemes to command line switches, so child processes can also
|
||||
// register them.
|
||||
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
|
||||
atom::switches::kSecureSchemes, base::JoinString(schemes, ","));
|
||||
}
|
||||
switch_name, base::JoinString(schemes, ","));
|
||||
};
|
||||
|
||||
AppendSchemesToCmdLine(atom::switches::kSecureSchemes, secure_schemes);
|
||||
AppendSchemesToCmdLine(atom::switches::kBypassCSPSchemes,
|
||||
cspbypassing_schemes);
|
||||
AppendSchemesToCmdLine(atom::switches::kCORSSchemes, cors_schemes);
|
||||
AppendSchemesToCmdLine(atom::switches::kFetchSchemes, fetch_schemes);
|
||||
AppendSchemesToCmdLine(atom::switches::kServiceWorkerSchemes,
|
||||
service_worker_schemes);
|
||||
AppendSchemesToCmdLine(atom::switches::kStandardSchemes, g_standard_schemes);
|
||||
}
|
||||
|
||||
Protocol::Protocol(v8::Isolate* isolate, AtomBrowserContext* browser_context)
|
||||
|
@ -73,12 +145,6 @@ Protocol::Protocol(v8::Isolate* isolate, AtomBrowserContext* browser_context)
|
|||
}
|
||||
|
||||
Protocol::~Protocol() {}
|
||||
|
||||
void Protocol::RegisterServiceWorkerSchemes(
|
||||
const std::vector<std::string>& schemes) {
|
||||
atom::AtomBrowserClient::SetCustomServiceWorkerSchemes(schemes);
|
||||
}
|
||||
|
||||
void Protocol::UnregisterProtocol(const std::string& scheme,
|
||||
mate::Arguments* args) {
|
||||
CompletionCallback callback;
|
||||
|
@ -195,8 +261,6 @@ void Protocol::BuildPrototype(v8::Isolate* isolate,
|
|||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "Protocol"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.SetMethod("registerServiceWorkerSchemes",
|
||||
&Protocol::RegisterServiceWorkerSchemes)
|
||||
.SetMethod("registerStringProtocol",
|
||||
&Protocol::RegisterProtocol<URLRequestStringJob>)
|
||||
.SetMethod("registerBufferProtocol",
|
||||
|
@ -228,16 +292,16 @@ void Protocol::BuildPrototype(v8::Isolate* isolate,
|
|||
|
||||
namespace {
|
||||
|
||||
void RegisterStandardSchemes(const std::vector<std::string>& schemes,
|
||||
mate::Arguments* args) {
|
||||
void RegisterSchemesAsPrivileged(v8::Local<v8::Value> val,
|
||||
mate::Arguments* args) {
|
||||
if (atom::Browser::Get()->is_ready()) {
|
||||
args->ThrowError(
|
||||
"protocol.registerStandardSchemes should be called before "
|
||||
"protocol.registerSchemesAsPrivileged should be called before "
|
||||
"app is ready");
|
||||
return;
|
||||
}
|
||||
|
||||
atom::api::RegisterStandardSchemes(schemes, args);
|
||||
atom::api::RegisterSchemesAsPrivileged(val, args);
|
||||
}
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
|
@ -246,7 +310,7 @@ void Initialize(v8::Local<v8::Object> exports,
|
|||
void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.SetMethod("registerStandardSchemes", &RegisterStandardSchemes);
|
||||
dict.SetMethod("registerSchemesAsPrivileged", &RegisterSchemesAsPrivileged);
|
||||
dict.SetMethod("getStandardSchemes", &atom::api::GetStandardSchemes);
|
||||
}
|
||||
|
||||
|
|
|
@ -34,8 +34,9 @@ namespace atom {
|
|||
namespace api {
|
||||
|
||||
std::vector<std::string> GetStandardSchemes();
|
||||
void RegisterStandardSchemes(const std::vector<std::string>& schemes,
|
||||
mate::Arguments* args);
|
||||
|
||||
void RegisterSchemesAsPrivileged(v8::Local<v8::Value> val,
|
||||
mate::Arguments* args);
|
||||
|
||||
class Protocol : public mate::TrackableObject<Protocol> {
|
||||
public:
|
||||
|
@ -94,9 +95,6 @@ class Protocol : public mate::TrackableObject<Protocol> {
|
|||
DISALLOW_COPY_AND_ASSIGN(CustomProtocolHandler);
|
||||
};
|
||||
|
||||
// Register schemes that can handle service worker.
|
||||
void RegisterServiceWorkerSchemes(const std::vector<std::string>& schemes);
|
||||
|
||||
// Register the protocol with certain request job.
|
||||
template <typename RequestJob>
|
||||
void RegisterProtocol(const std::string& scheme,
|
||||
|
|
|
@ -114,9 +114,6 @@ namespace {
|
|||
// Next navigation should not restart renderer process.
|
||||
bool g_suppress_renderer_process_restart = false;
|
||||
|
||||
// Custom schemes to be registered to handle service worker.
|
||||
base::NoDestructor<std::string> g_custom_service_worker_schemes;
|
||||
|
||||
bool IsSameWebSite(content::BrowserContext* browser_context,
|
||||
const GURL& src_url,
|
||||
const GURL& dest_url) {
|
||||
|
@ -148,11 +145,6 @@ void AtomBrowserClient::SuppressRendererProcessRestartForOnce() {
|
|||
g_suppress_renderer_process_restart = true;
|
||||
}
|
||||
|
||||
void AtomBrowserClient::SetCustomServiceWorkerSchemes(
|
||||
const std::vector<std::string>& schemes) {
|
||||
*g_custom_service_worker_schemes = base::JoinString(schemes, ",");
|
||||
}
|
||||
|
||||
AtomBrowserClient* AtomBrowserClient::Get() {
|
||||
return g_browser_client;
|
||||
}
|
||||
|
@ -477,18 +469,15 @@ void AtomBrowserClient::AppendExtraCommandLineSwitches(
|
|||
return;
|
||||
|
||||
// Copy following switches to child process.
|
||||
static const char* const kCommonSwitchNames[] = {switches::kStandardSchemes,
|
||||
switches::kEnableSandbox,
|
||||
switches::kSecureSchemes};
|
||||
static const char* const kCommonSwitchNames[] = {
|
||||
switches::kStandardSchemes, switches::kEnableSandbox,
|
||||
switches::kSecureSchemes, switches::kBypassCSPSchemes,
|
||||
switches::kCORSSchemes, switches::kFetchSchemes,
|
||||
switches::kServiceWorkerSchemes};
|
||||
command_line->CopySwitchesFrom(*base::CommandLine::ForCurrentProcess(),
|
||||
kCommonSwitchNames,
|
||||
arraysize(kCommonSwitchNames));
|
||||
|
||||
// The registered service worker schemes.
|
||||
if (!g_custom_service_worker_schemes->empty())
|
||||
command_line->AppendSwitchASCII(switches::kRegisterServiceWorkerSchemes,
|
||||
*g_custom_service_worker_schemes);
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// Append --app-user-model-id.
|
||||
PWSTR current_app_id;
|
||||
|
|
|
@ -49,10 +49,6 @@ class AtomBrowserClient : public content::ContentBrowserClient,
|
|||
// Don't force renderer process to restart for once.
|
||||
static void SuppressRendererProcessRestartForOnce();
|
||||
|
||||
// Custom schemes to be registered to handle service worker.
|
||||
static void SetCustomServiceWorkerSchemes(
|
||||
const std::vector<std::string>& schemes);
|
||||
|
||||
NotificationPresenter* GetNotificationPresenter();
|
||||
|
||||
void WebNotificationAllowed(int render_process_id,
|
||||
|
|
|
@ -179,11 +179,20 @@ const char kDisableHttpCache[] = "disable-http-cache";
|
|||
const char kStandardSchemes[] = "standard-schemes";
|
||||
|
||||
// Register schemes to handle service worker.
|
||||
const char kRegisterServiceWorkerSchemes[] = "register-service-worker-schemes";
|
||||
const char kServiceWorkerSchemes[] = "service-worker-schemes";
|
||||
|
||||
// Register schemes as secure.
|
||||
const char kSecureSchemes[] = "secure-schemes";
|
||||
|
||||
// Register schemes as bypassing CSP.
|
||||
const char kBypassCSPSchemes[] = "bypasscsp-schemes";
|
||||
|
||||
// Register schemes as support fetch API.
|
||||
const char kFetchSchemes[] = "fetch-schemes";
|
||||
|
||||
// Register schemes as CORS enabled.
|
||||
const char kCORSSchemes[] = "cors-schemes";
|
||||
|
||||
// The browser process app model ID
|
||||
const char kAppUserModelId[] = "app-user-model-id";
|
||||
|
||||
|
|
|
@ -89,8 +89,11 @@ extern const char kPpapiFlashPath[];
|
|||
extern const char kPpapiFlashVersion[];
|
||||
extern const char kDisableHttpCache[];
|
||||
extern const char kStandardSchemes[];
|
||||
extern const char kRegisterServiceWorkerSchemes[];
|
||||
extern const char kServiceWorkerSchemes[];
|
||||
extern const char kSecureSchemes[];
|
||||
extern const char kBypassCSPSchemes[];
|
||||
extern const char kFetchSchemes[];
|
||||
extern const char kCORSSchemes[];
|
||||
extern const char kAppUserModelId[];
|
||||
extern const char kAppPath[];
|
||||
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
#include "third_party/blink/public/web/web_script_execution_callback.h"
|
||||
#include "third_party/blink/public/web/web_script_source.h"
|
||||
#include "third_party/blink/public/web/web_view.h"
|
||||
#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
|
||||
#include "url/url_util.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
@ -262,54 +261,6 @@ void WebFrame::SetSpellCheckProvider(mate::Arguments* args,
|
|||
new AtomWebFrameObserver(render_frame, std::move(spell_check_client));
|
||||
}
|
||||
|
||||
void WebFrame::RegisterURLSchemeAsBypassingCSP(const std::string& scheme) {
|
||||
// Register scheme to bypass pages's Content Security Policy.
|
||||
blink::SchemeRegistry::RegisterURLSchemeAsBypassingContentSecurityPolicy(
|
||||
WTF::String::FromUTF8(scheme.data(), scheme.length()));
|
||||
}
|
||||
|
||||
void WebFrame::RegisterURLSchemeAsPrivileged(const std::string& scheme,
|
||||
mate::Arguments* args) {
|
||||
// TODO(deepak1556): blink::SchemeRegistry methods should be called
|
||||
// before any renderer threads are created. Fixing this would break
|
||||
// current api. Change it with 2.0.
|
||||
|
||||
// Read optional flags
|
||||
bool secure = true;
|
||||
bool bypassCSP = true;
|
||||
bool allowServiceWorkers = true;
|
||||
bool supportFetchAPI = true;
|
||||
bool corsEnabled = true;
|
||||
if (args->Length() == 2) {
|
||||
mate::Dictionary options;
|
||||
if (args->GetNext(&options)) {
|
||||
options.Get("secure", &secure);
|
||||
options.Get("bypassCSP", &bypassCSP);
|
||||
options.Get("allowServiceWorkers", &allowServiceWorkers);
|
||||
options.Get("supportFetchAPI", &supportFetchAPI);
|
||||
options.Get("corsEnabled", &corsEnabled);
|
||||
}
|
||||
}
|
||||
// Register scheme to privileged list (https, wss, data, chrome-extension)
|
||||
WTF::String privileged_scheme(
|
||||
WTF::String::FromUTF8(scheme.data(), scheme.length()));
|
||||
if (bypassCSP) {
|
||||
blink::SchemeRegistry::RegisterURLSchemeAsBypassingContentSecurityPolicy(
|
||||
privileged_scheme);
|
||||
}
|
||||
if (allowServiceWorkers) {
|
||||
blink::SchemeRegistry::RegisterURLSchemeAsAllowingServiceWorkers(
|
||||
privileged_scheme);
|
||||
}
|
||||
if (supportFetchAPI) {
|
||||
blink::SchemeRegistry::RegisterURLSchemeAsSupportingFetchAPI(
|
||||
privileged_scheme);
|
||||
}
|
||||
if (corsEnabled) {
|
||||
url::AddCorsEnabledScheme(scheme.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void WebFrame::InsertText(const std::string& text) {
|
||||
web_frame_->FrameWidget()->GetActiveWebInputMethodController()->CommitText(
|
||||
blink::WebString::FromUTF8(text),
|
||||
|
@ -522,10 +473,6 @@ void WebFrame::BuildPrototype(v8::Isolate* isolate,
|
|||
&WebFrame::AllowGuestViewElementDefinition)
|
||||
.SetMethod("getWebFrameId", &WebFrame::GetWebFrameId)
|
||||
.SetMethod("setSpellCheckProvider", &WebFrame::SetSpellCheckProvider)
|
||||
.SetMethod("registerURLSchemeAsBypassingCSP",
|
||||
&WebFrame::RegisterURLSchemeAsBypassingCSP)
|
||||
.SetMethod("registerURLSchemeAsPrivileged",
|
||||
&WebFrame::RegisterURLSchemeAsPrivileged)
|
||||
.SetMethod("insertText", &WebFrame::InsertText)
|
||||
.SetMethod("insertCSS", &WebFrame::InsertCSS)
|
||||
.SetMethod("executeJavaScript", &WebFrame::ExecuteJavaScript)
|
||||
|
|
|
@ -57,10 +57,6 @@ class WebFrame : public mate::Wrappable<WebFrame> {
|
|||
const std::string& language,
|
||||
v8::Local<v8::Object> provider);
|
||||
|
||||
void RegisterURLSchemeAsBypassingCSP(const std::string& scheme);
|
||||
void RegisterURLSchemeAsPrivileged(const std::string& scheme,
|
||||
mate::Arguments* args);
|
||||
|
||||
// Editing.
|
||||
void InsertText(const std::string& text);
|
||||
void InsertCSS(const std::string& css);
|
||||
|
|
|
@ -163,6 +163,25 @@ void RendererClientBase::RenderThreadStarted() {
|
|||
blink::SchemeRegistry::RegisterURLSchemeAsSecure(
|
||||
WTF::String::FromUTF8(scheme.data(), scheme.length()));
|
||||
|
||||
std::vector<std::string> fetch_enabled_schemes =
|
||||
ParseSchemesCLISwitch(command_line, switches::kFetchSchemes);
|
||||
for (const std::string& scheme : fetch_enabled_schemes) {
|
||||
blink::WebSecurityPolicy::RegisterURLSchemeAsSupportingFetchAPI(
|
||||
blink::WebString::FromASCII(scheme));
|
||||
}
|
||||
|
||||
std::vector<std::string> service_worker_schemes =
|
||||
ParseSchemesCLISwitch(command_line, switches::kServiceWorkerSchemes);
|
||||
for (const std::string& scheme : service_worker_schemes)
|
||||
blink::WebSecurityPolicy::RegisterURLSchemeAsAllowingServiceWorkers(
|
||||
blink::WebString::FromASCII(scheme));
|
||||
|
||||
std::vector<std::string> csp_bypassing_schemes =
|
||||
ParseSchemesCLISwitch(command_line, switches::kBypassCSPSchemes);
|
||||
for (const std::string& scheme : csp_bypassing_schemes)
|
||||
blink::SchemeRegistry::RegisterURLSchemeAsBypassingContentSecurityPolicy(
|
||||
WTF::String::FromUTF8(scheme.data(), scheme.length()));
|
||||
|
||||
// Allow file scheme to handle service worker by default.
|
||||
// FIXME(zcbenz): Can this be moved elsewhere?
|
||||
blink::WebSecurityPolicy::RegisterURLSchemeAsAllowingServiceWorkers("file");
|
||||
|
|
|
@ -57,6 +57,11 @@ The following `webPreferences` option default values are deprecated in favor of
|
|||
|
||||
Child windows opened with the `nativeWindowOpen` option will always have Node.js integration disabled.
|
||||
|
||||
## Privileged Schemes Registration
|
||||
|
||||
Renderer process APIs `webFrame.setRegisterURLSchemeAsPrivileged` and `webFrame.registerURLSchemeAsBypassingCSP` as well as browser process API `protocol.registerStandardSchemes` have been removed.
|
||||
A new API, `protocol.registerSchemesAsPrivileged` has been added and should be used for registering custom schemes with the required privileges. Custom schemes are required to be registered before app ready.
|
||||
|
||||
# Planned Breaking API Changes (4.0)
|
||||
|
||||
The following list includes the breaking API changes planned for Electron 4.0.
|
||||
|
|
|
@ -28,12 +28,26 @@ of the `app` module gets emitted.
|
|||
|
||||
The `protocol` module has the following methods:
|
||||
|
||||
### `protocol.registerStandardSchemes(schemes[, options])`
|
||||
### `protocol.registerSchemesAsPrivileged(schemes[, options])`
|
||||
|
||||
* `schemes` String[] - Custom schemes to be registered as standard schemes.
|
||||
* `options` Object (optional)
|
||||
* `secure` Boolean (optional) - `true` to register the scheme as secure.
|
||||
Default `false`.
|
||||
* `custom_schemes` [CustomScheme[]](structures/custom-scheme.md)
|
||||
|
||||
|
||||
**Note:** This method can only be used before the `ready` event of the `app`
|
||||
module gets emitted and can be called only once.
|
||||
|
||||
Registers the `scheme` as standard, secure, bypasses content security policy for resources,
|
||||
allows registering ServiceWorker and supports fetch API.
|
||||
|
||||
Specify an option with the value of `true` to enable the capability.
|
||||
An example of registering a privileged scheme, with bypassing Content Security Policy:
|
||||
|
||||
```javascript
|
||||
const { protocol } = require('electron')
|
||||
protocol.registerSchemesAsPrivileged([
|
||||
{ scheme: 'foo', options: { bypassCSP: true } }
|
||||
])
|
||||
```
|
||||
|
||||
A standard scheme adheres to what RFC 3986 calls [generic URI
|
||||
syntax](https://tools.ietf.org/html/rfc3986#section-3). For example `http` and
|
||||
|
@ -59,23 +73,7 @@ error for the scheme.
|
|||
|
||||
By default web storage apis (localStorage, sessionStorage, webSQL, indexedDB, cookies)
|
||||
are disabled for non standard schemes. So in general if you want to register a
|
||||
custom protocol to replace the `http` protocol, you have to register it as a standard scheme:
|
||||
|
||||
```javascript
|
||||
const { app, protocol } = require('electron')
|
||||
|
||||
protocol.registerStandardSchemes(['atom'])
|
||||
app.on('ready', () => {
|
||||
protocol.registerHttpProtocol('atom', '...')
|
||||
})
|
||||
```
|
||||
|
||||
**Note:** This method can only be used before the `ready` event of the `app`
|
||||
module gets emitted.
|
||||
|
||||
### `protocol.registerServiceWorkerSchemes(schemes)`
|
||||
|
||||
* `schemes` String[] - Custom schemes to be registered to handle service workers.
|
||||
custom protocol to replace the `http` protocol, you have to register it as a standard scheme.
|
||||
|
||||
### `protocol.registerFileProtocol(scheme, handler[, completion])`
|
||||
|
||||
|
|
10
docs/api/structures/custom-scheme.md
Normal file
10
docs/api/structures/custom-scheme.md
Normal file
|
@ -0,0 +1,10 @@
|
|||
# CustomScheme Object
|
||||
|
||||
* `scheme` String - Custom schemes to be registered with options.
|
||||
* `options` Object (optional)
|
||||
* `standard` Boolean (optional) - Default false.
|
||||
* `secure` Boolean (optional) - Default false.
|
||||
* `bypassCSP` Boolean (optional) - Default false.
|
||||
* `allowServiceWorkers` Boolean (optional) - Default false.
|
||||
* `supportFetchAPI` Boolean (optional) - Default false.
|
||||
* `corsEnabled` Boolean (optional) - Default false.
|
|
@ -95,34 +95,6 @@ webFrame.setSpellCheckProvider('en-US', {
|
|||
})
|
||||
```
|
||||
|
||||
### `webFrame.registerURLSchemeAsBypassingCSP(scheme)`
|
||||
|
||||
* `scheme` String
|
||||
|
||||
Resources will be loaded from this `scheme` regardless of the current page's
|
||||
Content Security Policy.
|
||||
|
||||
### `webFrame.registerURLSchemeAsPrivileged(scheme[, options])`
|
||||
|
||||
* `scheme` String
|
||||
* `options` Object (optional)
|
||||
* `secure` Boolean (optional) - Default true.
|
||||
* `bypassCSP` Boolean (optional) - Default true.
|
||||
* `allowServiceWorkers` Boolean (optional) - Default true.
|
||||
* `supportFetchAPI` Boolean (optional) - Default true.
|
||||
* `corsEnabled` Boolean (optional) - Default true.
|
||||
|
||||
Registers the `scheme` as secure, bypasses content security policy for resources,
|
||||
allows registering ServiceWorker and supports fetch API.
|
||||
|
||||
Specify an option with the value of `false` to omit it from the registration.
|
||||
An example of registering a privileged scheme, without bypassing Content Security Policy:
|
||||
|
||||
```javascript
|
||||
const { webFrame } = require('electron')
|
||||
webFrame.registerURLSchemeAsPrivileged('foo', { bypassCSP: false })
|
||||
```
|
||||
|
||||
### `webFrame.insertText(text)`
|
||||
|
||||
* `text` String
|
||||
|
|
|
@ -1087,7 +1087,7 @@ describe('protocol module', () => {
|
|||
})
|
||||
})
|
||||
|
||||
describe('protocol.registerStandardSchemes', () => {
|
||||
describe('protocol.registerSchemesAsPrivileged standard', () => {
|
||||
const standardScheme = remote.getGlobal('standardScheme')
|
||||
const origin = `${standardScheme}://fake-host`
|
||||
const imageURL = `${origin}/test.png`
|
||||
|
@ -1189,4 +1189,102 @@ describe('protocol module', () => {
|
|||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('protocol.registerSchemesAsPrivileged cors-fetch', function () {
|
||||
const standardScheme = remote.getGlobal('standardScheme')
|
||||
const fixtures = path.resolve(__dirname, 'fixtures')
|
||||
let w = null
|
||||
|
||||
beforeEach((done) => {
|
||||
protocol.unregisterProtocol(standardScheme, () => done())
|
||||
})
|
||||
|
||||
afterEach((done) => {
|
||||
closeWindow(w).then(() => {
|
||||
w = null
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('supports fetch api by default', (done) => {
|
||||
const url = 'file://' + fixtures + '/assets/logo.png'
|
||||
window.fetch(url)
|
||||
.then(function (response) {
|
||||
assert(response.ok)
|
||||
done()
|
||||
})
|
||||
.catch(function (err) {
|
||||
done('unexpected error : ' + err)
|
||||
})
|
||||
})
|
||||
|
||||
it('allows CORS requests by default', (done) => {
|
||||
allowsCORSRequests('cors', 200, `<html>
|
||||
<script>
|
||||
const {ipcRenderer} = require('electron')
|
||||
fetch('cors://myhost').then(function (response) {
|
||||
ipcRenderer.send('response', response.status)
|
||||
}).catch(function (response) {
|
||||
ipcRenderer.send('response', 'failed')
|
||||
})
|
||||
</script>
|
||||
</html>`, done)
|
||||
})
|
||||
|
||||
it('disallows CORS, but allows fetch requests, when specified', (done) => {
|
||||
allowsCORSRequests('no-cors', 'failed', `<html>
|
||||
<script>
|
||||
const {ipcRenderer} = require('electron')
|
||||
fetch('no-cors://myhost').then(function (response) {
|
||||
ipcRenderer.send('response', response.status)
|
||||
}).catch(function (response) {
|
||||
ipcRenderer.send('response', 'failed')
|
||||
})
|
||||
</script>
|
||||
</html>`, done)
|
||||
})
|
||||
|
||||
it('allows CORS, but disallows fetch requests, when specified', (done) => {
|
||||
allowsCORSRequests('no-fetch', 'failed', `<html>
|
||||
<script>
|
||||
const {ipcRenderer} = require('electron')
|
||||
fetch('no-fetch://myhost').then(function
|
||||
(response) {
|
||||
ipcRenderer.send('response', response.status)
|
||||
}).catch(function (response) {
|
||||
ipcRenderer.send('response', 'failed')
|
||||
})
|
||||
</script>
|
||||
</html>`, done)
|
||||
})
|
||||
|
||||
function allowsCORSRequests (corsScheme, expected, content, done) {
|
||||
const url = standardScheme + '://fake-host'
|
||||
w = new BrowserWindow({
|
||||
show: false,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
|
||||
const handler = (request, callback) => {
|
||||
callback({ data: content, mimeType: 'text/html' })
|
||||
}
|
||||
protocol.registerStringProtocol(standardScheme, handler, (error) => {
|
||||
if (error) { return done(error) }
|
||||
})
|
||||
|
||||
protocol.registerStringProtocol(corsScheme,
|
||||
(request, callback) => {
|
||||
callback('')
|
||||
}, (error) => {
|
||||
if (error) { return done(error) }
|
||||
ipcMain.once('response', function (event, status) {
|
||||
assert.strictEqual(status, expected)
|
||||
protocol.unregisterProtocol(corsScheme, () => done())
|
||||
})
|
||||
w.loadURL(url)
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
|
|
|
@ -695,12 +695,9 @@ describe('session module', () => {
|
|||
})
|
||||
})
|
||||
|
||||
// FIXME: Disabled with C71 upgrade
|
||||
// Re-enable with new api from
|
||||
// https://github.com/electron/electron/tree/webframe-scheme-api
|
||||
xdescribe('ses.getBlobData(identifier, callback)', () => {
|
||||
describe('ses.getBlobData(identifier, callback)', () => {
|
||||
it('returns blob data for uuid', (done) => {
|
||||
const scheme = 'temp'
|
||||
const scheme = 'cors-blob'
|
||||
const protocol = session.defaultSession.protocol
|
||||
const url = `${scheme}://host`
|
||||
before(() => {
|
||||
|
@ -723,8 +720,6 @@ describe('session module', () => {
|
|||
})
|
||||
const content = `<html>
|
||||
<script>
|
||||
const {webFrame} = require('electron')
|
||||
webFrame.registerURLSchemeAsPrivileged('${scheme}')
|
||||
let fd = new FormData();
|
||||
fd.append('file', new Blob(['${postData}'], {type:'application/json'}));
|
||||
fetch('${url}', {method:'POST', body: fd });
|
||||
|
|
|
@ -4,7 +4,7 @@ const dirtyChai = require('dirty-chai')
|
|||
const path = require('path')
|
||||
const { closeWindow } = require('./window-helpers')
|
||||
const { remote, webFrame } = require('electron')
|
||||
const { BrowserWindow, protocol, ipcMain } = remote
|
||||
const { BrowserWindow, ipcMain } = remote
|
||||
|
||||
const { expect } = chai
|
||||
chai.use(dirtyChai)
|
||||
|
@ -20,124 +20,6 @@ describe('webFrame module', function () {
|
|||
return closeWindow(w).then(function () { w = null })
|
||||
})
|
||||
|
||||
// FIXME: Disabled with C70.
|
||||
xdescribe('webFrame.registerURLSchemeAsPrivileged', function () {
|
||||
it('supports fetch api by default', function (done) {
|
||||
const url = 'file://' + fixtures + '/assets/logo.png'
|
||||
window.fetch(url).then(function (response) {
|
||||
assert(response.ok)
|
||||
done()
|
||||
}).catch(function (err) {
|
||||
done('unexpected error : ' + err)
|
||||
})
|
||||
})
|
||||
|
||||
it('allows CORS requests by default', function (done) {
|
||||
allowsCORSRequests(200, `<html>
|
||||
<script>
|
||||
const {ipcRenderer, webFrame} = require('electron')
|
||||
webFrame.registerURLSchemeAsPrivileged('cors1')
|
||||
fetch('cors1://myhost').then(function (response) {
|
||||
ipcRenderer.send('response', response.status)
|
||||
}).catch(function (response) {
|
||||
ipcRenderer.send('response', 'failed')
|
||||
})
|
||||
</script>
|
||||
</html>`, done)
|
||||
})
|
||||
|
||||
it('allows CORS and fetch requests when specified', function (done) {
|
||||
allowsCORSRequests(200, `<html>
|
||||
<script>
|
||||
const {ipcRenderer, webFrame} = require('electron')
|
||||
webFrame.registerURLSchemeAsPrivileged('cors2', { supportFetchAPI: true, corsEnabled: true })
|
||||
fetch('cors2://myhost').then(function (response) {
|
||||
ipcRenderer.send('response', response.status)
|
||||
}).catch(function (response) {
|
||||
ipcRenderer.send('response', 'failed')
|
||||
})
|
||||
</script>
|
||||
</html>`, done)
|
||||
})
|
||||
|
||||
it('allows CORS and fetch requests when half-specified', function (done) {
|
||||
allowsCORSRequests(200, `<html>
|
||||
<script>
|
||||
const {ipcRenderer, webFrame} = require('electron')
|
||||
webFrame.registerURLSchemeAsPrivileged('cors3', { supportFetchAPI: true })
|
||||
fetch('cors3://myhost').then(function (response) {
|
||||
ipcRenderer.send('response', response.status)
|
||||
}).catch(function (response) {
|
||||
ipcRenderer.send('response', 'failed')
|
||||
})
|
||||
</script>
|
||||
</html>`, done)
|
||||
})
|
||||
|
||||
it('disallows CORS, but allows fetch requests, when specified', function (done) {
|
||||
allowsCORSRequests('failed', `<html>
|
||||
<script>
|
||||
const {ipcRenderer, webFrame} = require('electron')
|
||||
webFrame.registerURLSchemeAsPrivileged('cors4', { supportFetchAPI: true, corsEnabled: false })
|
||||
fetch('cors4://myhost').then(function (response) {
|
||||
ipcRenderer.send('response', response.status)
|
||||
}).catch(function (response) {
|
||||
ipcRenderer.send('response', 'failed')
|
||||
})
|
||||
</script>
|
||||
</html>`, done)
|
||||
})
|
||||
|
||||
it('allows CORS, but disallows fetch requests, when specified', function (done) {
|
||||
allowsCORSRequests('failed', `<html>
|
||||
<script>
|
||||
const {ipcRenderer, webFrame} = require('electron')
|
||||
webFrame.registerURLSchemeAsPrivileged('cors5', { supportFetchAPI: false, corsEnabled: true })
|
||||
fetch('cors5://myhost').then(function (response) {
|
||||
ipcRenderer.send('response', response.status)
|
||||
}).catch(function (response) {
|
||||
ipcRenderer.send('response', 'failed')
|
||||
})
|
||||
</script>
|
||||
</html>`, done)
|
||||
})
|
||||
|
||||
let runNumber = 1
|
||||
function allowsCORSRequests (expected, content, done) {
|
||||
const standardScheme = remote.getGlobal('standardScheme') + runNumber
|
||||
const corsScheme = 'cors' + runNumber
|
||||
runNumber++
|
||||
|
||||
const url = standardScheme + '://fake-host'
|
||||
w = new BrowserWindow({ show: false })
|
||||
after(function (done) {
|
||||
protocol.unregisterProtocol(corsScheme, function () {
|
||||
protocol.unregisterProtocol(standardScheme, function () {
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
const handler = function (request, callback) {
|
||||
callback({ data: content, mimeType: 'text/html' })
|
||||
}
|
||||
protocol.registerStringProtocol(standardScheme, handler, function (error) {
|
||||
if (error) return done(error)
|
||||
})
|
||||
|
||||
protocol.registerStringProtocol(corsScheme, function (request, callback) {
|
||||
callback('')
|
||||
}, function (error) {
|
||||
if (error) return done(error)
|
||||
ipcMain.once('response', function (event, status) {
|
||||
assert.strictEqual(status, expected)
|
||||
done()
|
||||
})
|
||||
w.loadURL(url)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
it('supports setting the visual and layout zoom level limits', function () {
|
||||
assert.doesNotThrow(function () {
|
||||
webFrame.setVisualZoomLevelLimits(1, 50)
|
||||
|
|
32
spec/package-lock.json
generated
32
spec/package-lock.json
generated
|
@ -72,7 +72,7 @@
|
|||
},
|
||||
"bl": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz",
|
||||
"resolved": "http://registry.npmjs.org/bl/-/bl-1.2.2.tgz",
|
||||
"integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
|
@ -228,7 +228,7 @@
|
|||
},
|
||||
"commander": {
|
||||
"version": "2.15.1",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
|
||||
"resolved": "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
|
||||
"integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==",
|
||||
"dev": true
|
||||
},
|
||||
|
@ -267,7 +267,7 @@
|
|||
},
|
||||
"dbus-native": {
|
||||
"version": "0.2.5",
|
||||
"resolved": "https://registry.npmjs.org/dbus-native/-/dbus-native-0.2.5.tgz",
|
||||
"resolved": "http://registry.npmjs.org/dbus-native/-/dbus-native-0.2.5.tgz",
|
||||
"integrity": "sha512-ocxMKCV7QdiNhzhFSeEMhj258OGtvpANSb3oWGiotmI5h1ZIse0TMPcSLiXSpqvbYvQz2Y5RsYPMNYLWhg9eBw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
|
@ -358,7 +358,7 @@
|
|||
},
|
||||
"duplexer": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
|
||||
"resolved": "http://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
|
||||
"integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=",
|
||||
"dev": true
|
||||
},
|
||||
|
@ -512,7 +512,7 @@
|
|||
},
|
||||
"get-stream": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
|
||||
"resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
|
||||
"integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
|
||||
"dev": true
|
||||
},
|
||||
|
@ -753,7 +753,7 @@
|
|||
},
|
||||
"mkdirp": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
|
||||
"resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
|
||||
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
|
||||
"requires": {
|
||||
"minimist": "0.0.8"
|
||||
|
@ -761,7 +761,7 @@
|
|||
"dependencies": {
|
||||
"minimist": {
|
||||
"version": "0.0.8",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
|
||||
"resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
|
||||
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
|
||||
}
|
||||
}
|
||||
|
@ -941,7 +941,7 @@
|
|||
},
|
||||
"os-homedir": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
|
||||
"resolved": "http://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
|
||||
"integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
|
||||
"optional": true
|
||||
},
|
||||
|
@ -958,7 +958,7 @@
|
|||
},
|
||||
"os-tmpdir": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
|
||||
"resolved": "http://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
|
||||
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
|
||||
"dev": true
|
||||
},
|
||||
|
@ -1000,7 +1000,7 @@
|
|||
},
|
||||
"path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
|
||||
"dev": true
|
||||
},
|
||||
|
@ -1018,7 +1018,7 @@
|
|||
},
|
||||
"pause-stream": {
|
||||
"version": "0.0.11",
|
||||
"resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz",
|
||||
"resolved": "http://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz",
|
||||
"integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
|
@ -1139,7 +1139,7 @@
|
|||
},
|
||||
"rimraf": {
|
||||
"version": "2.2.8",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz",
|
||||
"resolved": "http://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz",
|
||||
"integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=",
|
||||
"dev": true
|
||||
},
|
||||
|
@ -1305,7 +1305,7 @@
|
|||
},
|
||||
"string_decoder": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||
"resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||
"requires": {
|
||||
"safe-buffer": "~5.1.0"
|
||||
|
@ -1321,7 +1321,7 @@
|
|||
},
|
||||
"strip-eof": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
|
||||
"resolved": "http://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
|
||||
"integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=",
|
||||
"dev": true
|
||||
},
|
||||
|
@ -1391,7 +1391,7 @@
|
|||
},
|
||||
"through": {
|
||||
"version": "2.3.8",
|
||||
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
||||
"resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
||||
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
|
||||
"dev": true
|
||||
},
|
||||
|
@ -1486,7 +1486,7 @@
|
|||
},
|
||||
"wrap-ansi": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
|
||||
"resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
|
||||
"integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
|
|
|
@ -97,7 +97,14 @@ global.nativeModulesEnabled = !process.env.ELECTRON_SKIP_NATIVE_MODULE_TESTS
|
|||
// Register app as standard scheme.
|
||||
global.standardScheme = 'app'
|
||||
global.zoomScheme = 'zoom'
|
||||
protocol.registerStandardSchemes([global.standardScheme, global.zoomScheme], { secure: true })
|
||||
protocol.registerSchemesAsPrivileged([
|
||||
{ scheme: global.standardScheme, options: { standard: true, secure: true } },
|
||||
{ scheme: global.zoomScheme, options: { standard: true, secure: true } },
|
||||
{ scheme: 'cors', options: { corsEnabled: true, supportFetchAPI: true } },
|
||||
{ scheme: 'cors-blob', options: { corsEnabled: true, supportFetchAPI: true } },
|
||||
{ scheme: 'no-cors', options: { supportFetchAPI: true } },
|
||||
{ scheme: 'no-fetch', options: { corsEnabled: true } }
|
||||
])
|
||||
|
||||
app.on('window-all-closed', function () {
|
||||
app.quit()
|
||||
|
|
Loading…
Reference in a new issue