mirror of
https://github.com/electron/electron.git
synced 2026-02-19 03:14:51 -05:00
Compare commits
64 Commits
robo/add_w
...
v4.0.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b2d4c519f8 | ||
|
|
86e35e6221 | ||
|
|
17b80ebb9c | ||
|
|
a313aaea72 | ||
|
|
11ebf5c990 | ||
|
|
daa0be56c9 | ||
|
|
e026e9aa82 | ||
|
|
fdfcd3cf12 | ||
|
|
f8450daa14 | ||
|
|
f68d59d1a3 | ||
|
|
b8bc25665f | ||
|
|
9a5915995e | ||
|
|
4844af489a | ||
|
|
fd4d0320cd | ||
|
|
57153ead89 | ||
|
|
e113ec78ec | ||
|
|
8a90bbf7ba | ||
|
|
cd1c9c8a45 | ||
|
|
6ba390e68a | ||
|
|
b77f41420b | ||
|
|
372fa4cdd0 | ||
|
|
435ca8cff3 | ||
|
|
f30c382d41 | ||
|
|
f88a06df84 | ||
|
|
96a4fce100 | ||
|
|
85b0f254be | ||
|
|
9ac4611075 | ||
|
|
6c18908333 | ||
|
|
f2ca4c11c8 | ||
|
|
7ab6073cdb | ||
|
|
b57d12583f | ||
|
|
3cd67db581 | ||
|
|
630bc64f2f | ||
|
|
a2b4458046 | ||
|
|
fd205a1577 | ||
|
|
1ff102e54a | ||
|
|
d525083d75 | ||
|
|
f1a8483349 | ||
|
|
5fbf1f9a54 | ||
|
|
838f108821 | ||
|
|
df70487f80 | ||
|
|
0c09199f77 | ||
|
|
6281e4ef0b | ||
|
|
abbf9c3ca3 | ||
|
|
b4f4ce1b84 | ||
|
|
5f83e07748 | ||
|
|
203b41fe2e | ||
|
|
c16b34539a | ||
|
|
446275c85a | ||
|
|
1adce9413a | ||
|
|
3ee697b258 | ||
|
|
6e30d855ba | ||
|
|
948fc6f612 | ||
|
|
8c2d16f031 | ||
|
|
11486b99a4 | ||
|
|
ebb2c53c3d | ||
|
|
8094f1a3f0 | ||
|
|
b7f20f1878 | ||
|
|
e9e0219ae8 | ||
|
|
24b809f2bc | ||
|
|
cfbb22b380 | ||
|
|
f9ae1aa999 | ||
|
|
f1ec2237e7 | ||
|
|
35df516e28 |
@@ -1,3 +1,12 @@
|
||||
# The config expects the following environment variables to be set:
|
||||
# - "SLACK_WEBHOOK" Slack hook URL to send notifications.
|
||||
#
|
||||
# The publishing scripts expect access tokens to be defined as env vars,
|
||||
# but those are not covered here.
|
||||
#
|
||||
# CircleCI docs on variables:
|
||||
# https://circleci.com/docs/2.0/env-vars/
|
||||
|
||||
# Build machines configs.
|
||||
docker-image: &docker-image
|
||||
docker:
|
||||
@@ -311,20 +320,30 @@ step-mksnapshot-store: &step-mksnapshot-store
|
||||
path: src/out/Default/mksnapshot.zip
|
||||
destination: mksnapshot.zip
|
||||
|
||||
step-generate-breakpad-symbols: &step-generate-breakpad-symbols
|
||||
step-build-dump-syms: &step-build-dump-syms
|
||||
run:
|
||||
name: Generate breakpad symbols
|
||||
environment:
|
||||
# TODO(alexeykuzmin): Explicitly pass an out folder path to the scripts.
|
||||
ELECTRON_OUT_DIR: Default
|
||||
name: Build dump_syms binary
|
||||
command: |
|
||||
cd src
|
||||
|
||||
# Build needed dump_syms executable
|
||||
ninja -C out/Default third_party/breakpad:dump_syms
|
||||
|
||||
electron/script/dump-symbols.py -d "$PWD/out/Default/electron.breakpad.syms"
|
||||
electron/script/zip-symbols.py
|
||||
step-generate-breakpad-symbols: &step-generate-breakpad-symbols
|
||||
run:
|
||||
name: Generate breakpad symbols
|
||||
command: |
|
||||
cd src
|
||||
export BUILD_PATH="$PWD/out/Default"
|
||||
export DEST_PATH="$BUILD_PATH/electron.breakpad.syms"
|
||||
electron/script/dump-symbols.py -b $BUILD_PATH -d $DEST_PATH -v
|
||||
|
||||
step-zip-symbols: &step-zip-symbols
|
||||
run:
|
||||
name: Zip symbols
|
||||
command: |
|
||||
cd src
|
||||
export BUILD_PATH="$PWD/out/Default"
|
||||
electron/script/zip-symbols.py -b $BUILD_PATH
|
||||
|
||||
step-maybe-native-mksnapshot-gn-gen: &step-maybe-native-mksnapshot-gn-gen
|
||||
run:
|
||||
@@ -458,7 +477,9 @@ steps-electron-build-for-tests: &steps-electron-build-for-tests
|
||||
|
||||
# Breakpad symbols.
|
||||
# TODO(alexeykuzmin): We should do it only in nightly builds.
|
||||
- *step-build-dump-syms
|
||||
- *step-generate-breakpad-symbols
|
||||
- *step-zip-symbols
|
||||
|
||||
# Trigger tests on arm hardware if needed
|
||||
- *step-maybe-trigger-arm-test
|
||||
@@ -479,7 +500,9 @@ steps-electron-build-for-publish: &steps-electron-build-for-publish
|
||||
- *step-maybe-electron-dist-strip
|
||||
- *step-electron-dist-build
|
||||
- *step-electron-dist-store
|
||||
- *step-build-dump-syms
|
||||
- *step-generate-breakpad-symbols
|
||||
- *step-zip-symbols
|
||||
|
||||
# mksnapshot
|
||||
- *step-mksnapshot-build
|
||||
|
||||
10
BUILD.gn
10
BUILD.gn
@@ -750,6 +750,16 @@ if (is_mac) {
|
||||
"/DELAYLOAD:api-ms-win-core-winrt-l1-1-0.dll",
|
||||
"/DELAYLOAD:api-ms-win-core-winrt-string-l1-1-0.dll",
|
||||
]
|
||||
|
||||
# This is to support renaming of electron.exe. node-gyp has hard-coded
|
||||
# executable names which it will recognise as node. This module definition
|
||||
# file claims that the electron executable is in fact named "node.exe",
|
||||
# which is one of the executable names that node-gyp recognizes.
|
||||
# See https://github.com/nodejs/node-gyp/commit/52ceec3a6d15de3a8f385f43dbe5ecf5456ad07a
|
||||
ldflags += [ "/DEF:" + rebase_path("build/electron.def", root_build_dir) ]
|
||||
inputs = [
|
||||
"build/electron.def",
|
||||
]
|
||||
}
|
||||
if (is_linux) {
|
||||
ldflags = [ "-pie" ]
|
||||
|
||||
6
DEPS
6
DEPS
@@ -12,7 +12,7 @@ vars = {
|
||||
'chromium_version':
|
||||
'69.0.3497.106',
|
||||
'node_version':
|
||||
'5654c276d0497ff9a0bb0d7550b9073b2e2e7d3f',
|
||||
'4d44266b78256449dd6ae86e419e3ec07257b569',
|
||||
|
||||
'boto_version': 'f7574aa6cc2c819430c1f05e9a1a1a666ef8169b',
|
||||
'pyyaml_version': '3.12',
|
||||
@@ -24,6 +24,9 @@ vars = {
|
||||
'requests_git': 'https://github.com/kennethreitz',
|
||||
'yaml_git': 'https://github.com/yaml',
|
||||
|
||||
# To be able to build clean Chromium from sources.
|
||||
'apply_patches': True,
|
||||
|
||||
# Python interface to Amazon Web Services. Is used for releases only.
|
||||
'checkout_boto': False,
|
||||
|
||||
@@ -68,6 +71,7 @@ deps = {
|
||||
hooks = [
|
||||
{
|
||||
'name': 'patch_chromium',
|
||||
'condition': 'apply_patches',
|
||||
'pattern': 'src/electron',
|
||||
'action': [
|
||||
'python',
|
||||
|
||||
28
appveyor.yml
28
appveyor.yml
@@ -1,3 +1,28 @@
|
||||
# The config expects the following environment variables to be set:
|
||||
# - "GN_CONFIG" Build type. One of {'debug', 'testing', 'release'}.
|
||||
# - "GN_EXTRA_ARGS" Additional gn arguments for a build config,
|
||||
# e.g. 'target_cpu="x86"' to build for a 32bit platform.
|
||||
# https://gn.googlesource.com/gn/+/master/docs/reference.md#target_cpu
|
||||
# Don't forget to set up "NPM_CONFIG_ARCH" and "TARGET_ARCH" accordningly
|
||||
# if you pass a custom value for 'target_cpu'.
|
||||
# - "ELECTRON_RELEASE" Set it to '1' upload binaries on success.
|
||||
# - "NPM_CONFIG_ARCH" E.g. 'x86'. Is used to build native Node.js modules.
|
||||
# Must match 'target_cpu' passed to "GN_EXTRA_ARGS" and "TARGET_ARCH" value.
|
||||
# - "TARGET_ARCH" Choose from {'ia32', 'x64', 'arm', 'arm64', 'mips64el'}.
|
||||
# Is used in some publishing scripts, but does NOT affect the Electron binary.
|
||||
# Must match 'target_cpu' passed to "GN_EXTRA_ARGS" and "NPM_CONFIG_ARCH" value.
|
||||
# - "UPLOAD_TO_S3" Set it to '1' upload a release to the S3 bucket.
|
||||
# Otherwise the release will be uploaded to the Github Releases.
|
||||
# (The value is only checked if "ELECTRON_RELEASE" is defined.)
|
||||
#
|
||||
# The publishing scripts expect access tokens to be defined as env vars,
|
||||
# but those are not covered here.
|
||||
#
|
||||
# AppVeyor docs on variables:
|
||||
# https://www.appveyor.com/docs/environment-variables/
|
||||
# https://www.appveyor.com/docs/build-configuration/#secure-variables
|
||||
# https://www.appveyor.com/docs/build-configuration/#custom-environment-variables
|
||||
|
||||
version: 1.0.{build}
|
||||
build_cloud: libcc-20
|
||||
image: libcc-20-vs2017-15.7.4
|
||||
@@ -29,7 +54,8 @@ build_script:
|
||||
"https://github.com/electron/electron"
|
||||
- gclient sync --with_branch_heads --with_tags
|
||||
- cd src
|
||||
- gn gen out/Default "--args=import(\"//electron/build/args/%GN_CONFIG%.gn\") %GN_EXTRA_ARGS%"
|
||||
- ps: $env:BUILD_CONFIG_PATH="//electron/build/args/%GN_CONFIG%.gn"
|
||||
- gn gen out/Default "--args=import(\"%BUILD_CONFIG_PATH%\") %GN_EXTRA_ARGS%"
|
||||
- ninja -C out/Default electron:electron_app
|
||||
- gn gen out/ffmpeg "--args=import(\"//electron/build/args/ffmpeg.gn\") %GN_EXTRA_ARGS%"
|
||||
- ninja -C out/ffmpeg electron:electron_ffmpeg_zip
|
||||
|
||||
@@ -1173,7 +1173,7 @@ v8::Local<v8::Promise> App::GetGPUInfo(v8::Isolate* isolate,
|
||||
|
||||
auto* const info_mgr = GPUInfoManager::GetInstance();
|
||||
if (info_type == "complete") {
|
||||
#if defined(OS_WIN)
|
||||
#if defined(OS_WIN) || defined(OS_MACOSX)
|
||||
info_mgr->FetchCompleteInfo(promise);
|
||||
#else
|
||||
info_mgr->FetchBasicInfo(promise);
|
||||
|
||||
@@ -814,8 +814,10 @@ void WebContents::DidChangeThemeColor(SkColor theme_color) {
|
||||
|
||||
void WebContents::DocumentLoadedInFrame(
|
||||
content::RenderFrameHost* render_frame_host) {
|
||||
if (!render_frame_host->GetParent())
|
||||
if (!render_frame_host->GetParent()) {
|
||||
is_dom_ready_ = true;
|
||||
Emit("dom-ready");
|
||||
}
|
||||
}
|
||||
|
||||
void WebContents::DidFinishLoad(content::RenderFrameHost* render_frame_host,
|
||||
@@ -842,6 +844,7 @@ void WebContents::DidFailLoad(content::RenderFrameHost* render_frame_host,
|
||||
}
|
||||
|
||||
void WebContents::DidStartLoading() {
|
||||
is_dom_ready_ = false;
|
||||
Emit("did-start-loading");
|
||||
}
|
||||
|
||||
@@ -1422,6 +1425,10 @@ bool WebContents::IsCurrentlyAudible() {
|
||||
return web_contents()->IsCurrentlyAudible();
|
||||
}
|
||||
|
||||
bool WebContents::IsDOMReady() const {
|
||||
return is_dom_ready_;
|
||||
}
|
||||
|
||||
void WebContents::Print(mate::Arguments* args) {
|
||||
PrintSettings settings = {false, false, base::string16()};
|
||||
if (args->Length() >= 1 && !args->GetNext(&settings)) {
|
||||
@@ -1889,6 +1896,13 @@ v8::Local<v8::Value> WebContents::GetLastWebPreferences(
|
||||
return mate::ConvertToV8(isolate, *web_preferences->last_preference());
|
||||
}
|
||||
|
||||
bool WebContents::IsRemoteModuleEnabled() const {
|
||||
if (auto* web_preferences = WebContentsPreferences::From(web_contents())) {
|
||||
return web_preferences->IsRemoteModuleEnabled();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> WebContents::GetOwnerBrowserWindow() const {
|
||||
if (owner_window())
|
||||
return BrowserWindow::From(isolate(), owner_window());
|
||||
@@ -2019,6 +2033,7 @@ void WebContents::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("setAudioMuted", &WebContents::SetAudioMuted)
|
||||
.SetMethod("isAudioMuted", &WebContents::IsAudioMuted)
|
||||
.SetMethod("isCurrentlyAudible", &WebContents::IsCurrentlyAudible)
|
||||
.SetMethod("isDomReady", &WebContents::IsDOMReady)
|
||||
.SetMethod("undo", &WebContents::Undo)
|
||||
.SetMethod("redo", &WebContents::Redo)
|
||||
.SetMethod("cut", &WebContents::Cut)
|
||||
@@ -2059,6 +2074,7 @@ void WebContents::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("_getPreloadPath", &WebContents::GetPreloadPath)
|
||||
.SetMethod("getWebPreferences", &WebContents::GetWebPreferences)
|
||||
.SetMethod("getLastWebPreferences", &WebContents::GetLastWebPreferences)
|
||||
.SetMethod("_isRemoteModuleEnabled", &WebContents::IsRemoteModuleEnabled)
|
||||
.SetMethod("getOwnerBrowserWindow", &WebContents::GetOwnerBrowserWindow)
|
||||
.SetMethod("hasServiceWorker", &WebContents::HasServiceWorker)
|
||||
.SetMethod("unregisterServiceWorker",
|
||||
|
||||
@@ -52,7 +52,6 @@ class FrameSubscriber;
|
||||
|
||||
#if BUILDFLAG(ENABLE_OSR)
|
||||
class OffScreenWebContentsView;
|
||||
class OffScreenRenderWidgetHostView;
|
||||
#endif
|
||||
|
||||
namespace api {
|
||||
@@ -142,6 +141,7 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
void SetAudioMuted(bool muted);
|
||||
bool IsAudioMuted();
|
||||
bool IsCurrentlyAudible();
|
||||
bool IsDOMReady() const;
|
||||
void Print(mate::Arguments* args);
|
||||
std::vector<printing::PrinterBasicInfo> GetPrinterList();
|
||||
void SetEmbedder(const WebContents* embedder);
|
||||
@@ -249,6 +249,8 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
v8::Local<v8::Value> GetWebPreferences(v8::Isolate* isolate) const;
|
||||
v8::Local<v8::Value> GetLastWebPreferences(v8::Isolate* isolate) const;
|
||||
|
||||
bool IsRemoteModuleEnabled() const;
|
||||
|
||||
// Returns the owner window.
|
||||
v8::Local<v8::Value> GetOwnerBrowserWindow() const;
|
||||
|
||||
@@ -425,7 +427,8 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
|
||||
#if BUILDFLAG(ENABLE_OSR)
|
||||
OffScreenWebContentsView* GetOffScreenWebContentsView() const;
|
||||
OffScreenRenderWidgetHostView* GetOffScreenRenderWidgetHostView() const;
|
||||
OffScreenRenderWidgetHostView* GetOffScreenRenderWidgetHostView()
|
||||
const override;
|
||||
#endif
|
||||
|
||||
// Called when we receive a CursorChange message from chromium.
|
||||
@@ -491,6 +494,9 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
// Whether to enable devtools.
|
||||
bool enable_devtools_ = true;
|
||||
|
||||
// Whether page's document is ready.
|
||||
bool is_dom_ready_ = false;
|
||||
|
||||
// Observers of this WebContents.
|
||||
base::ObserverList<ExtendedWebContentsObserver> observers_;
|
||||
|
||||
|
||||
@@ -17,15 +17,23 @@ namespace atom {
|
||||
namespace api {
|
||||
|
||||
OffScreenWebContentsView* WebContents::GetOffScreenWebContentsView() const {
|
||||
const auto* impl =
|
||||
static_cast<const content::WebContentsImpl*>(web_contents());
|
||||
return static_cast<OffScreenWebContentsView*>(impl->GetView());
|
||||
if (IsOffScreen()) {
|
||||
const auto* impl =
|
||||
static_cast<const content::WebContentsImpl*>(web_contents());
|
||||
return static_cast<OffScreenWebContentsView*>(impl->GetView());
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
OffScreenRenderWidgetHostView* WebContents::GetOffScreenRenderWidgetHostView()
|
||||
const {
|
||||
return static_cast<OffScreenRenderWidgetHostView*>(
|
||||
web_contents()->GetRenderWidgetHostView());
|
||||
if (IsOffScreen()) {
|
||||
return static_cast<OffScreenRenderWidgetHostView*>(
|
||||
web_contents()->GetRenderWidgetHostView());
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
@@ -26,11 +26,12 @@ GPUInfoManager::~GPUInfoManager() {
|
||||
|
||||
// Based on
|
||||
// https://chromium.googlesource.com/chromium/src.git/+/69.0.3497.106/content/browser/gpu/gpu_data_manager_impl_private.cc#838
|
||||
bool GPUInfoManager::NeedsCompleteGpuInfoCollection() {
|
||||
#if defined(OS_WIN)
|
||||
const auto& gpu_info = gpu_data_manager_->GetGPUInfo();
|
||||
return (gpu_info.dx_diagnostics.values.empty() &&
|
||||
gpu_info.dx_diagnostics.children.empty());
|
||||
bool GPUInfoManager::NeedsCompleteGpuInfoCollection() const {
|
||||
#if defined(OS_MACOSX)
|
||||
return gpu_data_manager_->GetGPUInfo().gl_vendor.empty();
|
||||
#elif defined(OS_WIN)
|
||||
return (gpu_data_manager_->GetGPUInfo().dx_diagnostics.values.empty() &&
|
||||
gpu_data_manager_->GetGPUInfo().dx_diagnostics.children.empty());
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
|
||||
@@ -24,7 +24,7 @@ class GPUInfoManager : public content::GpuDataManagerObserver {
|
||||
|
||||
GPUInfoManager();
|
||||
~GPUInfoManager() override;
|
||||
bool NeedsCompleteGpuInfoCollection();
|
||||
bool NeedsCompleteGpuInfoCollection() const;
|
||||
void FetchCompleteInfo(scoped_refptr<util::Promise> promise);
|
||||
void FetchBasicInfo(scoped_refptr<util::Promise> promise);
|
||||
void OnGpuInfoUpdate() override;
|
||||
|
||||
@@ -253,6 +253,7 @@ void AtomBrowserMainParts::PreMainMessageLoopRun() {
|
||||
}
|
||||
|
||||
bool AtomBrowserMainParts::MainMessageLoopRun(int* result_code) {
|
||||
js_env_->OnMessageLoopCreated();
|
||||
exit_code_ = result_code;
|
||||
return brightray::BrowserMainParts::MainMessageLoopRun(result_code);
|
||||
}
|
||||
|
||||
@@ -217,14 +217,74 @@ Browser::LoginItemSettings Browser::GetLoginItemSettings(
|
||||
return settings;
|
||||
}
|
||||
|
||||
// copied from GetLoginItemForApp in base/mac/mac_util.mm
|
||||
LSSharedFileListItemRef GetLoginItemForApp() {
|
||||
base::ScopedCFTypeRef<LSSharedFileListRef> login_items(
|
||||
LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL));
|
||||
if (!login_items.get()) {
|
||||
LOG(ERROR) << "Couldn't get a Login Items list.";
|
||||
return NULL;
|
||||
}
|
||||
base::scoped_nsobject<NSArray> login_items_array(
|
||||
base::mac::CFToNSCast(LSSharedFileListCopySnapshot(login_items, NULL)));
|
||||
NSURL* url = [NSURL fileURLWithPath:[base::mac::MainBundle() bundlePath]];
|
||||
for (NSUInteger i = 0; i < [login_items_array count]; ++i) {
|
||||
LSSharedFileListItemRef item =
|
||||
reinterpret_cast<LSSharedFileListItemRef>(login_items_array[i]);
|
||||
CFURLRef item_url_ref = NULL;
|
||||
if (LSSharedFileListItemResolve(item, 0, &item_url_ref, NULL) == noErr &&
|
||||
item_url_ref) {
|
||||
base::ScopedCFTypeRef<CFURLRef> item_url(item_url_ref);
|
||||
if (CFEqual(item_url, url)) {
|
||||
CFRetain(item);
|
||||
return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void RemoveFromLoginItems() {
|
||||
base::ScopedCFTypeRef<LSSharedFileListRef> list(
|
||||
LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL));
|
||||
if (!list) {
|
||||
LOG(ERROR) << "Unable to access shared file list";
|
||||
return;
|
||||
}
|
||||
|
||||
if (GetLoginItemForApp() != NULL) {
|
||||
base::scoped_nsobject<NSArray> login_items_array(
|
||||
base::mac::CFToNSCast(LSSharedFileListCopySnapshot(list, NULL)));
|
||||
|
||||
if (!login_items_array) {
|
||||
LOG(ERROR) << "No items in list of auto-loaded apps";
|
||||
return;
|
||||
}
|
||||
|
||||
for (NSUInteger i = 0; i < [login_items_array count]; ++i) {
|
||||
LSSharedFileListItemRef item =
|
||||
reinterpret_cast<LSSharedFileListItemRef>(login_items_array[i]);
|
||||
CFURLRef url_ref = NULL;
|
||||
if (LSSharedFileListItemResolve(item, 0, &url_ref, NULL) == noErr &&
|
||||
item) {
|
||||
base::ScopedCFTypeRef<CFURLRef> url(url_ref);
|
||||
if ([[base::mac::CFToNSCast(url.get()) path]
|
||||
hasPrefix:[[NSBundle mainBundle] bundlePath]])
|
||||
LSSharedFileListItemRemove(list, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Browser::SetLoginItemSettings(LoginItemSettings settings) {
|
||||
#if defined(MAS_BUILD)
|
||||
platform_util::SetLoginItemEnabled(settings.open_at_login);
|
||||
#else
|
||||
if (settings.open_at_login)
|
||||
base::mac::AddToLoginItems(settings.open_as_hidden);
|
||||
else
|
||||
base::mac::RemoveFromLoginItems();
|
||||
else {
|
||||
RemoveFromLoginItems();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "components/prefs/scoped_user_pref_update.h"
|
||||
#include "components/security_state/content/content_utils.h"
|
||||
#include "components/security_state/core/security_state.h"
|
||||
#include "content/browser/renderer_host/render_widget_host_view_base.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "content/public/browser/child_process_security_policy.h"
|
||||
#include "content/public/browser/render_process_host.h"
|
||||
@@ -39,6 +40,10 @@
|
||||
#include "content/public/browser/security_style_explanations.h"
|
||||
#include "storage/browser/fileapi/isolated_context.h"
|
||||
|
||||
#if BUILDFLAG(ENABLE_OSR)
|
||||
#include "atom/browser/osr/osr_render_widget_host_view.h"
|
||||
#endif
|
||||
|
||||
using content::BrowserThread;
|
||||
|
||||
namespace atom {
|
||||
@@ -201,6 +206,11 @@ void CommonWebContentsDelegate::SetOwnerWindow(
|
||||
web_contents->RemoveUserData(
|
||||
NativeWindowRelay::kNativeWindowRelayUserDataKey);
|
||||
}
|
||||
#if BUILDFLAG(ENABLE_OSR)
|
||||
auto* osr_rwhv = GetOffScreenRenderWidgetHostView();
|
||||
if (osr_rwhv)
|
||||
osr_rwhv->SetNativeWindow(owner_window);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CommonWebContentsDelegate::ResetManagedWebContents(bool async) {
|
||||
@@ -236,6 +246,13 @@ content::WebContents* CommonWebContentsDelegate::GetDevToolsWebContents()
|
||||
return web_contents_->GetDevToolsWebContents();
|
||||
}
|
||||
|
||||
#if BUILDFLAG(ENABLE_OSR)
|
||||
OffScreenRenderWidgetHostView*
|
||||
CommonWebContentsDelegate::GetOffScreenRenderWidgetHostView() const {
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
content::WebContents* CommonWebContentsDelegate::OpenURLFromTab(
|
||||
content::WebContents* source,
|
||||
const content::OpenURLParams& params) {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "brightray/browser/inspectable_web_contents_view_delegate.h"
|
||||
#include "chrome/browser/devtools/devtools_file_system_indexer.h"
|
||||
#include "content/public/browser/web_contents_delegate.h"
|
||||
#include "electron/buildflags/buildflags.h"
|
||||
|
||||
#if defined(TOOLKIT_VIEWS) && !defined(OS_MACOSX)
|
||||
#include "atom/browser/ui/autofill_popup.h"
|
||||
@@ -31,6 +32,10 @@ class AtomBrowserContext;
|
||||
class NativeWindow;
|
||||
class WebDialogHelper;
|
||||
|
||||
#if BUILDFLAG(ENABLE_OSR)
|
||||
class OffScreenRenderWidgetHostView;
|
||||
#endif
|
||||
|
||||
class CommonWebContentsDelegate
|
||||
: public content::WebContentsDelegate,
|
||||
public brightray::InspectableWebContentsDelegate,
|
||||
@@ -65,6 +70,11 @@ class CommonWebContentsDelegate
|
||||
bool is_html_fullscreen() const { return html_fullscreen_; }
|
||||
|
||||
protected:
|
||||
#if BUILDFLAG(ENABLE_OSR)
|
||||
virtual OffScreenRenderWidgetHostView* GetOffScreenRenderWidgetHostView()
|
||||
const;
|
||||
#endif
|
||||
|
||||
// content::WebContentsDelegate:
|
||||
content::WebContents* OpenURLFromTab(
|
||||
content::WebContents* source,
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "atom/browser/microtasks_runner.h"
|
||||
#include "base/command_line.h"
|
||||
#include "base/message_loop/message_loop.h"
|
||||
#include "base/task_scheduler/initialization_util.h"
|
||||
@@ -62,7 +63,15 @@ v8::Isolate* JavascriptEnvironment::Initialize(uv_loop_t* event_loop) {
|
||||
return isolate;
|
||||
}
|
||||
|
||||
void JavascriptEnvironment::OnMessageLoopCreated() {
|
||||
DCHECK(!microtasks_runner_);
|
||||
microtasks_runner_.reset(new MicrotasksRunner(isolate()));
|
||||
base::MessageLoopCurrent::Get()->AddTaskObserver(microtasks_runner_.get());
|
||||
}
|
||||
|
||||
void JavascriptEnvironment::OnMessageLoopDestroying() {
|
||||
DCHECK(microtasks_runner_);
|
||||
base::MessageLoopCurrent::Get()->RemoveTaskObserver(microtasks_runner_.get());
|
||||
platform_->UnregisterIsolate(isolate_);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#ifndef ATOM_BROWSER_JAVASCRIPT_ENVIRONMENT_H_
|
||||
#define ATOM_BROWSER_JAVASCRIPT_ENVIRONMENT_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "base/macros.h"
|
||||
#include "gin/public/isolate_holder.h"
|
||||
#include "uv.h" // NOLINT(build/include)
|
||||
@@ -16,12 +18,14 @@ class MultiIsolatePlatform;
|
||||
|
||||
namespace atom {
|
||||
|
||||
class MicrotasksRunner;
|
||||
// Manage the V8 isolate and context automatically.
|
||||
class JavascriptEnvironment {
|
||||
public:
|
||||
explicit JavascriptEnvironment(uv_loop_t* event_loop);
|
||||
~JavascriptEnvironment();
|
||||
|
||||
void OnMessageLoopCreated();
|
||||
void OnMessageLoopDestroying();
|
||||
|
||||
node::MultiIsolatePlatform* platform() const { return platform_; }
|
||||
@@ -43,6 +47,8 @@ class JavascriptEnvironment {
|
||||
v8::Global<v8::Context> context_;
|
||||
v8::Context::Scope context_scope_;
|
||||
|
||||
std::unique_ptr<MicrotasksRunner> microtasks_runner_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(JavascriptEnvironment);
|
||||
};
|
||||
|
||||
|
||||
20
atom/browser/microtasks_runner.cc
Normal file
20
atom/browser/microtasks_runner.cc
Normal file
@@ -0,0 +1,20 @@
|
||||
|
||||
// Copyright (c) 2018 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/microtasks_runner.h"
|
||||
#include "v8/include/v8.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
MicrotasksRunner::MicrotasksRunner(v8::Isolate* isolate) : isolate_(isolate) {}
|
||||
|
||||
void MicrotasksRunner::WillProcessTask(const base::PendingTask& pending_task) {}
|
||||
|
||||
void MicrotasksRunner::DidProcessTask(const base::PendingTask& pending_task) {
|
||||
v8::Isolate::Scope scope(isolate_);
|
||||
v8::MicrotasksScope::PerformCheckpoint(isolate_);
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
36
atom/browser/microtasks_runner.h
Normal file
36
atom/browser/microtasks_runner.h
Normal file
@@ -0,0 +1,36 @@
|
||||
// Copyright (c) 2018 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_MICROTASKS_RUNNER_H_
|
||||
#define ATOM_BROWSER_MICROTASKS_RUNNER_H_
|
||||
|
||||
#include "base/message_loop/message_loop.h"
|
||||
|
||||
namespace v8 {
|
||||
class Isolate;
|
||||
}
|
||||
|
||||
namespace atom {
|
||||
|
||||
// Microtasks like promise resolution, are run at the end of the current
|
||||
// task. This class implements a task observer that runs tells v8 to run them.
|
||||
// Microtasks runner implementation is based on the EndOfTaskRunner in blink.
|
||||
// Node follows the kExplicit MicrotasksPolicy, and we do the same in browser
|
||||
// process. Hence, we need to have this task observer to flush the queued
|
||||
// microtasks.
|
||||
class MicrotasksRunner : public base::MessageLoop::TaskObserver {
|
||||
public:
|
||||
explicit MicrotasksRunner(v8::Isolate* isolate);
|
||||
|
||||
// base::MessageLoop::TaskObserver
|
||||
void WillProcessTask(const base::PendingTask& pending_task) override;
|
||||
void DidProcessTask(const base::PendingTask& pending_task) override;
|
||||
|
||||
private:
|
||||
v8::Isolate* isolate_;
|
||||
};
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_MICROTASKS_RUNNER_H_
|
||||
@@ -585,13 +585,13 @@ bool NativeWindowMac::IsEnabled() {
|
||||
|
||||
void NativeWindowMac::SetEnabled(bool enable) {
|
||||
if (enable) {
|
||||
[window_ endSheet:[window_ attachedSheet]];
|
||||
} else {
|
||||
[window_ beginSheet:window_
|
||||
completionHandler:^(NSModalResponse returnCode) {
|
||||
NSLog(@"modal enabled");
|
||||
return;
|
||||
}];
|
||||
} else {
|
||||
[window_ endSheet:[window_ attachedSheet]];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -344,7 +344,7 @@ bool NativeWindowViews::IsFocused() {
|
||||
void NativeWindowViews::Show() {
|
||||
if (is_modal() && NativeWindow::parent() &&
|
||||
!widget()->native_widget_private()->IsVisible())
|
||||
NativeWindow::parent()->SetEnabled(false);
|
||||
static_cast<NativeWindowViews*>(parent())->IncrementChildModals();
|
||||
|
||||
widget()->native_widget_private()->ShowWithWindowState(GetRestoredState());
|
||||
|
||||
@@ -369,7 +369,7 @@ void NativeWindowViews::ShowInactive() {
|
||||
|
||||
void NativeWindowViews::Hide() {
|
||||
if (is_modal() && NativeWindow::parent())
|
||||
NativeWindow::parent()->SetEnabled(true);
|
||||
static_cast<NativeWindowViews*>(parent())->DecrementChildModals();
|
||||
|
||||
widget()->Hide();
|
||||
|
||||
@@ -393,16 +393,34 @@ bool NativeWindowViews::IsEnabled() {
|
||||
#endif
|
||||
}
|
||||
|
||||
void NativeWindowViews::IncrementChildModals() {
|
||||
num_modal_children_++;
|
||||
SetEnabledInternal(ShouldBeEnabled());
|
||||
}
|
||||
|
||||
void NativeWindowViews::DecrementChildModals() {
|
||||
if (num_modal_children_ > 0) {
|
||||
num_modal_children_--;
|
||||
}
|
||||
SetEnabledInternal(ShouldBeEnabled());
|
||||
}
|
||||
|
||||
void NativeWindowViews::SetEnabled(bool enable) {
|
||||
// Handle multiple calls of SetEnabled correctly.
|
||||
if (enable) {
|
||||
--disable_count_;
|
||||
if (disable_count_ != 0)
|
||||
return;
|
||||
} else {
|
||||
++disable_count_;
|
||||
if (disable_count_ != 1)
|
||||
return;
|
||||
if (enable != is_enabled_) {
|
||||
is_enabled_ = enable;
|
||||
SetEnabledInternal(ShouldBeEnabled());
|
||||
}
|
||||
}
|
||||
|
||||
bool NativeWindowViews::ShouldBeEnabled() {
|
||||
return is_enabled_ && (num_modal_children_ == 0);
|
||||
}
|
||||
|
||||
void NativeWindowViews::SetEnabledInternal(bool enable) {
|
||||
if (enable && IsEnabled()) {
|
||||
return;
|
||||
} else if (!enable && !IsEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(OS_WIN)
|
||||
@@ -1161,10 +1179,10 @@ void NativeWindowViews::OnWidgetBoundsChanged(views::Widget* changed_widget,
|
||||
}
|
||||
|
||||
void NativeWindowViews::DeleteDelegate() {
|
||||
if (is_modal() && NativeWindow::parent()) {
|
||||
auto* parent = NativeWindow::parent();
|
||||
if (is_modal() && this->parent()) {
|
||||
auto* parent = this->parent();
|
||||
// Enable parent window after current window gets closed.
|
||||
parent->SetEnabled(true);
|
||||
static_cast<NativeWindowViews*>(parent)->DecrementChildModals();
|
||||
// Focus on parent window.
|
||||
parent->Focus(true);
|
||||
}
|
||||
|
||||
@@ -134,6 +134,9 @@ class NativeWindowViews : public NativeWindow,
|
||||
|
||||
void UpdateDraggableRegions(std::unique_ptr<SkRegion> region);
|
||||
|
||||
void IncrementChildModals();
|
||||
void DecrementChildModals();
|
||||
|
||||
#if defined(OS_WIN)
|
||||
void SetIcon(HICON small_icon, HICON app_icon);
|
||||
#elif defined(USE_X11)
|
||||
@@ -190,6 +193,10 @@ class NativeWindowViews : public NativeWindow,
|
||||
LPARAM l_param);
|
||||
#endif
|
||||
|
||||
// Enable/disable:
|
||||
bool ShouldBeEnabled();
|
||||
void SetEnabledInternal(bool enabled);
|
||||
|
||||
// NativeWindow:
|
||||
void HandleKeyboardEvent(
|
||||
content::WebContents*,
|
||||
@@ -273,8 +280,11 @@ class NativeWindowViews : public NativeWindow,
|
||||
// has to been explicitly provided.
|
||||
std::unique_ptr<SkRegion> draggable_region_; // used in custom drag.
|
||||
|
||||
// How many times the Disable has been called.
|
||||
int disable_count_ = 0;
|
||||
// Whether the window should be enabled based on user calls to SetEnabled()
|
||||
bool is_enabled_ = true;
|
||||
// How many modal children this window has;
|
||||
// used to determine enabled state
|
||||
unsigned int num_modal_children_ = 0;
|
||||
|
||||
bool use_content_size_ = false;
|
||||
bool movable_ = true;
|
||||
|
||||
@@ -153,13 +153,17 @@ void URLRequestStreamJob::OnData(std::vector<char>&& buffer) { // NOLINT
|
||||
if (pending_buf_) {
|
||||
int len = BufferCopy(&write_buffer_, pending_buf_.get(), pending_buf_size_);
|
||||
write_buffer_.erase(write_buffer_.begin(), write_buffer_.begin() + len);
|
||||
pending_buf_ = nullptr;
|
||||
pending_buf_size_ = 0;
|
||||
ReadRawDataComplete(len);
|
||||
}
|
||||
}
|
||||
|
||||
void URLRequestStreamJob::OnEnd() {
|
||||
ended_ = true;
|
||||
ReadRawDataComplete(0);
|
||||
if (pending_buf_) {
|
||||
ReadRawDataComplete(0);
|
||||
}
|
||||
}
|
||||
|
||||
void URLRequestStreamJob::OnError(int error) {
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "components/viz/common/frame_sinks/delay_based_time_source.h"
|
||||
#include "components/viz/common/gl_helper.h"
|
||||
#include "components/viz/common/quads/render_pass.h"
|
||||
#include "content/browser/renderer_host/cursor_manager.h"
|
||||
#include "content/browser/renderer_host/render_widget_host_delegate.h"
|
||||
#include "content/browser/renderer_host/render_widget_host_impl.h"
|
||||
#include "content/common/view_messages.h"
|
||||
@@ -264,9 +265,10 @@ OffScreenRenderWidgetHostView::OffScreenRenderWidgetHostView(
|
||||
callback_(callback),
|
||||
frame_rate_(frame_rate),
|
||||
scale_factor_(kDefaultScaleFactor),
|
||||
size_(native_window->GetSize()),
|
||||
size_(native_window ? native_window->GetSize() : gfx::Size()),
|
||||
painting_(painting),
|
||||
is_showing_(!render_widget_host_->is_hidden()),
|
||||
cursor_manager_(new content::CursorManager(this)),
|
||||
mouse_wheel_phase_handler_(this),
|
||||
weak_ptr_factory_(this) {
|
||||
DCHECK(render_widget_host_);
|
||||
@@ -280,6 +282,8 @@ OffScreenRenderWidgetHostView::OffScreenRenderWidgetHostView(
|
||||
root_layer_.reset(new ui::Layer(ui::LAYER_SOLID_COLOR));
|
||||
#endif
|
||||
|
||||
current_device_scale_factor_ = 1;
|
||||
|
||||
local_surface_id_ = local_surface_id_allocator_.GenerateId();
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
@@ -308,7 +312,8 @@ OffScreenRenderWidgetHostView::OffScreenRenderWidgetHostView(
|
||||
#endif
|
||||
GetCompositor()->SetDelegate(this);
|
||||
|
||||
native_window_->AddObserver(this);
|
||||
if (native_window_)
|
||||
native_window_->AddObserver(this);
|
||||
|
||||
ResizeRootLayer(false);
|
||||
render_widget_host_->SetView(this);
|
||||
@@ -351,13 +356,15 @@ OffScreenRenderWidgetHostView::CreateBrowserAccessibilityManager(
|
||||
|
||||
void OffScreenRenderWidgetHostView::OnWindowResize() {
|
||||
// In offscreen mode call RenderWidgetHostView's SetSize explicitly
|
||||
auto size = native_window_->GetSize();
|
||||
auto size = native_window_ ? native_window_->GetSize() : gfx::Size();
|
||||
SetSize(size);
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::OnWindowClosed() {
|
||||
native_window_->RemoveObserver(this);
|
||||
native_window_ = nullptr;
|
||||
if (native_window_) {
|
||||
native_window_->RemoveObserver(this);
|
||||
native_window_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::OnBeginFrameTimerTick() {
|
||||
@@ -445,12 +452,12 @@ void OffScreenRenderWidgetHostView::Show() {
|
||||
browser_compositor_->SetRenderWidgetHostIsHidden(false);
|
||||
#else
|
||||
delegated_frame_host_->SetCompositor(compositor_.get());
|
||||
delegated_frame_host_->WasShown(
|
||||
GetLocalSurfaceId(), GetRootLayer()->bounds().size(), ui::LatencyInfo());
|
||||
delegated_frame_host_->WasShown(GetLocalSurfaceId(),
|
||||
GetRootLayer()->bounds().size(), false);
|
||||
#endif
|
||||
|
||||
if (render_widget_host_)
|
||||
render_widget_host_->WasShown(ui::LatencyInfo());
|
||||
render_widget_host_->WasShown(false);
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::Hide() {
|
||||
@@ -628,6 +635,10 @@ void OffScreenRenderWidgetHostView::InitAsFullscreen(
|
||||
|
||||
void OffScreenRenderWidgetHostView::UpdateCursor(const content::WebCursor&) {}
|
||||
|
||||
content::CursorManager* OffScreenRenderWidgetHostView::GetCursorManager() {
|
||||
return cursor_manager_.get();
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::SetIsLoading(bool loading) {}
|
||||
|
||||
void OffScreenRenderWidgetHostView::TextInputStateChanged(
|
||||
@@ -727,10 +738,6 @@ gfx::Size OffScreenRenderWidgetHostView::GetCompositorViewportPixelSize()
|
||||
return gfx::ScaleToCeiledSize(GetRequestedRendererSize(), scale_factor_);
|
||||
}
|
||||
|
||||
gfx::Size OffScreenRenderWidgetHostView::GetRequestedRendererSize() const {
|
||||
return GetDelegatedFrameHost()->GetRequestedRendererSize();
|
||||
}
|
||||
|
||||
content::RenderWidgetHostViewBase*
|
||||
OffScreenRenderWidgetHostView::CreateViewForWidget(
|
||||
content::RenderWidgetHost* render_widget_host,
|
||||
@@ -783,13 +790,14 @@ void OffScreenRenderWidgetHostView::DidReceiveFirstFrameAfterNavigation() {
|
||||
render_widget_host_->DidReceiveFirstFrameAfterNavigation();
|
||||
}
|
||||
|
||||
viz::LocalSurfaceId OffScreenRenderWidgetHostView::GetLocalSurfaceId() const {
|
||||
const viz::LocalSurfaceId& OffScreenRenderWidgetHostView::GetLocalSurfaceId()
|
||||
const {
|
||||
return local_surface_id_;
|
||||
}
|
||||
|
||||
#endif // !defined(OS_MACOSX)
|
||||
|
||||
viz::FrameSinkId OffScreenRenderWidgetHostView::GetFrameSinkId() {
|
||||
const viz::FrameSinkId& OffScreenRenderWidgetHostView::GetFrameSinkId() const {
|
||||
return GetDelegatedFrameHost()->frame_sink_id();
|
||||
}
|
||||
|
||||
@@ -1029,7 +1037,7 @@ void OffScreenRenderWidgetHostView::SynchronizeVisualProperties() {
|
||||
ResizeRootLayer(false);
|
||||
if (render_widget_host_)
|
||||
render_widget_host_->SynchronizeVisualProperties();
|
||||
GetDelegatedFrameHost()->SynchronizeVisualProperties(
|
||||
GetDelegatedFrameHost()->EmbedSurface(
|
||||
local_surface_id_, size_, cc::DeadlinePolicy::UseDefaultDeadline());
|
||||
}
|
||||
|
||||
@@ -1240,6 +1248,18 @@ void OffScreenRenderWidgetHostView::InvalidateBounds(const gfx::Rect& bounds) {
|
||||
}
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::SetNativeWindow(NativeWindow* window) {
|
||||
if (native_window_)
|
||||
native_window_->RemoveObserver(this);
|
||||
|
||||
native_window_ = window;
|
||||
|
||||
if (native_window_)
|
||||
native_window_->AddObserver(this);
|
||||
|
||||
OnWindowResize();
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::ResizeRootLayer(bool force) {
|
||||
SetupFrameRate(false);
|
||||
|
||||
@@ -1269,7 +1289,7 @@ void OffScreenRenderWidgetHostView::ResizeRootLayer(bool force) {
|
||||
bool resized = UpdateNSViewAndDisplay();
|
||||
#else
|
||||
bool resized = true;
|
||||
GetDelegatedFrameHost()->SynchronizeVisualProperties(
|
||||
GetDelegatedFrameHost()->EmbedSurface(
|
||||
local_surface_id_, size, cc::DeadlinePolicy::UseDefaultDeadline());
|
||||
#endif
|
||||
|
||||
|
||||
@@ -57,6 +57,10 @@ class NSWindow;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace content {
|
||||
class CursorManager;
|
||||
} // namespace content
|
||||
|
||||
namespace atom {
|
||||
|
||||
class AtomCopyFrameGenerator;
|
||||
@@ -141,6 +145,7 @@ class OffScreenRenderWidgetHostView : public content::RenderWidgetHostViewBase,
|
||||
void RenderProcessGone(base::TerminationStatus, int) override;
|
||||
void Destroy(void) override;
|
||||
void SetTooltipText(const base::string16&) override;
|
||||
content::CursorManager* GetCursorManager() override;
|
||||
void SelectionBoundsChanged(
|
||||
const ViewHostMsg_SelectionBounds_Params&) override;
|
||||
void CopyFromSurface(
|
||||
@@ -156,7 +161,11 @@ class OffScreenRenderWidgetHostView : public content::RenderWidgetHostViewBase,
|
||||
void ImeCompositionRangeChanged(const gfx::Range&,
|
||||
const std::vector<gfx::Rect>&) override;
|
||||
gfx::Size GetCompositorViewportPixelSize() const override;
|
||||
gfx::Size GetRequestedRendererSize() const override;
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
viz::ScopedSurfaceIdAllocator DidUpdateVisualProperties(
|
||||
const cc::RenderFrameMetadata& metadata) override;
|
||||
#endif
|
||||
|
||||
content::RenderWidgetHostViewBase* CreateViewForWidget(
|
||||
content::RenderWidgetHost*,
|
||||
@@ -175,8 +184,8 @@ class OffScreenRenderWidgetHostView : public content::RenderWidgetHostViewBase,
|
||||
void DidReceiveFirstFrameAfterNavigation() override;
|
||||
#endif // !defined(OS_MACOSX)
|
||||
|
||||
viz::LocalSurfaceId GetLocalSurfaceId() const override;
|
||||
viz::FrameSinkId GetFrameSinkId() override;
|
||||
const viz::LocalSurfaceId& GetLocalSurfaceId() const override;
|
||||
const viz::FrameSinkId& GetFrameSinkId() const override;
|
||||
|
||||
void DidNavigate() override;
|
||||
|
||||
@@ -259,6 +268,7 @@ class OffScreenRenderWidgetHostView : public content::RenderWidgetHostViewBase,
|
||||
content::RenderWidgetHostImpl* render_widget_host() const {
|
||||
return render_widget_host_;
|
||||
}
|
||||
void SetNativeWindow(NativeWindow* window);
|
||||
NativeWindow* window() const { return native_window_; }
|
||||
gfx::Size size() const { return size_; }
|
||||
float scale_factor() const { return scale_factor_; }
|
||||
@@ -272,6 +282,12 @@ class OffScreenRenderWidgetHostView : public content::RenderWidgetHostViewBase,
|
||||
}
|
||||
|
||||
private:
|
||||
#if defined(OS_MACOSX)
|
||||
display::Display GetDisplay();
|
||||
void OnDidUpdateVisualPropertiesComplete(
|
||||
const cc::RenderFrameMetadata& metadata);
|
||||
#endif
|
||||
|
||||
void SetupFrameRate(bool force);
|
||||
void ResizeRootLayer(bool force);
|
||||
|
||||
@@ -324,6 +340,8 @@ class OffScreenRenderWidgetHostView : public content::RenderWidgetHostViewBase,
|
||||
std::unique_ptr<ui::Compositor> compositor_;
|
||||
std::unique_ptr<content::DelegatedFrameHost> delegated_frame_host_;
|
||||
|
||||
std::unique_ptr<content::CursorManager> cursor_manager_;
|
||||
|
||||
std::unique_ptr<AtomCopyFrameGenerator> copy_frame_generator_;
|
||||
std::unique_ptr<AtomBeginFrameTimer> begin_frame_timer_;
|
||||
|
||||
|
||||
@@ -11,21 +11,13 @@
|
||||
#include "ui/accelerated_widget_mac/accelerated_widget_mac.h"
|
||||
#include "ui/display/screen.h"
|
||||
|
||||
namespace {
|
||||
|
||||
display::Display GetDisplay() {
|
||||
return display::Screen::GetScreen()->GetDisplayNearestView(nullptr);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace atom {
|
||||
|
||||
class MacHelper : public content::BrowserCompositorMacClient,
|
||||
public ui::AcceleratedWidgetMacNSView {
|
||||
public:
|
||||
explicit MacHelper(OffScreenRenderWidgetHostView* view) : view_(view) {
|
||||
[this->AcceleratedWidgetGetNSView() setWantsLayer:YES];
|
||||
[view_->GetNativeView() setWantsLayer:YES];
|
||||
}
|
||||
|
||||
virtual ~MacHelper() {}
|
||||
@@ -48,11 +40,6 @@ class MacHelper : public content::BrowserCompositorMacClient,
|
||||
view_->render_widget_host()->DidProcessFrame(frame_token);
|
||||
}
|
||||
|
||||
// ui::AcceleratedWidgetMacNSView:
|
||||
NSView* AcceleratedWidgetGetNSView() const override {
|
||||
return [view_->window()->GetNativeWindow() contentView];
|
||||
}
|
||||
|
||||
void AcceleratedWidgetCALayerParamsUpdated() override {}
|
||||
|
||||
void DidReceiveFirstFrameAfterNavigation() override {
|
||||
@@ -61,7 +48,22 @@ class MacHelper : public content::BrowserCompositorMacClient,
|
||||
|
||||
void DestroyCompositorForShutdown() override {}
|
||||
|
||||
bool SynchronizeVisualProperties() override {
|
||||
bool SynchronizeVisualProperties(
|
||||
const base::Optional<viz::LocalSurfaceId>&
|
||||
child_allocated_local_surface_id) override {
|
||||
auto* browser_compositor = view_->browser_compositor();
|
||||
if (child_allocated_local_surface_id) {
|
||||
browser_compositor->UpdateRendererLocalSurfaceIdFromChild(
|
||||
*child_allocated_local_surface_id);
|
||||
} else {
|
||||
browser_compositor->AllocateNewRendererLocalSurfaceId();
|
||||
}
|
||||
|
||||
if (auto* host = browser_compositor->GetDelegatedFrameHost()) {
|
||||
host->EmbedSurface(browser_compositor->GetRendererLocalSurfaceId(),
|
||||
browser_compositor->GetRendererSize(),
|
||||
cc::DeadlinePolicy::UseDefaultDeadline());
|
||||
}
|
||||
return view_->render_widget_host()->SynchronizeVisualProperties();
|
||||
}
|
||||
|
||||
@@ -90,8 +92,8 @@ void OffScreenRenderWidgetHostView::CreatePlatformWidget(
|
||||
bool is_guest_view_hack) {
|
||||
mac_helper_ = new MacHelper(this);
|
||||
browser_compositor_.reset(new content::BrowserCompositorMac(
|
||||
mac_helper_, mac_helper_, render_widget_host_->is_hidden(), true,
|
||||
GetDisplay(), AllocateFrameSinkId(is_guest_view_hack)));
|
||||
mac_helper_, mac_helper_, render_widget_host_->is_hidden(), GetDisplay(),
|
||||
AllocateFrameSinkId(is_guest_view_hack)));
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::DestroyPlatformWidget() {
|
||||
@@ -99,7 +101,48 @@ void OffScreenRenderWidgetHostView::DestroyPlatformWidget() {
|
||||
delete mac_helper_;
|
||||
}
|
||||
|
||||
viz::LocalSurfaceId OffScreenRenderWidgetHostView::GetLocalSurfaceId() const {
|
||||
viz::ScopedSurfaceIdAllocator
|
||||
OffScreenRenderWidgetHostView::DidUpdateVisualProperties(
|
||||
const cc::RenderFrameMetadata& metadata) {
|
||||
base::OnceCallback<void()> allocation_task = base::BindOnce(
|
||||
base::IgnoreResult(
|
||||
&OffScreenRenderWidgetHostView::OnDidUpdateVisualPropertiesComplete),
|
||||
weak_ptr_factory_.GetWeakPtr(), metadata);
|
||||
return browser_compositor_->GetScopedRendererSurfaceIdAllocator(
|
||||
std::move(allocation_task));
|
||||
}
|
||||
|
||||
display::Display OffScreenRenderWidgetHostView::GetDisplay() {
|
||||
content::ScreenInfo screen_info;
|
||||
GetScreenInfo(&screen_info);
|
||||
|
||||
// Start with a reasonable display representation.
|
||||
display::Display display =
|
||||
display::Screen::GetScreen()->GetDisplayNearestView(nullptr);
|
||||
|
||||
// Populate attributes based on |screen_info|.
|
||||
display.set_bounds(screen_info.rect);
|
||||
display.set_work_area(screen_info.available_rect);
|
||||
display.set_device_scale_factor(screen_info.device_scale_factor);
|
||||
display.set_color_space(screen_info.color_space);
|
||||
display.set_color_depth(screen_info.depth);
|
||||
display.set_depth_per_component(screen_info.depth_per_component);
|
||||
display.set_is_monochrome(screen_info.is_monochrome);
|
||||
display.SetRotationAsDegree(screen_info.orientation_angle);
|
||||
|
||||
return display;
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::OnDidUpdateVisualPropertiesComplete(
|
||||
const cc::RenderFrameMetadata& metadata) {
|
||||
DCHECK_EQ(current_device_scale_factor_, metadata.device_scale_factor);
|
||||
browser_compositor_->SynchronizeVisualProperties(
|
||||
metadata.device_scale_factor, metadata.viewport_size_in_pixels,
|
||||
metadata.local_surface_id.value_or(viz::LocalSurfaceId()));
|
||||
}
|
||||
|
||||
const viz::LocalSurfaceId& OffScreenRenderWidgetHostView::GetLocalSurfaceId()
|
||||
const {
|
||||
return browser_compositor_->GetRendererLocalSurfaceId();
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ gfx::NativeView OffScreenWebContentsView::GetNativeView() const {
|
||||
auto* relay = NativeWindowRelay::FromWebContents(web_contents_);
|
||||
if (!relay)
|
||||
return gfx::NativeView();
|
||||
return relay->window->GetNativeView();
|
||||
return relay->GetNativeWindow()->GetNativeView();
|
||||
}
|
||||
|
||||
gfx::NativeView OffScreenWebContentsView::GetContentNativeView() const {
|
||||
@@ -52,7 +52,7 @@ gfx::NativeView OffScreenWebContentsView::GetContentNativeView() const {
|
||||
auto* relay = NativeWindowRelay::FromWebContents(web_contents_);
|
||||
if (!relay)
|
||||
return gfx::NativeView();
|
||||
return relay->window->GetNativeView();
|
||||
return relay->GetNativeWindow()->GetNativeView();
|
||||
}
|
||||
|
||||
gfx::NativeWindow OffScreenWebContentsView::GetTopLevelNativeWindow() const {
|
||||
@@ -62,7 +62,7 @@ gfx::NativeWindow OffScreenWebContentsView::GetTopLevelNativeWindow() const {
|
||||
auto* relay = NativeWindowRelay::FromWebContents(web_contents_);
|
||||
if (!relay)
|
||||
return gfx::NativeWindow();
|
||||
return relay->window->GetNativeWindow();
|
||||
return relay->GetNativeWindow()->GetNativeWindow();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -102,17 +102,14 @@ OffScreenWebContentsView::CreateViewForWidget(
|
||||
render_widget_host->GetView());
|
||||
}
|
||||
|
||||
auto* relay = NativeWindowRelay::FromWebContents(web_contents_);
|
||||
return new OffScreenRenderWidgetHostView(
|
||||
transparent_, painting_, GetFrameRate(), callback_, render_widget_host,
|
||||
nullptr, relay->window.get());
|
||||
nullptr, nullptr);
|
||||
}
|
||||
|
||||
content::RenderWidgetHostViewBase*
|
||||
OffScreenWebContentsView::CreateViewForPopupWidget(
|
||||
content::RenderWidgetHost* render_widget_host) {
|
||||
auto* relay = NativeWindowRelay::FromWebContents(web_contents_);
|
||||
|
||||
content::WebContentsImpl* web_contents_impl =
|
||||
static_cast<content::WebContentsImpl*>(web_contents_);
|
||||
|
||||
@@ -123,9 +120,9 @@ OffScreenWebContentsView::CreateViewForPopupWidget(
|
||||
->GetRenderWidgetHostView()
|
||||
: web_contents_impl->GetRenderWidgetHostView());
|
||||
|
||||
return new OffScreenRenderWidgetHostView(
|
||||
transparent_, true, view->GetFrameRate(), callback_, render_widget_host,
|
||||
view, relay->window.get());
|
||||
return new OffScreenRenderWidgetHostView(transparent_, true,
|
||||
view->GetFrameRate(), callback_,
|
||||
render_widget_host, view, nullptr);
|
||||
}
|
||||
|
||||
void OffScreenWebContentsView::SetPageTitle(const base::string16& title) {}
|
||||
@@ -140,8 +137,11 @@ void OffScreenWebContentsView::RenderViewCreated(
|
||||
#endif
|
||||
}
|
||||
|
||||
void OffScreenWebContentsView::RenderViewSwappedIn(
|
||||
content::RenderViewHost* host) {}
|
||||
void OffScreenWebContentsView::RenderViewReady() {}
|
||||
|
||||
void OffScreenWebContentsView::RenderViewHostChanged(
|
||||
content::RenderViewHost* old_host,
|
||||
content::RenderViewHost* new_host) {}
|
||||
|
||||
void OffScreenWebContentsView::SetOverscrollControllerEnabled(bool enabled) {}
|
||||
|
||||
|
||||
@@ -50,7 +50,9 @@ class OffScreenWebContentsView : public content::WebContentsView,
|
||||
content::RenderWidgetHost* render_widget_host) override;
|
||||
void SetPageTitle(const base::string16& title) override;
|
||||
void RenderViewCreated(content::RenderViewHost* host) override;
|
||||
void RenderViewSwappedIn(content::RenderViewHost* host) override;
|
||||
void RenderViewReady() override;
|
||||
void RenderViewHostChanged(content::RenderViewHost* old_host,
|
||||
content::RenderViewHost* new_host) override;
|
||||
void SetOverscrollControllerEnabled(bool enabled) override;
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
|
||||
@@ -50,8 +50,8 @@ END
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 4,0,0,20181010
|
||||
PRODUCTVERSION 4,0,0,20181010
|
||||
FILEVERSION 4,0,0,5
|
||||
PRODUCTVERSION 4,0,0,5
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
||||
@@ -171,6 +171,10 @@ bool WebContentsPreferences::GetPreference(const base::StringPiece& name,
|
||||
return GetAsString(&preference_, name, value);
|
||||
}
|
||||
|
||||
bool WebContentsPreferences::IsRemoteModuleEnabled() const {
|
||||
return IsEnabled(options::kEnableRemoteModule, true);
|
||||
}
|
||||
|
||||
bool WebContentsPreferences::GetPreloadPath(
|
||||
base::FilePath::StringType* path) const {
|
||||
DCHECK(path);
|
||||
@@ -267,6 +271,10 @@ void WebContentsPreferences::AppendCommandLineSwitches(
|
||||
}
|
||||
}
|
||||
|
||||
// Whether to enable the remote module
|
||||
if (!IsRemoteModuleEnabled())
|
||||
command_line->AppendSwitch(switches::kDisableRemoteModule);
|
||||
|
||||
// Run Electron APIs and preload script in isolated world
|
||||
if (IsEnabled(options::kContextIsolation))
|
||||
command_line->AppendSwitch(switches::kContextIsolation);
|
||||
@@ -397,6 +405,8 @@ void WebContentsPreferences::OverrideWebkitPrefs(
|
||||
std::string encoding;
|
||||
if (GetAsString(&preference_, "defaultEncoding", &encoding))
|
||||
prefs->default_encoding = encoding;
|
||||
|
||||
prefs->node_integration = IsEnabled(options::kNodeIntegration);
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -55,6 +55,9 @@ class WebContentsPreferences
|
||||
// Return true if the particular preference value exists.
|
||||
bool GetPreference(const base::StringPiece& name, std::string* value) const;
|
||||
|
||||
// Whether to enable the remote module
|
||||
bool IsRemoteModuleEnabled() const;
|
||||
|
||||
// Returns the preload script path.
|
||||
bool GetPreloadPath(base::FilePath::StringType* path) const;
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#define ATOM_MINOR_VERSION 0
|
||||
#define ATOM_PATCH_VERSION 0
|
||||
// clang-format off
|
||||
#define ATOM_PRE_RELEASE_VERSION -nightly.20181010
|
||||
#define ATOM_PRE_RELEASE_VERSION -beta.5
|
||||
// clang-format on
|
||||
|
||||
#ifndef ATOM_STRINGIFY
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "atom/common/api/event_emitter_caller.h"
|
||||
@@ -18,6 +19,7 @@
|
||||
#include "base/environment.h"
|
||||
#include "base/path_service.h"
|
||||
#include "base/run_loop.h"
|
||||
#include "base/strings/string_split.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "base/threading/thread_task_runner_handle.h"
|
||||
#include "base/trace_event/trace_event.h"
|
||||
@@ -213,19 +215,73 @@ void NodeBindings::Initialize() {
|
||||
// Explicitly register electron's builtin modules.
|
||||
RegisterBuiltinModules();
|
||||
|
||||
// Init node.
|
||||
// (we assume node::Init would not modify the parameters under embedded mode).
|
||||
// NOTE: If you change this line, please ping @codebytere or @MarshallOfSound
|
||||
int argc = 0;
|
||||
// pass non-null program name to argv so it doesn't crash
|
||||
// trying to index into a nullptr
|
||||
int argc = 1;
|
||||
int exec_argc = 0;
|
||||
const char** argv = nullptr;
|
||||
const char* prog_name = "electron";
|
||||
const char** argv = &prog_name;
|
||||
const char** exec_argv = nullptr;
|
||||
|
||||
std::unique_ptr<base::Environment> env(base::Environment::Create());
|
||||
if (env->HasVar("NODE_OPTIONS")) {
|
||||
base::FilePath exe_path;
|
||||
base::PathService::Get(base::FILE_EXE, &exe_path);
|
||||
#if defined(OS_WIN)
|
||||
std::string path = base::UTF16ToUTF8(exe_path.value());
|
||||
#else
|
||||
std::string path = exe_path.value();
|
||||
#endif
|
||||
std::transform(path.begin(), path.end(), path.begin(), ::tolower);
|
||||
|
||||
#if defined(OS_WIN)
|
||||
const bool is_packaged_app = path == "electron.exe";
|
||||
#else
|
||||
const bool is_packaged_app = path == "electron";
|
||||
#endif
|
||||
|
||||
// explicitly disallow NODE_OPTIONS in packaged apps
|
||||
if (is_packaged_app) {
|
||||
LOG(WARNING) << "NODE_OPTIONs are not supported in packaged apps";
|
||||
env->SetVar("NODE_OPTIONS", "");
|
||||
} else {
|
||||
const std::vector<std::string> disallowed = {
|
||||
"--openssl-config", "--use-bundled-ca", "--use-openssl-ca",
|
||||
"--force-fips", "--enable-fips"};
|
||||
|
||||
std::string options;
|
||||
env->GetVar("NODE_OPTIONS", &options);
|
||||
std::vector<std::string> parts = base::SplitString(
|
||||
options, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
|
||||
|
||||
// parse passed options for unsupported options
|
||||
// and remove them from the options list
|
||||
std::string new_options = options;
|
||||
for (const auto& disallow : disallowed) {
|
||||
for (const auto& part : parts) {
|
||||
if (part.find(disallow) != std::string::npos) {
|
||||
LOG(WARNING) << "The NODE_OPTION" << disallow
|
||||
<< "is not supported in Electron";
|
||||
new_options.erase(new_options.find(part), part.length());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// overwrite new NODE_OPTIONS without unsupported variables
|
||||
if (new_options != options)
|
||||
env->SetVar("NODE_OPTIONS", new_options);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(codebytere): this is going to be deprecated in the near future
|
||||
// in favor of Init(std::vector<std::string>* argv,
|
||||
// std::vector<std::string>* exec_argv)
|
||||
node::Init(&argc, argv, &exec_argc, &exec_argv);
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// uv_init overrides error mode to suppress the default crash dialog, bring
|
||||
// it back if user wants to show it.
|
||||
std::unique_ptr<base::Environment> env(base::Environment::Create());
|
||||
if (browser_env_ == BROWSER || env->HasVar("ELECTRON_DEFAULT_ERROR_MODE"))
|
||||
SetErrorMode(GetErrorMode() & ~SEM_NOGPFAULTERRORBOX);
|
||||
#endif
|
||||
|
||||
@@ -110,6 +110,9 @@ const char kPreloadURL[] = "preloadURL";
|
||||
// Enable the node integration.
|
||||
const char kNodeIntegration[] = "nodeIntegration";
|
||||
|
||||
// Enable the remote module
|
||||
const char kEnableRemoteModule[] = "enableRemoteModule";
|
||||
|
||||
// Enable context isolation of Electron APIs and preload script
|
||||
const char kContextIsolation[] = "contextIsolation";
|
||||
|
||||
@@ -193,6 +196,7 @@ const char kBackgroundColor[] = "background-color";
|
||||
const char kPreloadScript[] = "preload";
|
||||
const char kPreloadScripts[] = "preload-scripts";
|
||||
const char kNodeIntegration[] = "node-integration";
|
||||
const char kDisableRemoteModule[] = "disable-remote-module";
|
||||
const char kContextIsolation[] = "context-isolation";
|
||||
const char kGuestInstanceID[] = "guest-instance-id";
|
||||
const char kOpenerID[] = "opener-id";
|
||||
|
||||
@@ -58,6 +58,7 @@ extern const char kZoomFactor[];
|
||||
extern const char kPreloadScript[];
|
||||
extern const char kPreloadURL[];
|
||||
extern const char kNodeIntegration[];
|
||||
extern const char kEnableRemoteModule[];
|
||||
extern const char kContextIsolation[];
|
||||
extern const char kGuestInstanceID[];
|
||||
extern const char kExperimentalFeatures[];
|
||||
@@ -97,6 +98,7 @@ extern const char kBackgroundColor[];
|
||||
extern const char kPreloadScript[];
|
||||
extern const char kPreloadScripts[];
|
||||
extern const char kNodeIntegration[];
|
||||
extern const char kDisableRemoteModule[];
|
||||
extern const char kContextIsolation[];
|
||||
extern const char kGuestInstanceID[];
|
||||
extern const char kOpenerID[];
|
||||
|
||||
@@ -21,8 +21,7 @@ v8::Maybe<bool> Promise::RejectWithErrorMessage(const std::string& string) {
|
||||
v8::Local<v8::String> error_message =
|
||||
v8::String::NewFromUtf8(isolate(), string.c_str());
|
||||
v8::Local<v8::Value> error = v8::Exception::Error(error_message);
|
||||
return GetInner()->Reject(isolate()->GetCurrentContext(),
|
||||
mate::ConvertToV8(isolate(), error));
|
||||
return Reject(error);
|
||||
}
|
||||
|
||||
v8::Local<v8::Promise> Promise::GetHandle() const {
|
||||
|
||||
@@ -32,6 +32,8 @@ class Promise : public base::RefCounted<Promise> {
|
||||
v8::Undefined(isolate()));
|
||||
}
|
||||
|
||||
// Promise resolution is a microtask
|
||||
// We use the MicrotasksRunner to trigger the running of pending microtasks
|
||||
template <typename T>
|
||||
v8::Maybe<bool> Resolve(const T& value) {
|
||||
return GetInner()->Resolve(isolate()->GetCurrentContext(),
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "atom/renderer/atom_render_frame_observer.h"
|
||||
#include "atom/renderer/web_worker_observer.h"
|
||||
#include "base/command_line.h"
|
||||
#include "content/public/common/web_preferences.h"
|
||||
#include "content/public/renderer/render_frame.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "third_party/blink/public/web/web_document.h"
|
||||
@@ -86,6 +87,15 @@ void AtomRendererClient::DidCreateScriptContext(
|
||||
if (!render_frame->IsMainFrame() && !IsDevToolsExtension(render_frame))
|
||||
return;
|
||||
|
||||
// Don't allow node integration if this is a child window and it does not have
|
||||
// node integration enabled. Otherwise we would have memory leak in the child
|
||||
// window since we don't clean up node environments.
|
||||
//
|
||||
// TODO(zcbenz): We shouldn't allow node integration even for the top frame.
|
||||
if (!render_frame->GetWebkitPreferences().node_integration &&
|
||||
render_frame->GetWebFrame()->Opener())
|
||||
return;
|
||||
|
||||
injected_frames_.insert(render_frame);
|
||||
|
||||
// Prepare the node bindings.
|
||||
|
||||
@@ -71,6 +71,15 @@ std::vector<std::string> ParseSchemesCLISwitch(base::CommandLine* command_line,
|
||||
base::SPLIT_WANT_NONEMPTY);
|
||||
}
|
||||
|
||||
void SetHiddenValue(v8::Handle<v8::Context> context,
|
||||
const base::StringPiece& key,
|
||||
v8::Local<v8::Value> value) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
v8::Local<v8::Private> privateKey =
|
||||
v8::Private::ForApi(isolate, mate::StringToV8(isolate, key));
|
||||
context->Global()->SetPrivate(context, privateKey, value);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
RendererClientBase::RendererClientBase() {
|
||||
@@ -100,10 +109,13 @@ void RendererClientBase::DidCreateScriptContext(
|
||||
auto context_id = base::StringPrintf(
|
||||
"%s-%" PRId64, renderer_client_id_.c_str(), ++next_context_id_);
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
v8::Local<v8::String> key = mate::StringToSymbol(isolate, "contextId");
|
||||
v8::Local<v8::Private> private_key = v8::Private::ForApi(isolate, key);
|
||||
v8::Local<v8::Value> value = mate::ConvertToV8(isolate, context_id);
|
||||
context->Global()->SetPrivate(context, private_key, value);
|
||||
SetHiddenValue(context, "contextId", mate::ConvertToV8(isolate, context_id));
|
||||
|
||||
auto* command_line = base::CommandLine::ForCurrentProcess();
|
||||
bool enableRemoteModule =
|
||||
!command_line->HasSwitch(switches::kDisableRemoteModule);
|
||||
SetHiddenValue(context, "enableRemoteModule",
|
||||
mate::ConvertToV8(isolate, enableRemoteModule));
|
||||
}
|
||||
|
||||
void RendererClientBase::AddRenderBindings(
|
||||
@@ -177,22 +189,26 @@ void RendererClientBase::RenderFrameCreated(
|
||||
blink::WebSecurityPolicy::AddOriginAccessWhitelistEntry(
|
||||
GURL(kPdfViewerUIOrigin), "file", "", true);
|
||||
#endif // BUILDFLAG(ENABLE_PDF_VIEWER)
|
||||
|
||||
content::RenderView* render_view = render_frame->GetRenderView();
|
||||
if (render_frame->IsMainFrame() && render_view) {
|
||||
blink::WebFrameWidget* web_frame_widget = render_view->GetWebFrameWidget();
|
||||
if (web_frame_widget) {
|
||||
base::CommandLine* cmd = base::CommandLine::ForCurrentProcess();
|
||||
if (cmd->HasSwitch(switches::kGuestInstanceID)) { // webview.
|
||||
web_frame_widget->SetBaseBackgroundColor(SK_ColorTRANSPARENT);
|
||||
} else { // normal window.
|
||||
std::string name = cmd->GetSwitchValueASCII(switches::kBackgroundColor);
|
||||
SkColor color =
|
||||
name.empty() ? SK_ColorTRANSPARENT : ParseHexColor(name);
|
||||
web_frame_widget->SetBaseBackgroundColor(color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RendererClientBase::RenderViewCreated(content::RenderView* render_view) {
|
||||
new AtomRenderViewObserver(render_view);
|
||||
blink::WebFrameWidget* web_frame_widget = render_view->GetWebFrameWidget();
|
||||
if (!web_frame_widget)
|
||||
return;
|
||||
|
||||
base::CommandLine* cmd = base::CommandLine::ForCurrentProcess();
|
||||
if (cmd->HasSwitch(switches::kGuestInstanceID)) { // webview.
|
||||
web_frame_widget->SetBaseBackgroundColor(SK_ColorTRANSPARENT);
|
||||
} else { // normal window.
|
||||
std::string name = cmd->GetSwitchValueASCII(switches::kBackgroundColor);
|
||||
SkColor color = name.empty() ? SK_ColorTRANSPARENT : ParseHexColor(name);
|
||||
web_frame_widget->SetBaseBackgroundColor(color);
|
||||
}
|
||||
}
|
||||
|
||||
void RendererClientBase::DidClearWindowObject(
|
||||
|
||||
@@ -4,6 +4,7 @@ root_extra_deps = [ "//electron" ]
|
||||
|
||||
v8_promise_internal_field_count = 1
|
||||
v8_typed_array_max_size_in_heap = 0
|
||||
v8_embedder_string = "-electron.0"
|
||||
|
||||
enable_cdm_host_verification = false
|
||||
enable_extensions = false
|
||||
|
||||
6
build/electron.def
Normal file
6
build/electron.def
Normal file
@@ -0,0 +1,6 @@
|
||||
; This is to support renaming of electron.exe. node-gyp has hard-coded
|
||||
; executable names which it will recognise as node. This module definition
|
||||
; file claims that the electron executable is in fact named "node.exe",
|
||||
; which is one of the executable names that node-gyp recognizes.
|
||||
; See https://github.com/nodejs/node-gyp/commit/52ceec3a6d15de3a8f385f43dbe5ecf5456ad07a
|
||||
NAME node.exe
|
||||
@@ -8,7 +8,7 @@ declare_args() {
|
||||
# Allow running Electron as a node binary.
|
||||
enable_run_as_node = true
|
||||
|
||||
enable_osr = false
|
||||
enable_osr = true
|
||||
|
||||
enable_view_api = false
|
||||
|
||||
|
||||
@@ -369,7 +369,6 @@ details.
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `session` [Session](session.md)
|
||||
|
||||
Emitted when Electron has created a new `session`.
|
||||
@@ -995,7 +994,7 @@ Returns `Object`:
|
||||
the app as a login item. Defaults to `false`.
|
||||
* `openAsHidden` Boolean (optional) _macOS_ - `true` to open the app as hidden. Defaults to
|
||||
`false`. The user can edit this setting from the System Preferences so
|
||||
`app.getLoginItemStatus().wasOpenedAsHidden` should be checked when the app
|
||||
`app.getLoginItemSettings().wasOpenedAsHidden` should be checked when the app
|
||||
is opened to know the current value. This setting is not available on [MAS builds][mas-builds].
|
||||
* `path` String (optional) _Windows_ - The executable to launch at login.
|
||||
Defaults to `process.execPath`.
|
||||
|
||||
@@ -18,6 +18,9 @@ The following `webPreferences` option default values are deprecated in favor of
|
||||
| `nodeIntegration` | `true` | `false` |
|
||||
| `webviewTag` | `nodeIntegration` if set else `true` | `false` |
|
||||
|
||||
## `nativeWindowOpen`
|
||||
|
||||
Child windows opened with the `nativeWindowOpen` option will always have Node.js integration disabled.
|
||||
|
||||
# Planned Breaking API Changes (4.0)
|
||||
|
||||
|
||||
@@ -2,9 +2,6 @@
|
||||
|
||||
> Create and control views.
|
||||
|
||||
**Note:** The BrowserView API is currently experimental and may change or be
|
||||
removed in future Electron releases.
|
||||
|
||||
Process: [Main](../glossary.md#main-process)
|
||||
|
||||
A `BrowserView` can be used to embed additional web content into a
|
||||
|
||||
@@ -270,6 +270,8 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
are more limited. Read more about the option [here](sandbox-option.md).
|
||||
**Note:** This option is currently experimental and may change or be
|
||||
removed in future Electron releases.
|
||||
* `enableRemoteModule` Boolean (optional) - Whether to enable the [`remote`](remote.md) module.
|
||||
Default is `true`.
|
||||
* `session` [Session](session.md#class-session) (optional) - Sets the session used by the
|
||||
page. Instead of passing the Session object directly, you can also choose to
|
||||
use the `partition` option instead, which accepts a partition string. When
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
|
||||
Process: [Main](../glossary.md#main-process), [Renderer](../glossary.md#renderer-process)
|
||||
|
||||
In the renderer process context it depends on the [`remote`](remote.md) module on Linux,
|
||||
it is therefore not available when this module is disabled.
|
||||
|
||||
The following example shows how to write a string to the clipboard:
|
||||
|
||||
```javascript
|
||||
|
||||
@@ -24,6 +24,28 @@ Windows console example:
|
||||
The following environment variables are intended primarily for use at runtime
|
||||
in packaged Electron applications.
|
||||
|
||||
### `NODE_OPTIONS`
|
||||
|
||||
Electron includes support for a subset of Node's [`NODE_OPTIONS`](https://nodejs.org/api/cli.html#cli_node_options_options). The majority are supported with the exception of those which conflict with Chromium's use of BoringSSL.
|
||||
|
||||
Example:
|
||||
|
||||
```sh
|
||||
export NODE_OPTIONS="--no-warnings --max-old-space-size=2048"
|
||||
```
|
||||
|
||||
Unsupported options are:
|
||||
|
||||
```sh
|
||||
--use-bundled-ca
|
||||
--force-fips
|
||||
--enable-fips
|
||||
--openssl-config
|
||||
--use-openssl-ca
|
||||
```
|
||||
|
||||
`NODE_OPTIONS` are explicitly disallowed in packaged apps.
|
||||
|
||||
### `GOOGLE_API_KEY`
|
||||
|
||||
Electron includes a hardcoded API key for making requests to Google's geocoding
|
||||
|
||||
@@ -24,6 +24,10 @@ win.loadURL('https://github.com')
|
||||
**Note:** For the reverse (access the renderer process from the main process),
|
||||
you can use [webContents.executeJavaScript](web-contents.md#contentsexecutejavascriptcode-usergesture-callback).
|
||||
|
||||
**Note:** The remote module can be disabled for security reasons in the following contexts:
|
||||
- [`BrowserWindow`](browser-window.md) - by setting the `enableRemoteModule` option to `false`.
|
||||
- [`<webview>`](webview-tag.md) - by setting the `enableremotemodule` attribute to `false`.
|
||||
|
||||
## Remote Objects
|
||||
|
||||
Each object (including functions) returned by the `remote` module represents an
|
||||
@@ -180,7 +184,7 @@ belongs.
|
||||
**Note:** Do not use `removeAllListeners` on [`BrowserWindow`](browser-window.md).
|
||||
Use of this can remove all [`blur`](https://developer.mozilla.org/en-US/docs/Web/Events/blur)
|
||||
listeners, disable click events on touch bar buttons, and other unintended
|
||||
consequences.
|
||||
consequences.
|
||||
|
||||
### `remote.getCurrentWebContents()`
|
||||
|
||||
|
||||
@@ -7,6 +7,9 @@ Process: [Main](../glossary.md#main-process), [Renderer](../glossary.md#renderer
|
||||
You cannot require or use this module until the `ready` event of the `app`
|
||||
module is emitted.
|
||||
|
||||
In the renderer process context it depends on the [`remote`](remote.md) module,
|
||||
it is therefore not available when this module is disabled.
|
||||
|
||||
`screen` is an [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter).
|
||||
|
||||
**Note:** In the renderer / DevTools, `window.screen` is a reserved DOM
|
||||
|
||||
@@ -126,6 +126,15 @@ integration and can use node APIs like `require` and `process` to access low
|
||||
level system resources. Node integration is disabled by default in the guest
|
||||
page.
|
||||
|
||||
### `enableremotemodule`
|
||||
|
||||
```html
|
||||
<webview src="http://www.google.com/" enableremotemodule="false"></webview>
|
||||
```
|
||||
|
||||
When this attribute is `false` the guest page in `webview` will not have access
|
||||
to the [`remote`](remote.md) module. The remote module is avaiable by default.
|
||||
|
||||
### `plugins`
|
||||
|
||||
```html
|
||||
@@ -613,6 +622,9 @@ Shows pop-up dictionary that searches the selected word on the page.
|
||||
Returns [`WebContents`](web-contents.md) - The web contents associated with
|
||||
this `webview`.
|
||||
|
||||
It depends on the [`remote`](remote.md) module,
|
||||
it is therefore not available when this module is disabled.
|
||||
|
||||
## DOM events
|
||||
|
||||
The following DOM events are available to the `webview` tag:
|
||||
|
||||
@@ -68,6 +68,7 @@ filenames = {
|
||||
"lib/renderer/init.js",
|
||||
"lib/renderer/inspector.js",
|
||||
"lib/renderer/ipc-renderer-internal.js",
|
||||
"lib/renderer/remote.js",
|
||||
"lib/renderer/override.js",
|
||||
"lib/renderer/security-warnings.js",
|
||||
"lib/renderer/web-frame-init.js",
|
||||
@@ -270,6 +271,8 @@ filenames = {
|
||||
"atom/browser/mac/in_app_purchase_observer.mm",
|
||||
"atom/browser/mac/in_app_purchase_product.h",
|
||||
"atom/browser/mac/in_app_purchase_product.mm",
|
||||
"atom/browser/microtasks_runner.cc",
|
||||
"atom/browser/microtasks_runner.h",
|
||||
"atom/browser/native_browser_view.cc",
|
||||
"atom/browser/native_browser_view.h",
|
||||
"atom/browser/native_browser_view_mac.h",
|
||||
|
||||
@@ -49,6 +49,23 @@ BrowserWindow.prototype._init = function () {
|
||||
return
|
||||
}
|
||||
|
||||
if (webContents.getLastWebPreferences().nodeIntegration === true) {
|
||||
const message =
|
||||
'Enabling Node.js integration in child windows opened with the ' +
|
||||
'"nativeWindowOpen" option will cause memory leaks, please turn off ' +
|
||||
'the "nodeIntegration" option.\\n' +
|
||||
'From 5.x child windows opened with the "nativeWindowOpen" option ' +
|
||||
'will always have Node.js integration disabled.\\n' +
|
||||
'See https://github.com/electron/electron/pull/15076 for more.'
|
||||
// console is only available after DOM is created.
|
||||
const printWarning = () => this.webContents.executeJavaScript(`console.warn('${message}')`)
|
||||
if (this.webContents.isDomReady()) {
|
||||
printWarning()
|
||||
} else {
|
||||
this.webContents.once('dom-ready', printWarning)
|
||||
}
|
||||
}
|
||||
|
||||
const { url, frameName } = urlFrameName
|
||||
v8Util.deleteHiddenValue(webContents, 'url-framename')
|
||||
const options = {
|
||||
|
||||
@@ -17,10 +17,15 @@ function splitArray (arr, predicate) {
|
||||
return result
|
||||
}
|
||||
|
||||
function joinArrays (arrays, joiner) {
|
||||
function joinArrays (arrays, joinIDs) {
|
||||
return arrays.reduce((joined, arr, i) => {
|
||||
if (i > 0 && arr.length) {
|
||||
joined.push(joiner)
|
||||
if (joinIDs.length > 0) {
|
||||
joined.push(joinIDs[0])
|
||||
joinIDs.splice(0, 1)
|
||||
} else {
|
||||
joined.push({ type: 'separator' })
|
||||
}
|
||||
}
|
||||
return joined.concat(arr)
|
||||
}, [])
|
||||
@@ -156,6 +161,7 @@ function sortGroups (groups) {
|
||||
|
||||
function sortMenuItems (menuItems) {
|
||||
const isSeparator = (item) => item.type === 'separator'
|
||||
const separators = menuItems.filter(i => i.type === 'separator')
|
||||
|
||||
// Split the items into their implicit groups based upon separators.
|
||||
const groups = splitArray(menuItems, isSeparator)
|
||||
@@ -163,7 +169,7 @@ function sortMenuItems (menuItems) {
|
||||
const mergedGroupsWithSortedItems = mergedGroups.map(sortItemsInGroup)
|
||||
const sortedGroups = sortGroups(mergedGroupsWithSortedItems)
|
||||
|
||||
const joined = joinArrays(sortedGroups, { type: 'separator' })
|
||||
const joined = joinArrays(sortedGroups, separators)
|
||||
return joined
|
||||
}
|
||||
|
||||
|
||||
@@ -360,20 +360,6 @@ app.on('will-quit', function () {
|
||||
|
||||
// We can not use protocol or BrowserWindow until app is ready.
|
||||
app.once('ready', function () {
|
||||
// Load persisted extensions.
|
||||
loadedDevToolsExtensionsPath = path.join(app.getPath('userData'), 'DevTools Extensions')
|
||||
try {
|
||||
const loadedDevToolsExtensions = JSON.parse(fs.readFileSync(loadedDevToolsExtensionsPath))
|
||||
if (Array.isArray(loadedDevToolsExtensions)) {
|
||||
for (const srcDirectory of loadedDevToolsExtensions) {
|
||||
// Start background pages and set content scripts.
|
||||
BrowserWindow.addDevToolsExtension(srcDirectory)
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore error
|
||||
}
|
||||
|
||||
// The public API to add/remove extensions.
|
||||
BrowserWindow.addExtension = function (srcDirectory) {
|
||||
const manifest = getManifestFromPath(srcDirectory)
|
||||
@@ -429,4 +415,21 @@ app.once('ready', function () {
|
||||
})
|
||||
return devExtensions
|
||||
}
|
||||
|
||||
// Load persisted extensions.
|
||||
loadedDevToolsExtensionsPath = path.join(app.getPath('userData'), 'DevTools Extensions')
|
||||
try {
|
||||
const loadedDevToolsExtensions = JSON.parse(fs.readFileSync(loadedDevToolsExtensionsPath))
|
||||
if (Array.isArray(loadedDevToolsExtensions)) {
|
||||
for (const srcDirectory of loadedDevToolsExtensions) {
|
||||
// Start background pages and set content scripts.
|
||||
BrowserWindow.addDevToolsExtension(srcDirectory)
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
if (process.env.ELECTRON_ENABLE_LOGGING) {
|
||||
console.error('Failed to load browser extensions from directory:', loadedDevToolsExtensionsPath)
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -209,6 +209,7 @@ const attachGuest = function (event, embedderFrameId, elementInstanceId, guestIn
|
||||
const webPreferences = {
|
||||
guestInstanceId: guestInstanceId,
|
||||
nodeIntegration: params.nodeintegration != null ? params.nodeintegration : false,
|
||||
enableRemoteModule: params.enableremotemodule,
|
||||
plugins: params.plugins,
|
||||
zoomFactor: embedder._getZoomFactor(),
|
||||
webSecurity: !params.disablewebsecurity,
|
||||
@@ -243,6 +244,7 @@ const attachGuest = function (event, embedderFrameId, elementInstanceId, guestIn
|
||||
['javascript', false],
|
||||
['nativeWindowOpen', true],
|
||||
['nodeIntegration', false],
|
||||
['enableRemoteModule', false],
|
||||
['sandbox', true]
|
||||
])
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ const inheritedWebPreferences = new Map([
|
||||
['javascript', false],
|
||||
['nativeWindowOpen', true],
|
||||
['nodeIntegration', false],
|
||||
['enableRemoteModule', false],
|
||||
['sandbox', true],
|
||||
['webviewTag', false]
|
||||
])
|
||||
@@ -195,7 +196,7 @@ ipcMain.on('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_OPEN', (event, url, frameName,
|
||||
const options = {}
|
||||
|
||||
const ints = ['x', 'y', 'width', 'height', 'minWidth', 'maxWidth', 'minHeight', 'maxHeight', 'zoomFactor']
|
||||
const webPreferences = ['zoomFactor', 'nodeIntegration', 'preload', 'javascript', 'contextIsolation', 'webviewTag']
|
||||
const webPreferences = ['zoomFactor', 'nodeIntegration', 'enableRemoteModule', 'preload', 'javascript', 'contextIsolation', 'webviewTag']
|
||||
const disposition = 'new-window'
|
||||
|
||||
// Used to store additional features
|
||||
|
||||
@@ -127,9 +127,9 @@ if (packageJson.version != null) {
|
||||
|
||||
// Set application's name.
|
||||
if (packageJson.productName != null) {
|
||||
app.setName(packageJson.productName)
|
||||
app.setName(`${packageJson.productName}`.trim())
|
||||
} else if (packageJson.name != null) {
|
||||
app.setName(packageJson.name)
|
||||
app.setName(`${packageJson.name}`.trim())
|
||||
}
|
||||
|
||||
// Set application's desktop name.
|
||||
|
||||
@@ -263,11 +263,17 @@ const callFunction = function (event, contextId, func, caller, args) {
|
||||
const handleRemoteCommand = function (channel, handler) {
|
||||
ipcMain.on(channel, (event, contextId, ...args) => {
|
||||
let returnValue
|
||||
if (!event.sender._isRemoteModuleEnabled()) {
|
||||
event.returnValue = null
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
returnValue = handler(event, contextId, ...args)
|
||||
} catch (error) {
|
||||
returnValue = exceptionToMeta(event.sender, contextId, error)
|
||||
}
|
||||
|
||||
if (returnValue !== undefined) {
|
||||
event.returnValue = returnValue
|
||||
}
|
||||
@@ -376,7 +382,7 @@ handleRemoteCommand('ELECTRON_BROWSER_GUEST_WEB_CONTENTS', function (event, cont
|
||||
|
||||
ipcMain.on('ELECTRON_BROWSER_ASYNC_CALL_TO_GUEST_VIEW', function (event, requestId, guestInstanceId, method, args, hasCallback) {
|
||||
new Promise(resolve => {
|
||||
const guestViewManager = require('./guest-view-manager')
|
||||
const guestViewManager = require('@electron/internal/browser/guest-view-manager')
|
||||
const guest = guestViewManager.getGuest(guestInstanceId)
|
||||
if (guest.hostWebContents !== event.sender) {
|
||||
throw new Error('Access denied')
|
||||
@@ -428,6 +434,7 @@ const getTempDirectory = function () {
|
||||
const crashReporterInit = function (options) {
|
||||
const productName = options.productName || electron.app.getName()
|
||||
const crashesDirectory = path.join(getTempDirectory(), `${productName} Crashes`)
|
||||
let crashServicePid
|
||||
|
||||
if (process.platform === 'win32') {
|
||||
const env = {
|
||||
@@ -440,25 +447,44 @@ const crashReporterInit = function (options) {
|
||||
'--v=1'
|
||||
]
|
||||
|
||||
spawn(process.helperExecPath, args, {
|
||||
const crashServiceProcess = spawn(process.helperExecPath, args, {
|
||||
env,
|
||||
detached: true
|
||||
})
|
||||
|
||||
crashServicePid = crashServiceProcess.pid
|
||||
}
|
||||
|
||||
return {
|
||||
productName,
|
||||
crashesDirectory,
|
||||
crashServicePid,
|
||||
appVersion: electron.app.getVersion()
|
||||
}
|
||||
}
|
||||
|
||||
ipcMain.on('ELECTRON_CRASH_REPORTER_INIT', function (event, options) {
|
||||
const setReturnValue = function (event, getValue) {
|
||||
try {
|
||||
event.returnValue = [null, crashReporterInit(options)]
|
||||
event.returnValue = [null, getValue()]
|
||||
} catch (error) {
|
||||
event.returnValue = [errorUtils.serialize(error)]
|
||||
}
|
||||
}
|
||||
|
||||
ipcMain.on('ELECTRON_CRASH_REPORTER_INIT', function (event, options) {
|
||||
setReturnValue(event, () => crashReporterInit(options))
|
||||
})
|
||||
|
||||
ipcMain.on('ELECTRON_BROWSER_GET_LAST_WEB_PREFERENCES', function (event) {
|
||||
setReturnValue(event, () => event.sender.getLastWebPreferences())
|
||||
})
|
||||
|
||||
ipcMain.on('ELECTRON_BROWSER_CLIPBOARD_READ_FIND_TEXT', function (event) {
|
||||
setReturnValue(event, () => electron.clipboard.readFindText())
|
||||
})
|
||||
|
||||
ipcMain.on('ELECTRON_BROWSER_CLIPBOARD_WRITE_FIND_TEXT', function (event, text) {
|
||||
setReturnValue(event, () => electron.clipboard.writeFindText(text))
|
||||
})
|
||||
|
||||
ipcMain.on('ELECTRON_BROWSER_SANDBOX_LOAD', function (event) {
|
||||
@@ -475,6 +501,7 @@ ipcMain.on('ELECTRON_BROWSER_SANDBOX_LOAD', function (event) {
|
||||
event.returnValue = {
|
||||
preloadSrc,
|
||||
preloadError,
|
||||
isRemoteModuleEnabled: event.sender._isRemoteModuleEnabled(),
|
||||
process: {
|
||||
arch: process.arch,
|
||||
platform: process.platform,
|
||||
@@ -484,11 +511,3 @@ ipcMain.on('ELECTRON_BROWSER_SANDBOX_LOAD', function (event) {
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.on('ELECTRON_BROWSER_GET_LAST_WEB_PREFERENCES', function (event) {
|
||||
try {
|
||||
event.returnValue = [null, event.sender.getLastWebPreferences()]
|
||||
} catch (error) {
|
||||
event.returnValue = [errorUtils.serialize(error)]
|
||||
}
|
||||
})
|
||||
|
||||
@@ -2,15 +2,29 @@
|
||||
|
||||
if (process.platform === 'linux' && process.type === 'renderer') {
|
||||
// On Linux we could not access clipboard in renderer process.
|
||||
module.exports = require('electron').remote.clipboard
|
||||
const { getRemoteForUsage } = require('@electron/internal/renderer/remote')
|
||||
module.exports = getRemoteForUsage('clipboard').clipboard
|
||||
} else {
|
||||
const clipboard = process.atomBinding('clipboard')
|
||||
|
||||
// Read/write to find pasteboard over IPC since only main process is notified
|
||||
// of changes
|
||||
if (process.platform === 'darwin' && process.type === 'renderer') {
|
||||
clipboard.readFindText = require('electron').remote.clipboard.readFindText
|
||||
clipboard.writeFindText = require('electron').remote.clipboard.writeFindText
|
||||
const ipcRenderer = require('@electron/internal/renderer/ipc-renderer-internal')
|
||||
const errorUtils = require('@electron/internal/common/error-utils')
|
||||
|
||||
const invoke = function (command, ...args) {
|
||||
const [ error, result ] = ipcRenderer.sendSync(command, ...args)
|
||||
|
||||
if (error) {
|
||||
throw errorUtils.deserialize(error)
|
||||
} else {
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
clipboard.readFindText = (...args) => invoke('ELECTRON_BROWSER_CLIPBOARD_READ_FIND_TEXT', ...args)
|
||||
clipboard.writeFindText = (...args) => invoke('ELECTRON_BROWSER_CLIPBOARD_WRITE_FIND_TEXT', ...args)
|
||||
}
|
||||
|
||||
module.exports = clipboard
|
||||
|
||||
@@ -292,20 +292,6 @@
|
||||
process.nextTick(() => fs.lstat(pathArgument, callback))
|
||||
}
|
||||
|
||||
const { statSyncNoException } = fs
|
||||
fs.statSyncNoException = pathArgument => {
|
||||
const { isAsar, asarPath, filePath } = splitPath(pathArgument)
|
||||
if (!isAsar) return statSyncNoException(pathArgument)
|
||||
|
||||
const archive = getOrCreateArchive(asarPath)
|
||||
if (!archive) return false
|
||||
|
||||
const stats = archive.stat(filePath)
|
||||
if (!stats) return false
|
||||
|
||||
return asarStatsToFsStats(stats)
|
||||
}
|
||||
|
||||
const { realpathSync } = fs
|
||||
fs.realpathSync = function (pathArgument) {
|
||||
const { isAsar, asarPath, filePath } = splitPath(pathArgument)
|
||||
|
||||
@@ -58,6 +58,7 @@ class CrashReporter {
|
||||
|
||||
this.productName = ret.productName
|
||||
this.crashesDirectory = ret.crashesDirectory
|
||||
this.crashServicePid = ret.crashServicePid
|
||||
|
||||
if (extra == null) extra = {}
|
||||
if (extra._productName == null) extra._productName = ret.productName
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
'use strict'
|
||||
|
||||
const features = process.atomBinding('features')
|
||||
const v8Util = process.atomBinding('v8_util')
|
||||
|
||||
const enableRemoteModule = v8Util.getHiddenValue(global, 'enableRemoteModule')
|
||||
|
||||
// Renderer side modules, please sort alphabetically.
|
||||
// A module is `enabled` if there is no explicit condition defined.
|
||||
@@ -11,8 +14,8 @@ module.exports = [
|
||||
file: 'desktop-capturer',
|
||||
enabled: features.isDesktopCapturerEnabled()
|
||||
},
|
||||
{ name: 'ipcRenderer', file: 'ipc-renderer', enabled: true },
|
||||
{ name: 'remote', file: 'remote', enabled: true },
|
||||
{ name: 'screen', file: 'screen', enabled: true },
|
||||
{ name: 'webFrame', file: 'web-frame', enabled: true }
|
||||
{ name: 'ipcRenderer', file: 'ipc-renderer' },
|
||||
{ name: 'remote', file: 'remote', enabled: enableRemoteModule },
|
||||
{ name: 'screen', file: 'screen' },
|
||||
{ name: 'webFrame', file: 'web-frame' }
|
||||
]
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use strict'
|
||||
|
||||
module.exports = require('electron').remote.screen
|
||||
const { getRemoteForUsage } = require('@electron/internal/renderer/remote')
|
||||
module.exports = getRemoteForUsage('screen').screen
|
||||
|
||||
@@ -5,8 +5,7 @@ window.onload = function () {
|
||||
window.InspectorFrontendHost.showContextMenuAtPoint = createMenu
|
||||
|
||||
// Use dialog API to override file chooser dialog.
|
||||
// Note: It will be moved to UI after Chrome 57.
|
||||
window.Bindings.createFileSelectorElement = createFileSelectorElement
|
||||
window.UI.createFileSelectorElement = createFileSelectorElement
|
||||
}
|
||||
|
||||
window.confirm = function (message, title) {
|
||||
|
||||
10
lib/renderer/remote.js
Normal file
10
lib/renderer/remote.js
Normal file
@@ -0,0 +1,10 @@
|
||||
'use strict'
|
||||
|
||||
const { remote } = require('electron')
|
||||
|
||||
exports.getRemoteForUsage = function (usage) {
|
||||
if (!remote) {
|
||||
throw new Error(`${usage} requires remote, which is not enabled`)
|
||||
}
|
||||
return remote
|
||||
}
|
||||
@@ -248,6 +248,20 @@ class WebPreferencesAttribute extends WebViewAttribute {
|
||||
}
|
||||
}
|
||||
|
||||
class EnableRemoteModuleAttribute extends WebViewAttribute {
|
||||
constructor (webViewImpl) {
|
||||
super(webViewConstants.ATTRIBUTE_ENABLEREMOTEMODULE, webViewImpl)
|
||||
}
|
||||
|
||||
getValue () {
|
||||
return this.webViewImpl.webviewNode.getAttribute(this.name) !== 'false'
|
||||
}
|
||||
|
||||
setValue (value) {
|
||||
this.webViewImpl.webviewNode.setAttribute(this.name, value ? 'true' : 'false')
|
||||
}
|
||||
}
|
||||
|
||||
// Sets up all of the webview attributes.
|
||||
WebViewImpl.prototype.setupWebViewAttributes = function () {
|
||||
this.attributes = {}
|
||||
@@ -259,6 +273,7 @@ WebViewImpl.prototype.setupWebViewAttributes = function () {
|
||||
this.attributes[webViewConstants.ATTRIBUTE_PLUGINS] = new BooleanAttribute(webViewConstants.ATTRIBUTE_PLUGINS, this)
|
||||
this.attributes[webViewConstants.ATTRIBUTE_DISABLEWEBSECURITY] = new BooleanAttribute(webViewConstants.ATTRIBUTE_DISABLEWEBSECURITY, this)
|
||||
this.attributes[webViewConstants.ATTRIBUTE_ALLOWPOPUPS] = new BooleanAttribute(webViewConstants.ATTRIBUTE_ALLOWPOPUPS, this)
|
||||
this.attributes[webViewConstants.ATTRIBUTE_ENABLEREMOTEMODULE] = new EnableRemoteModuleAttribute(this)
|
||||
this.attributes[webViewConstants.ATTRIBUTE_PRELOAD] = new PreloadAttribute(this)
|
||||
this.attributes[webViewConstants.ATTRIBUTE_BLINKFEATURES] = new BlinkFeaturesAttribute(this)
|
||||
this.attributes[webViewConstants.ATTRIBUTE_DISABLEBLINKFEATURES] = new DisableBlinkFeaturesAttribute(this)
|
||||
|
||||
@@ -7,6 +7,7 @@ module.exports = {
|
||||
ATTRIBUTE_SRC: 'src',
|
||||
ATTRIBUTE_HTTPREFERRER: 'httpreferrer',
|
||||
ATTRIBUTE_NODEINTEGRATION: 'nodeintegration',
|
||||
ATTRIBUTE_ENABLEREMOTEMODULE: 'enableremotemodule',
|
||||
ATTRIBUTE_PLUGINS: 'plugins',
|
||||
ATTRIBUTE_DISABLEWEBSECURITY: 'disablewebsecurity',
|
||||
ATTRIBUTE_ALLOWPOPUPS: 'allowpopups',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
'use strict'
|
||||
|
||||
const { remote, webFrame } = require('electron')
|
||||
const { webFrame } = require('electron')
|
||||
|
||||
const v8Util = process.atomBinding('v8_util')
|
||||
const ipcRenderer = require('@electron/internal/renderer/ipc-renderer-internal')
|
||||
@@ -47,6 +47,7 @@ class WebViewImpl {
|
||||
createInternalElement () {
|
||||
const iframeElement = document.createElement('iframe')
|
||||
iframeElement.style.flex = '1 1 auto'
|
||||
iframeElement.style.width = '100%'
|
||||
iframeElement.style.border = '0'
|
||||
v8Util.setHiddenValue(iframeElement, 'internal', this)
|
||||
return iframeElement
|
||||
@@ -337,6 +338,8 @@ const registerWebViewElement = function () {
|
||||
|
||||
// WebContents associated with this webview.
|
||||
proto.getWebContents = function () {
|
||||
const { getRemoteForUsage } = require('@electron/internal/renderer/remote')
|
||||
const remote = getRemoteForUsage('getWebContents()')
|
||||
const internal = v8Util.getHiddenValue(this, 'internal')
|
||||
if (!internal.guestInstanceId) {
|
||||
internal.createGuestSync()
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use strict'
|
||||
|
||||
module.exports = require('electron').remote.require('child_process')
|
||||
const { getRemoteForUsage } = require('@electron/internal/renderer/remote')
|
||||
module.exports = getRemoteForUsage('child_process').require('child_process')
|
||||
|
||||
@@ -6,6 +6,7 @@ for (const {
|
||||
name,
|
||||
load,
|
||||
enabled = true,
|
||||
configurable = false,
|
||||
private: isPrivate = false
|
||||
} of moduleList) {
|
||||
if (!enabled) {
|
||||
@@ -13,6 +14,7 @@ for (const {
|
||||
}
|
||||
|
||||
Object.defineProperty(exports, name, {
|
||||
configurable,
|
||||
enumerable: !isPrivate,
|
||||
get: load
|
||||
})
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use strict'
|
||||
|
||||
module.exports = require('electron').remote.require('fs')
|
||||
const { getRemoteForUsage } = require('@electron/internal/renderer/remote')
|
||||
module.exports = getRemoteForUsage('fs').require('fs')
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use strict'
|
||||
|
||||
module.exports = require('electron').remote.require('os')
|
||||
const { getRemoteForUsage } = require('@electron/internal/renderer/remote')
|
||||
module.exports = getRemoteForUsage('os').require('os')
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use strict'
|
||||
|
||||
module.exports = require('electron').remote.require('path')
|
||||
const { getRemoteForUsage } = require('@electron/internal/renderer/remote')
|
||||
module.exports = getRemoteForUsage('path').require('path')
|
||||
|
||||
@@ -16,21 +16,28 @@ module.exports = [
|
||||
name: 'ipcRenderer',
|
||||
load: () => require('@electron/internal/renderer/api/ipc-renderer')
|
||||
},
|
||||
{
|
||||
name: 'isPromise',
|
||||
load: () => require('@electron/internal/common/api/is-promise'),
|
||||
private: true
|
||||
},
|
||||
{
|
||||
name: 'nativeImage',
|
||||
load: () => require('@electron/internal/common/api/native-image')
|
||||
},
|
||||
{
|
||||
name: 'remote',
|
||||
configurable: true, // will be configured in init.js
|
||||
load: () => require('@electron/internal/renderer/api/remote')
|
||||
},
|
||||
{
|
||||
name: 'webFrame',
|
||||
load: () => require('@electron/internal/renderer/api/web-frame')
|
||||
},
|
||||
// The internal modules, invisible unless you know their names.
|
||||
{
|
||||
name: 'deprecate',
|
||||
load: () => require('@electron/internal/common/api/deprecate'),
|
||||
private: true
|
||||
},
|
||||
{
|
||||
name: 'isPromise',
|
||||
load: () => require('@electron/internal/common/api/is-promise'),
|
||||
private: true
|
||||
}
|
||||
]
|
||||
|
||||
@@ -63,9 +63,21 @@ ipcNative.onExit = function () {
|
||||
}
|
||||
|
||||
const {
|
||||
preloadSrc, preloadError, process: processProps
|
||||
preloadSrc, preloadError, isRemoteModuleEnabled, process: processProps
|
||||
} = ipcRenderer.sendSync('ELECTRON_BROWSER_SANDBOX_LOAD')
|
||||
|
||||
const makePropertyNonConfigurable = function (object, name) {
|
||||
const descriptor = Object.getOwnPropertyDescriptor(electron, name)
|
||||
descriptor.configurable = false
|
||||
Object.defineProperty(electron, name, descriptor)
|
||||
}
|
||||
|
||||
if (isRemoteModuleEnabled) {
|
||||
makePropertyNonConfigurable(electron, 'remote')
|
||||
} else {
|
||||
delete electron.remote
|
||||
}
|
||||
|
||||
require('@electron/internal/renderer/web-frame-init')()
|
||||
|
||||
// Pass different process object to the preload script(which should not have
|
||||
|
||||
2
package-lock.json
generated
2
package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "electron",
|
||||
"version": "4.0.0-nightly.20181010",
|
||||
"version": "4.0.0-beta.5",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "electron",
|
||||
"version": "4.0.0-nightly.20181010",
|
||||
"version": "4.0.0-beta.5",
|
||||
"repository": "https://github.com/electron/electron",
|
||||
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
|
||||
"devDependencies": {
|
||||
@@ -45,7 +45,7 @@
|
||||
"check-tls": "python ./script/tls.py",
|
||||
"clang-format": "find atom/ brightray/ chromium_src/ -iname *.h -o -iname *.cc -o -iname *.mm | xargs clang-format -i",
|
||||
"lint": "node ./script/lint.js && npm run lint:clang-format && npm run lint:docs",
|
||||
"lint:js": ".node /script/lint.js --js",
|
||||
"lint:js": "node ./script/lint.js --js",
|
||||
"lint:clang-format": "python script/run-clang-format.py -r -c atom/ chromium_src/ brightray/ || (echo \"\\nCode not formatted correctly.\" && exit 1)",
|
||||
"lint:cpp": "node ./script/lint.js --cc",
|
||||
"lint:py": "node ./script/lint.js --py",
|
||||
|
||||
@@ -491,3 +491,12 @@ patches:
|
||||
dylib currently fails to resolve Squirrel.framework on OSX, we need to fix
|
||||
this but it is not a blocker for releasing Electron. This patch removes
|
||||
the hard fail on dylib resolve failure from dump_syms
|
||||
-
|
||||
author: zcbenz <zcbenz@gmail.com>
|
||||
file: web_preferences.patch
|
||||
description: |
|
||||
Add a node_integration field to WebPreferences so we can determine whether
|
||||
a frame has node integration in renderer process.
|
||||
|
||||
This is required by the nativeWindowOpen option, which put multiple main
|
||||
frames in one renderer process.
|
||||
|
||||
26
patches/common/chromium/web_preferences.patch
Normal file
26
patches/common/chromium/web_preferences.patch
Normal file
@@ -0,0 +1,26 @@
|
||||
diff --git a/content/public/common/common_param_traits_macros.h b/content/public/common/common_param_traits_macros.h
|
||||
index 57f03dc..7c4409e 100644
|
||||
--- a/content/public/common/common_param_traits_macros.h
|
||||
+++ b/content/public/common/common_param_traits_macros.h
|
||||
@@ -198,6 +198,7 @@ IPC_STRUCT_TRAITS_BEGIN(content::WebPreferences)
|
||||
IPC_STRUCT_TRAITS_MEMBER(animation_policy)
|
||||
IPC_STRUCT_TRAITS_MEMBER(user_gesture_required_for_presentation)
|
||||
IPC_STRUCT_TRAITS_MEMBER(text_track_margin_percentage)
|
||||
+ IPC_STRUCT_TRAITS_MEMBER(node_integration)
|
||||
IPC_STRUCT_TRAITS_MEMBER(save_previous_document_resources)
|
||||
IPC_STRUCT_TRAITS_MEMBER(text_autosizing_enabled)
|
||||
IPC_STRUCT_TRAITS_MEMBER(double_tap_to_zoom_enabled)
|
||||
diff --git a/content/public/common/web_preferences.h b/content/public/common/web_preferences.h
|
||||
index 78cbf5f..b33ac28 100644
|
||||
--- a/content/public/common/web_preferences.h
|
||||
+++ b/content/public/common/web_preferences.h
|
||||
@@ -222,6 +222,9 @@ struct CONTENT_EXPORT WebPreferences {
|
||||
// Cues will not be placed in this margin area.
|
||||
float text_track_margin_percentage;
|
||||
|
||||
+ // Electron: Whether the frame has node integration.
|
||||
+ bool node_integration = false;
|
||||
+
|
||||
bool immersive_mode_enabled;
|
||||
|
||||
bool text_autosizing_enabled;
|
||||
@@ -177,7 +177,8 @@ async function buildVSTS (targetBranch, options) {
|
||||
async function callVSTSBuild (build, targetBranch, environmentVariables) {
|
||||
const buildBody = {
|
||||
definition: build,
|
||||
sourceBranch: targetBranch
|
||||
sourceBranch: targetBranch,
|
||||
priority: 'high'
|
||||
}
|
||||
if (Object.keys(environmentVariables).length !== 0) {
|
||||
buildBody.parameters = JSON.stringify(environmentVariables)
|
||||
|
||||
@@ -78,8 +78,7 @@ def generate_posix_symbols(binary, source_root, build_dir, destination):
|
||||
def parse_args():
|
||||
parser = argparse.ArgumentParser(description='Create breakpad symbols')
|
||||
parser.add_argument('-b', '--build-dir',
|
||||
help='Path to an Electron build folder. \
|
||||
Relative to the --source-root.',
|
||||
help='Path to an Electron build folder.',
|
||||
default=RELEASE_PATH,
|
||||
required=False)
|
||||
parser.add_argument('-d', '--destination',
|
||||
|
||||
8
script/release-artifact-cleanup.js
Normal file → Executable file
8
script/release-artifact-cleanup.js
Normal file → Executable file
@@ -3,7 +3,7 @@
|
||||
if (!process.env.CI) require('dotenv-safe').load()
|
||||
require('colors')
|
||||
const args = require('minimist')(process.argv.slice(2), {
|
||||
boolean: ['tag']
|
||||
string: ['tag']
|
||||
})
|
||||
const { execSync } = require('child_process')
|
||||
const { GitProcess } = require('dugite')
|
||||
@@ -20,7 +20,7 @@ github.authenticate({
|
||||
})
|
||||
|
||||
function getLastBumpCommit (tag) {
|
||||
const data = execSync(`git log -n1 --grep "Bump ${tag}" --format="format:{hash: %H, message: '%s'}"`)
|
||||
const data = execSync(`git log -n1 --grep "Bump ${tag}" --format='format:{"hash": "%H", "message": "%s"}'`).toString()
|
||||
return JSON.parse(data)
|
||||
}
|
||||
|
||||
@@ -90,9 +90,9 @@ async function deleteTag (tag, targetRepo) {
|
||||
|
||||
async function cleanReleaseArtifacts () {
|
||||
const tag = args.tag
|
||||
const lastBumpCommit = getLastBumpCommit().message
|
||||
const isNightly = args.tag.includes('nightly')
|
||||
|
||||
if (lastBumpCommit.indexOf('nightly' > 0)) {
|
||||
if (isNightly) {
|
||||
await deleteDraft(tag, 'nightlies')
|
||||
await deleteTag(tag, 'nightlies')
|
||||
} else {
|
||||
|
||||
@@ -29,9 +29,11 @@ def main():
|
||||
for pdb in PDB_LIST:
|
||||
run_symstore(pdb, SYMBOLS_DIR, PRODUCT_NAME)
|
||||
files = glob.glob(SYMBOLS_DIR + '/*.pdb/*/*.pdb')
|
||||
files = [f.lower() for f in files]
|
||||
else:
|
||||
files = glob.glob(SYMBOLS_DIR + '/*/*/*.sym')
|
||||
# The symbol server needs lowercase paths, it will fail otherwise
|
||||
# So lowercase all the file paths here
|
||||
files = [f.lower() for f in files]
|
||||
|
||||
bucket, access_key, secret_key = s3_config()
|
||||
upload_symbols(bucket, access_key, secret_key, files)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import argparse
|
||||
import glob
|
||||
import os
|
||||
import sys
|
||||
@@ -17,29 +18,38 @@ def main():
|
||||
if get_target_arch() == 'mips64el':
|
||||
return
|
||||
|
||||
args = parse_args()
|
||||
dist_name = 'symbols.zip'
|
||||
zip_file = os.path.join(OUT_DIR, dist_name)
|
||||
zip_file = os.path.join(args.build_dir, dist_name)
|
||||
licenses = ['LICENSE', 'LICENSES.chromium.html', 'version']
|
||||
|
||||
with scoped_cwd(OUT_DIR):
|
||||
with scoped_cwd(args.build_dir):
|
||||
dirs = ['{0}.breakpad.syms'.format(PROJECT_NAME)]
|
||||
print('Making symbol zip: ' + zip_file)
|
||||
make_zip(zip_file, licenses, dirs)
|
||||
|
||||
if PLATFORM == 'darwin':
|
||||
dsym_name = 'dsym.zip'
|
||||
with scoped_cwd(OUT_DIR):
|
||||
with scoped_cwd(args.build_dir):
|
||||
dsyms = glob.glob('*.dSYM')
|
||||
dsym_zip_file = os.path.join(OUT_DIR, dsym_name)
|
||||
dsym_zip_file = os.path.join(args.build_dir, dsym_name)
|
||||
print('Making dsym zip: ' + dsym_zip_file)
|
||||
make_zip(dsym_zip_file, licenses, dsyms)
|
||||
elif PLATFORM == 'win32':
|
||||
pdb_name = 'pdb.zip'
|
||||
with scoped_cwd(OUT_DIR):
|
||||
with scoped_cwd(args.build_dir):
|
||||
pdbs = glob.glob('*.pdb')
|
||||
pdb_zip_file = os.path.join(OUT_DIR, pdb_name)
|
||||
pdb_zip_file = os.path.join(args.build_dir, pdb_name)
|
||||
print('Making pdb zip: ' + pdb_zip_file)
|
||||
make_zip(pdb_zip_file, pdbs + licenses, [])
|
||||
|
||||
def parse_args():
|
||||
parser = argparse.ArgumentParser(description='Zip symbols')
|
||||
parser.add_argument('-b', '--build-dir',
|
||||
help='Path to an Electron build folder.',
|
||||
default=OUT_DIR,
|
||||
required=False)
|
||||
return parser.parse_args()
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
sys.exit(main())
|
||||
|
||||
@@ -432,31 +432,13 @@ describe('app module', () => {
|
||||
app.setLoginItemSettings({ openAtLogin: false, path: updateExe, args: processStartArgs })
|
||||
})
|
||||
|
||||
it('returns the login item status of the app', done => {
|
||||
it('sets and returns the app as a login item', done => {
|
||||
app.setLoginItemSettings({ openAtLogin: true })
|
||||
expect(app.getLoginItemSettings()).to.deep.equal({
|
||||
openAtLogin: true,
|
||||
openAsHidden: false,
|
||||
wasOpenedAtLogin: false,
|
||||
wasOpenedAsHidden: false,
|
||||
restoreState: false
|
||||
})
|
||||
|
||||
app.setLoginItemSettings({ openAtLogin: true, openAsHidden: true })
|
||||
expect(app.getLoginItemSettings()).to.deep.equal({
|
||||
openAtLogin: true,
|
||||
openAsHidden: process.platform === 'darwin' && !process.mas, // Only available on macOS
|
||||
wasOpenedAtLogin: false,
|
||||
wasOpenedAsHidden: false,
|
||||
restoreState: false
|
||||
})
|
||||
|
||||
app.setLoginItemSettings({})
|
||||
// Wait because login item settings are not applied immediately in MAS build
|
||||
const delay = process.mas ? 100 : 0
|
||||
const delay = process.mas ? 250 : 0
|
||||
setTimeout(() => {
|
||||
expect(app.getLoginItemSettings()).to.deep.equal({
|
||||
openAtLogin: false,
|
||||
openAtLogin: true,
|
||||
openAsHidden: false,
|
||||
wasOpenedAtLogin: false,
|
||||
wasOpenedAsHidden: false,
|
||||
@@ -466,6 +448,37 @@ describe('app module', () => {
|
||||
}, delay)
|
||||
})
|
||||
|
||||
it('adds a login item that loads in hidden mode', done => {
|
||||
app.setLoginItemSettings({ openAtLogin: true, openAsHidden: true })
|
||||
// Wait because login item settings are not applied immediately in MAS build
|
||||
const delay = process.mas ? 250 : 0
|
||||
setTimeout(() => {
|
||||
expect(app.getLoginItemSettings()).to.deep.equal({
|
||||
openAtLogin: true,
|
||||
openAsHidden: process.platform === 'darwin' && !process.mas, // Only available on macOS
|
||||
wasOpenedAtLogin: false,
|
||||
wasOpenedAsHidden: false,
|
||||
restoreState: false
|
||||
})
|
||||
done()
|
||||
}, delay)
|
||||
})
|
||||
|
||||
it('correctly sets and unsets the LoginItem as hidden', function () {
|
||||
if (process.platform !== 'darwin' || process.mas) this.skip()
|
||||
|
||||
expect(app.getLoginItemSettings().openAtLogin).to.be.false()
|
||||
expect(app.getLoginItemSettings().openAsHidden).to.be.false()
|
||||
|
||||
app.setLoginItemSettings({ openAtLogin: true, openAsHidden: true })
|
||||
expect(app.getLoginItemSettings().openAtLogin).to.be.true()
|
||||
expect(app.getLoginItemSettings().openAsHidden).to.be.true()
|
||||
|
||||
app.setLoginItemSettings({ openAtLogin: true, openAsHidden: false })
|
||||
expect(app.getLoginItemSettings().openAtLogin).to.be.true()
|
||||
expect(app.getLoginItemSettings().openAsHidden).to.be.false()
|
||||
})
|
||||
|
||||
it('allows you to pass a custom executable and arguments', function () {
|
||||
if (process.platform !== 'win32') {
|
||||
// FIXME(alexeykuzmin): Skip the test.
|
||||
@@ -844,10 +857,9 @@ describe('app module', () => {
|
||||
await verifyBasicGPUInfo(gpuInfo)
|
||||
})
|
||||
|
||||
// FIXME: this broke with the M69 upgrade.
|
||||
xit('succeeds with complete GPUInfo', async () => {
|
||||
it('succeeds with complete GPUInfo', async () => {
|
||||
const completeInfo = await getGPUInfo('complete')
|
||||
if (process.platform === 'linux' || process.platform === 'darwin') {
|
||||
if (process.platform === 'linux') {
|
||||
// For linux and macOS complete info is same as basic info
|
||||
await verifyBasicGPUInfo(completeInfo)
|
||||
const basicInfo = await getGPUInfo('basic')
|
||||
@@ -864,11 +876,8 @@ describe('app module', () => {
|
||||
|
||||
it('fails for invalid info_type', () => {
|
||||
const invalidType = 'invalid'
|
||||
const errorMessage =
|
||||
`app.getGPUInfo() didn't fail for the "${invalidType}" info type`
|
||||
return app.getGPUInfo(invalidType).then(
|
||||
() => Promise.reject(new Error(errorMessage)),
|
||||
() => Promise.resolve())
|
||||
const expectedErrorMessage = "Invalid info type. Use 'basic' or 'complete'"
|
||||
return expect(app.getGPUInfo(invalidType)).to.eventually.be.rejectedWith(expectedErrorMessage)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -1396,6 +1396,46 @@ describe('BrowserWindow module', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('"enableRemoteModule" option', () => {
|
||||
const generateSpecs = (description, sandbox) => {
|
||||
describe(description, () => {
|
||||
const preload = path.join(fixtures, 'module', 'preload-remote.js')
|
||||
|
||||
it('enables the remote module by default', async () => {
|
||||
const w = await openTheWindow({
|
||||
show: false,
|
||||
webPreferences: {
|
||||
nodeIntegration: false,
|
||||
preload,
|
||||
sandbox
|
||||
}
|
||||
})
|
||||
w.loadFile(path.join(fixtures, 'api', 'blank.html'))
|
||||
const [, remote] = await emittedOnce(ipcMain, 'remote')
|
||||
expect(remote).to.equal('object')
|
||||
})
|
||||
|
||||
it('disables the remote module when false', async () => {
|
||||
const w = await openTheWindow({
|
||||
show: false,
|
||||
webPreferences: {
|
||||
nodeIntegration: false,
|
||||
preload,
|
||||
sandbox,
|
||||
enableRemoteModule: false
|
||||
}
|
||||
})
|
||||
w.loadFile(path.join(fixtures, 'api', 'blank.html'))
|
||||
const [, remote] = await emittedOnce(ipcMain, 'remote')
|
||||
expect(remote).to.equal('undefined')
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
generateSpecs('without sandbox', false)
|
||||
generateSpecs('with sandbox', true)
|
||||
})
|
||||
|
||||
describe('"sandbox" option', () => {
|
||||
function waitForEvents (emitter, events, callback) {
|
||||
let count = events.length
|
||||
@@ -1515,41 +1555,42 @@ describe('BrowserWindow module', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('should open windows in another domain with cross-scripting disabled', (done) => {
|
||||
w.destroy()
|
||||
w = new BrowserWindow({
|
||||
it('should open windows in another domain with cross-scripting disabled', async () => {
|
||||
const w = await openTheWindow({
|
||||
show: false,
|
||||
webPreferences: {
|
||||
sandbox: true,
|
||||
preload: preload
|
||||
preload
|
||||
}
|
||||
})
|
||||
|
||||
ipcRenderer.send('set-web-preferences-on-next-new-window', w.webContents.id, 'preload', preload)
|
||||
let popupWindow
|
||||
w.loadFile(path.join(fixtures, 'api', 'sandbox.html'), { search: 'window-open-external' })
|
||||
w.webContents.once('new-window', (e, url, frameName, disposition, options) => {
|
||||
assert.strictEqual(url, 'http://www.google.com/#q=electron')
|
||||
assert.strictEqual(options.width, 505)
|
||||
assert.strictEqual(options.height, 605)
|
||||
ipcMain.once('child-loaded', function (event, openerIsNull, html) {
|
||||
assert(openerIsNull)
|
||||
assert.strictEqual(html, '<h1>http://www.google.com/#q=electron</h1>')
|
||||
ipcMain.once('answer', function (event, exceptionMessage) {
|
||||
assert(/Blocked a frame with origin/.test(exceptionMessage))
|
||||
const expectedPopupUrl = 'http://www.google.com/#q=electron' // Set in the "sandbox.html".
|
||||
|
||||
// FIXME this popup window should be closed in sandbox.html
|
||||
closeWindow(popupWindow, { assertSingleWindow: false }).then(() => {
|
||||
popupWindow = null
|
||||
done()
|
||||
})
|
||||
})
|
||||
w.webContents.send('child-loaded')
|
||||
})
|
||||
})
|
||||
// The page is going to open a popup that it won't be able to close.
|
||||
// We have to close it from here later.
|
||||
// XXX(alexeykuzmin): It will leak if the test fails too soon.
|
||||
const [, popupWindow] = await emittedOnce(app, 'browser-window-created')
|
||||
|
||||
app.once('browser-window-created', function (event, window) {
|
||||
popupWindow = window
|
||||
})
|
||||
// Wait for a message from the popup's preload script.
|
||||
const [, openerIsNull, html, locationHref] = await emittedOnce(ipcMain, 'child-loaded')
|
||||
expect(openerIsNull).to.be.true('window.opener is not null')
|
||||
expect(html).to.equal(`<h1>${expectedPopupUrl}</h1>`,
|
||||
'looks like a http: request has not been intercepted locally')
|
||||
expect(locationHref).to.equal(expectedPopupUrl)
|
||||
|
||||
// Ask the page to access the popup.
|
||||
w.webContents.send('touch-the-popup')
|
||||
const [, exceptionMessage] = await emittedOnce(ipcMain, 'answer')
|
||||
|
||||
// We don't need the popup anymore, and its parent page can't close it,
|
||||
// so let's close it from here before we run any checks.
|
||||
await closeWindow(popupWindow, { assertSingleWindow: false })
|
||||
|
||||
expect(exceptionMessage).to.be.a('string',
|
||||
`child's .document is accessible from its parent window`)
|
||||
expect(exceptionMessage).to.match(/^Blocked a frame with origin/)
|
||||
})
|
||||
|
||||
it('should inherit the sandbox setting in opened windows', (done) => {
|
||||
@@ -2974,7 +3015,7 @@ describe('BrowserWindow module', () => {
|
||||
c.show()
|
||||
assert.strictEqual(w.isEnabled(), false)
|
||||
})
|
||||
it('enables parent window when closed', (done) => {
|
||||
it('re-enables an enabled parent window when closed', (done) => {
|
||||
c.once('closed', () => {
|
||||
assert.strictEqual(w.isEnabled(), true)
|
||||
done()
|
||||
@@ -2982,6 +3023,15 @@ describe('BrowserWindow module', () => {
|
||||
c.show()
|
||||
c.close()
|
||||
})
|
||||
it('does not re-enable a disabled parent window when closed', (done) => {
|
||||
c.once('closed', () => {
|
||||
assert.strictEqual(w.isEnabled(), false)
|
||||
done()
|
||||
})
|
||||
w.setEnabled(false)
|
||||
c.show()
|
||||
c.close()
|
||||
})
|
||||
it('disables parent window recursively', () => {
|
||||
const c2 = new BrowserWindow({ show: false, parent: w, modal: true })
|
||||
c.show()
|
||||
|
||||
@@ -195,6 +195,11 @@ describe('crashReporter module', () => {
|
||||
preload: path.join(fixtures, 'module', 'preload-sandbox.js')
|
||||
}
|
||||
})
|
||||
generateSpecs('with remote module disabled', {
|
||||
webPreferences: {
|
||||
enableRemoteModule: false
|
||||
}
|
||||
})
|
||||
|
||||
describe('getProductName', () => {
|
||||
it('returns the product name if one is specified', () => {
|
||||
|
||||
@@ -591,6 +591,26 @@ describe('Menu module', () => {
|
||||
const fsc = menu.getMenuItemById('fullScreen')
|
||||
expect(menu.items[0].submenu.items[0]).to.equal(fsc)
|
||||
})
|
||||
|
||||
it('should return the separator with the given id', () => {
|
||||
const menu = Menu.buildFromTemplate([
|
||||
{
|
||||
label: 'Item 1',
|
||||
id: 'item_1'
|
||||
},
|
||||
{
|
||||
id: 'separator',
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Item 2',
|
||||
id: 'item_2'
|
||||
}
|
||||
])
|
||||
const separator = menu.getMenuItemById('separator')
|
||||
expect(separator).to.be.an('object')
|
||||
expect(separator).to.equal(menu.items[1])
|
||||
})
|
||||
})
|
||||
|
||||
describe('Menu.insert', () => {
|
||||
|
||||
@@ -125,9 +125,7 @@ describe('webContents module', () => {
|
||||
})
|
||||
})
|
||||
|
||||
// FIXME: this is broken on mac in the M69 upgrade, fix & re-enable before
|
||||
// release
|
||||
xdescribe('isCurrentlyAudible() API', () => {
|
||||
describe('isCurrentlyAudible() API', () => {
|
||||
it('returns whether audio is playing', async () => {
|
||||
const webContents = remote.getCurrentWebContents()
|
||||
const context = new window.AudioContext()
|
||||
|
||||
2
spec/fixtures/api/crash-restart.html
vendored
2
spec/fixtures/api/crash-restart.html
vendored
@@ -19,7 +19,7 @@ crashReporter.start({
|
||||
})
|
||||
|
||||
if (process.platform === 'win32') {
|
||||
ipcRenderer.sendSync('crash-service-pid', crashReporter._crashServiceProcess.pid)
|
||||
ipcRenderer.sendSync('crash-service-pid', crashReporter.crashServicePid)
|
||||
}
|
||||
|
||||
setImmediate(() => {
|
||||
|
||||
2
spec/fixtures/api/crash.html
vendored
2
spec/fixtures/api/crash.html
vendored
@@ -20,7 +20,7 @@
|
||||
})
|
||||
|
||||
if (process.platform === 'win32') {
|
||||
ipcRenderer.sendSync('crash-service-pid', crashReporter._crashServiceProcess.pid)
|
||||
ipcRenderer.sendSync('crash-service-pid', crashReporter.crashServicePid)
|
||||
}
|
||||
|
||||
if (!uploadToServer) {
|
||||
|
||||
10
spec/fixtures/api/sandbox.html
vendored
10
spec/fixtures/api/sandbox.html
vendored
@@ -81,12 +81,14 @@
|
||||
},
|
||||
'window-open-external': () => {
|
||||
addEventListener('load', () => {
|
||||
ipcRenderer.once('child-loaded', (e) => {
|
||||
ipcRenderer.once('touch-the-popup', () => {
|
||||
let errorMessage = null
|
||||
try {
|
||||
let childDoc = popup.document
|
||||
} catch (e) {
|
||||
ipcRenderer.send('answer', e.message)
|
||||
const childDoc = popup.document
|
||||
} catch (error) {
|
||||
errorMessage = error.message
|
||||
}
|
||||
ipcRenderer.send('answer', errorMessage)
|
||||
})
|
||||
popup = open('http://www.google.com/#q=electron', '', 'top=65,left=55,width=505,height=605')
|
||||
})
|
||||
|
||||
8
spec/fixtures/module/preload-disable-remote.js
vendored
Normal file
8
spec/fixtures/module/preload-disable-remote.js
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
setImmediate(function () {
|
||||
try {
|
||||
const { remote } = require('electron')
|
||||
console.log(JSON.stringify(typeof remote))
|
||||
} catch (e) {
|
||||
console.log(e.message)
|
||||
}
|
||||
})
|
||||
5
spec/fixtures/module/preload-remote.js
vendored
Normal file
5
spec/fixtures/module/preload-remote.js
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
const { ipcRenderer, remote } = require('electron')
|
||||
|
||||
window.onload = function () {
|
||||
ipcRenderer.send('remote', typeof remote)
|
||||
}
|
||||
2
spec/fixtures/module/preload-sandbox.js
vendored
2
spec/fixtures/module/preload-sandbox.js
vendored
@@ -23,7 +23,7 @@
|
||||
}
|
||||
} else if (location.href !== 'about:blank') {
|
||||
addEventListener('DOMContentLoaded', () => {
|
||||
ipcRenderer.send('child-loaded', window.opener == null, document.body.innerHTML)
|
||||
ipcRenderer.send('child-loaded', window.opener == null, document.body.innerHTML, location.href)
|
||||
}, false)
|
||||
}
|
||||
})()
|
||||
|
||||
6
spec/fixtures/module/runas-renamed.js
vendored
Normal file
6
spec/fixtures/module/runas-renamed.js
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
try {
|
||||
require('runas')
|
||||
} catch (e) {
|
||||
process.exit(1)
|
||||
}
|
||||
process.exit(0)
|
||||
@@ -1,6 +1,7 @@
|
||||
const assert = require('assert')
|
||||
const Module = require('module')
|
||||
const path = require('path')
|
||||
const fs = require('fs')
|
||||
const { remote } = require('electron')
|
||||
const { BrowserWindow } = remote
|
||||
const { closeWindow } = require('./window-helpers')
|
||||
@@ -24,6 +25,22 @@ describe('modules support', () => {
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
if (process.platform === 'win32') {
|
||||
it('can be required if electron.exe is renamed', () => {
|
||||
const { execPath } = remote.process
|
||||
const testExecPath = path.join(path.dirname(execPath), 'test.exe')
|
||||
fs.copyFileSync(execPath, testExecPath)
|
||||
try {
|
||||
const runasFixture = path.join(fixtures, 'module', 'runas-renamed.js')
|
||||
assert.ok(fs.existsSync(runasFixture))
|
||||
const child = require('child_process').spawnSync(testExecPath, [runasFixture])
|
||||
assert.strictEqual(child.status, 0)
|
||||
} finally {
|
||||
fs.unlinkSync(testExecPath)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
// TODO(alexeykuzmin): Disabled during the Chromium 62 (Node.js 9) upgrade.
|
||||
|
||||
@@ -68,7 +68,7 @@ describe('security warnings', () => {
|
||||
w.loadURL(`http://127.0.0.1:8881/base-page-security.html`)
|
||||
})
|
||||
|
||||
const generateSpecs = (description, sandbox) => {
|
||||
const generateSpecs = (description, webPreferences) => {
|
||||
describe(description, () => {
|
||||
it('should warn about disabled webSecurity', (done) => {
|
||||
w = new BrowserWindow({
|
||||
@@ -76,7 +76,7 @@ describe('security warnings', () => {
|
||||
webPreferences: {
|
||||
webSecurity: false,
|
||||
nodeIntegration: false,
|
||||
sandbox
|
||||
...webPreferences
|
||||
}
|
||||
})
|
||||
w.webContents.once('console-message', (e, level, message) => {
|
||||
@@ -92,7 +92,7 @@ describe('security warnings', () => {
|
||||
show: false,
|
||||
webPreferences: {
|
||||
nodeIntegration: false,
|
||||
sandbox
|
||||
...webPreferences
|
||||
}
|
||||
})
|
||||
|
||||
@@ -111,7 +111,7 @@ describe('security warnings', () => {
|
||||
webPreferences: {
|
||||
allowRunningInsecureContent: true,
|
||||
nodeIntegration: false,
|
||||
sandbox
|
||||
...webPreferences
|
||||
}
|
||||
})
|
||||
w.webContents.once('console-message', (e, level, message) => {
|
||||
@@ -128,7 +128,7 @@ describe('security warnings', () => {
|
||||
webPreferences: {
|
||||
experimentalFeatures: true,
|
||||
nodeIntegration: false,
|
||||
sandbox
|
||||
...webPreferences
|
||||
}
|
||||
})
|
||||
w.webContents.once('console-message', (e, level, message) => {
|
||||
@@ -145,7 +145,7 @@ describe('security warnings', () => {
|
||||
webPreferences: {
|
||||
enableBlinkFeatures: ['my-cool-feature'],
|
||||
nodeIntegration: false,
|
||||
sandbox
|
||||
...webPreferences
|
||||
}
|
||||
})
|
||||
w.webContents.once('console-message', (e, level, message) => {
|
||||
@@ -161,7 +161,7 @@ describe('security warnings', () => {
|
||||
show: false,
|
||||
webPreferences: {
|
||||
nodeIntegration: false,
|
||||
sandbox
|
||||
...webPreferences
|
||||
}
|
||||
})
|
||||
w.webContents.once('console-message', (e, level, message) => {
|
||||
@@ -177,7 +177,7 @@ describe('security warnings', () => {
|
||||
show: false,
|
||||
webPreferences: {
|
||||
nodeIntegration: false,
|
||||
sandbox
|
||||
...webPreferences
|
||||
}
|
||||
})
|
||||
w.webContents.once('console-message', (e, level, message) => {
|
||||
@@ -191,6 +191,7 @@ describe('security warnings', () => {
|
||||
})
|
||||
}
|
||||
|
||||
generateSpecs('without sandbox', false)
|
||||
generateSpecs('with sandbox', true)
|
||||
generateSpecs('without sandbox', {})
|
||||
generateSpecs('with sandbox', { sandbox: true })
|
||||
generateSpecs('with remote module disabled', { enableRemoteModule: false })
|
||||
})
|
||||
|
||||
@@ -219,6 +219,41 @@ describe('<webview> tag', function () {
|
||||
})
|
||||
})
|
||||
|
||||
describe('enableremotemodule attribute', () => {
|
||||
const generateSpecs = (description, sandbox) => {
|
||||
describe(description, () => {
|
||||
const preload = `${fixtures}/module/preload-disable-remote.js`
|
||||
const src = `file://${fixtures}/api/blank.html`
|
||||
|
||||
it('enables the remote module by default', async () => {
|
||||
const message = await startLoadingWebViewAndWaitForMessage(webview, {
|
||||
preload,
|
||||
src,
|
||||
sandbox
|
||||
})
|
||||
|
||||
const typeOfRemote = JSON.parse(message)
|
||||
expect(typeOfRemote).to.equal('object')
|
||||
})
|
||||
|
||||
it('disables the remote module when false', async () => {
|
||||
const message = await startLoadingWebViewAndWaitForMessage(webview, {
|
||||
preload,
|
||||
src,
|
||||
sandbox,
|
||||
enableremotemodule: false
|
||||
})
|
||||
|
||||
const typeOfRemote = JSON.parse(message)
|
||||
expect(typeOfRemote).to.equal('undefined')
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
generateSpecs('without sandbox', false)
|
||||
generateSpecs('with sandbox', true)
|
||||
})
|
||||
|
||||
describe('preload attribute', () => {
|
||||
it('loads the script before other scripts in window', async () => {
|
||||
const message = await startLoadingWebViewAndWaitForMessage(webview, {
|
||||
@@ -506,6 +541,17 @@ describe('<webview> tag', function () {
|
||||
})
|
||||
})
|
||||
|
||||
it('can disable the remote module', async () => {
|
||||
const message = await startLoadingWebViewAndWaitForMessage(webview, {
|
||||
preload: `${fixtures}/module/preload-disable-remote.js`,
|
||||
src: `file://${fixtures}/api/blank.html`,
|
||||
webpreferences: 'enableRemoteModule=no'
|
||||
})
|
||||
|
||||
const typeOfRemote = JSON.parse(message)
|
||||
expect(typeOfRemote).to.equal('undefined')
|
||||
})
|
||||
|
||||
it('can disables web security and enable nodeintegration', async () => {
|
||||
const jqueryPath = path.join(__dirname, '/static/jquery-2.0.3.min.js')
|
||||
const src = `<script src='file://${jqueryPath}'></script> <script>console.log(typeof require);</script>`
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user