mirror of
https://github.com/electron/electron.git
synced 2026-02-19 03:14:51 -05:00
Compare commits
94 Commits
fix-codesp
...
v4.0.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3846a1b663 | ||
|
|
08d80295d7 | ||
|
|
127ad9252e | ||
|
|
f43920e436 | ||
|
|
62c0f842ae | ||
|
|
acea9d1576 | ||
|
|
8e31642530 | ||
|
|
91533574c7 | ||
|
|
eef05cba6a | ||
|
|
7e63ca603d | ||
|
|
2b7f854a83 | ||
|
|
d07115e1dc | ||
|
|
c268fd872c | ||
|
|
2ac5f33cf8 | ||
|
|
deac580f1a | ||
|
|
a5fa18767a | ||
|
|
3e4d77109a | ||
|
|
081af07892 | ||
|
|
d1c48456e9 | ||
|
|
282829c076 | ||
|
|
6e759e0852 | ||
|
|
74bd220436 | ||
|
|
d16304f2fb | ||
|
|
ac1bfb2337 | ||
|
|
436b9a2ee1 | ||
|
|
9625faeede | ||
|
|
8d4573f289 | ||
|
|
041773c6bc | ||
|
|
a51ad1f956 | ||
|
|
3a4c20b154 | ||
|
|
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:
|
||||
@@ -145,6 +154,7 @@ step-install-nodejs-on-mac: &step-install-nodejs-on-mac
|
||||
if [ "`uname`" == "Darwin" ]; then
|
||||
brew update
|
||||
brew install node@10
|
||||
echo 'export PATH="/usr/local/opt/node@10/bin:$PATH"' >> $BASH_ENV
|
||||
fi
|
||||
|
||||
step-gn-gen-default: &step-gn-gen-default
|
||||
@@ -311,20 +321,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 +478,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 +501,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
|
||||
@@ -696,8 +720,10 @@ jobs:
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True'
|
||||
<<: *steps-checkout
|
||||
|
||||
linux-x64-checkout:
|
||||
linux-checkout-for-native-tests:
|
||||
<<: *machine-linux-2xlarge
|
||||
environment:
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_pyyaml=True'
|
||||
<<: *steps-checkout
|
||||
|
||||
# Layer 2: Builds.
|
||||
@@ -1199,15 +1225,15 @@ workflows:
|
||||
- master
|
||||
- *chromium-upgrade-branches
|
||||
jobs:
|
||||
- linux-x64-checkout
|
||||
- linux-checkout-for-native-tests
|
||||
|
||||
# TODO(alexeykuzmin): Enable it back.
|
||||
# Tons of crashes right now, see
|
||||
# https://circleci.com/gh/electron/electron/67463
|
||||
# - linux-x64-browsertests:
|
||||
# requires:
|
||||
# - linux-x64-checkout
|
||||
# - linux-checkout-for-native-tests
|
||||
|
||||
- linux-x64-unittests:
|
||||
requires:
|
||||
- linux-x64-checkout
|
||||
- linux-checkout-for-native-tests
|
||||
|
||||
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" ]
|
||||
|
||||
36
DEPS
36
DEPS
@@ -12,7 +12,7 @@ vars = {
|
||||
'chromium_version':
|
||||
'69.0.3497.106',
|
||||
'node_version':
|
||||
'5654c276d0497ff9a0bb0d7550b9073b2e2e7d3f',
|
||||
'4d44266b78256449dd6ae86e419e3ec07257b569',
|
||||
|
||||
'boto_version': 'f7574aa6cc2c819430c1f05e9a1a1a666ef8169b',
|
||||
'pyyaml_version': '3.12',
|
||||
@@ -24,9 +24,19 @@ 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,
|
||||
|
||||
# To allow in-house builds to checkout those manually.
|
||||
'checkout_chromium': True,
|
||||
'checkout_node': True,
|
||||
|
||||
# It's only needed to parse the native tests configurations.
|
||||
'checkout_pyyaml': False,
|
||||
|
||||
# Python "requests" module is used for releases only.
|
||||
'checkout_requests': False,
|
||||
|
||||
@@ -49,12 +59,18 @@ vars = {
|
||||
}
|
||||
|
||||
deps = {
|
||||
'src':
|
||||
(Var("chromium_git")) + '/chromium/src.git@' + (Var("chromium_version")),
|
||||
'src/third_party/electron_node':
|
||||
(Var("electron_git")) + '/node.git@' + (Var("node_version")),
|
||||
'src/electron/vendor/pyyaml':
|
||||
(Var("yaml_git")) + '/pyyaml.git@' + (Var("pyyaml_version")),
|
||||
'src': {
|
||||
'url': (Var("chromium_git")) + '/chromium/src.git@' + (Var("chromium_version")),
|
||||
'condition': 'checkout_chromium',
|
||||
},
|
||||
'src/third_party/electron_node': {
|
||||
'url': (Var("electron_git")) + '/node.git@' + (Var("node_version")),
|
||||
'condition': 'checkout_node',
|
||||
},
|
||||
'src/electron/vendor/pyyaml': {
|
||||
'url': (Var("yaml_git")) + '/pyyaml.git@' + (Var("pyyaml_version")),
|
||||
'condition': 'checkout_pyyaml',
|
||||
},
|
||||
'src/electron/vendor/boto': {
|
||||
'url': Var('boto_git') + '/boto.git' + '@' + Var('boto_version'),
|
||||
'condition': 'checkout_boto',
|
||||
@@ -68,12 +84,12 @@ deps = {
|
||||
hooks = [
|
||||
{
|
||||
'name': 'patch_chromium',
|
||||
'condition': 'checkout_chromium and apply_patches',
|
||||
'pattern': 'src/electron',
|
||||
'action': [
|
||||
'python',
|
||||
'src/electron/script/apply-patches',
|
||||
'--project-root=.',
|
||||
'--commit',
|
||||
'src/electron/script/apply_all_patches.py',
|
||||
'src/electron/patches/common/config.json',
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
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);
|
||||
|
||||
26
atom/browser/api/atom_api_event.cc
Normal file
26
atom/browser/api/atom_api_event.cc
Normal file
@@ -0,0 +1,26 @@
|
||||
// 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/api/event_emitter.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
namespace {
|
||||
|
||||
v8::Local<v8::Object> CreateWithSender(v8::Isolate* isolate,
|
||||
v8::Local<v8::Object> sender) {
|
||||
return mate::internal::CreateJSEvent(isolate, sender, nullptr, nullptr);
|
||||
}
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
mate::Dictionary dict(context->GetIsolate(), exports);
|
||||
dict.SetMethod("createWithSender", &CreateWithSender);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_event, Initialize)
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
@@ -167,7 +167,7 @@ void FinishTransactionByDate(const std::string& date) {
|
||||
std::string GetReceiptURL() {
|
||||
NSURL* receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
|
||||
if (receiptURL != nil) {
|
||||
return [[receiptURL absoluteString] UTF8String];
|
||||
return std::string([[receiptURL path] UTF8String]);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
|
||||
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_
|
||||
@@ -341,6 +341,9 @@ NativeWindowMac::NativeWindowMac(const mate::Dictionary& options,
|
||||
if (!useStandardWindow || transparent() || !has_frame()) {
|
||||
styleMask |= NSTexturedBackgroundWindowMask;
|
||||
}
|
||||
if (resizable_) {
|
||||
styleMask |= NSResizableWindowMask;
|
||||
}
|
||||
|
||||
// Create views::Widget and assign window_ with it.
|
||||
// TODO(zcbenz): Get rid of the window_ in future.
|
||||
@@ -585,13 +588,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)
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
<key>LSApplicationCategoryType</key>
|
||||
<string>public.app-category.developer-tools</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.9.0</string>
|
||||
<string>10.10.0</string>
|
||||
<key>NSMainNibFile</key>
|
||||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
|
||||
@@ -50,8 +50,8 @@ END
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 4,0,0,20181010
|
||||
PRODUCTVERSION 4,0,0,20181010
|
||||
FILEVERSION 4,0,0,7
|
||||
PRODUCTVERSION 4,0,0,7
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "atom/browser/ui/cocoa/atom_preview_item.h"
|
||||
#include "atom/browser/ui/cocoa/atom_touch_bar.h"
|
||||
#include "base/mac/mac_util.h"
|
||||
#include "ui/views/cocoa/bridged_native_widget.h"
|
||||
#include "ui/views/widget/native_widget_mac.h"
|
||||
|
||||
@implementation AtomNSWindowDelegate
|
||||
@@ -246,7 +247,10 @@
|
||||
// Clears the delegate when window is going to be closed, since EL Capitan it
|
||||
// is possible that the methods of delegate would get called after the window
|
||||
// has been closed.
|
||||
[shell_->GetNativeWindow() setDelegate:nil];
|
||||
views::BridgedNativeWidget* bridged_view =
|
||||
views::NativeWidgetMac::GetBridgeForNativeWindow(
|
||||
shell_->GetNativeWindow());
|
||||
bridged_view->OnWindowWillClose();
|
||||
}
|
||||
|
||||
- (BOOL)windowShouldClose:(id)window {
|
||||
|
||||
@@ -94,10 +94,14 @@ class FileChooserDialog {
|
||||
}
|
||||
|
||||
void SetupProperties(int properties) {
|
||||
if (properties & FILE_DIALOG_MULTI_SELECTIONS)
|
||||
gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog()), TRUE);
|
||||
if (properties & FILE_DIALOG_SHOW_HIDDEN_FILES)
|
||||
g_object_set(dialog(), "show-hidden", TRUE, NULL);
|
||||
const auto hasProp = [properties](FileDialogProperty prop) {
|
||||
return gboolean((properties & prop) != 0);
|
||||
};
|
||||
auto* file_chooser = GTK_FILE_CHOOSER(dialog());
|
||||
gtk_file_chooser_set_select_multiple(file_chooser,
|
||||
hasProp(FILE_DIALOG_MULTI_SELECTIONS));
|
||||
gtk_file_chooser_set_show_hidden(file_chooser,
|
||||
hasProp(FILE_DIALOG_SHOW_HIDDEN_FILES));
|
||||
}
|
||||
|
||||
void RunAsynchronous() {
|
||||
|
||||
@@ -40,7 +40,8 @@ class GtkMessageBox : public NativeWindowObserver {
|
||||
const std::string& message,
|
||||
const std::string& detail,
|
||||
const std::string& checkbox_label,
|
||||
bool checkbox_checked)
|
||||
bool checkbox_checked,
|
||||
const gfx::ImageSkia& icon)
|
||||
: cancel_id_(cancel_id),
|
||||
parent_(static_cast<NativeWindow*>(parent_window)) {
|
||||
// Create dialog.
|
||||
@@ -56,6 +57,21 @@ class GtkMessageBox : public NativeWindowObserver {
|
||||
if (!title.empty())
|
||||
gtk_window_set_title(GTK_WINDOW(dialog_), title.c_str());
|
||||
|
||||
if (!icon.isNull()) {
|
||||
// No easy way to obtain this programmatically, but GTK+'s docs
|
||||
// define GTK_ICON_SIZE_DIALOG to be 48 pixels
|
||||
static constexpr int pixel_width = 48;
|
||||
static constexpr int pixel_height = 48;
|
||||
GdkPixbuf* pixbuf = libgtkui::GdkPixbufFromSkBitmap(*icon.bitmap());
|
||||
GdkPixbuf* scaled_pixbuf = gdk_pixbuf_scale_simple(
|
||||
pixbuf, pixel_width, pixel_height, GDK_INTERP_BILINEAR);
|
||||
GtkWidget* w = gtk_image_new_from_pixbuf(scaled_pixbuf);
|
||||
gtk_message_dialog_set_image(GTK_MESSAGE_DIALOG(dialog_), w);
|
||||
gtk_widget_show(w);
|
||||
g_clear_pointer(&scaled_pixbuf, gdk_pixbuf_unref);
|
||||
g_clear_pointer(&pixbuf, gdk_pixbuf_unref);
|
||||
}
|
||||
|
||||
if (!checkbox_label.empty()) {
|
||||
GtkWidget* message_area =
|
||||
gtk_message_dialog_get_message_area(GTK_MESSAGE_DIALOG(dialog_));
|
||||
@@ -66,15 +82,15 @@ class GtkMessageBox : public NativeWindowObserver {
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button),
|
||||
checkbox_checked);
|
||||
gtk_container_add(GTK_CONTAINER(message_area), check_button);
|
||||
gtk_widget_show(check_button);
|
||||
}
|
||||
|
||||
// Add buttons.
|
||||
GtkDialog* dialog = GTK_DIALOG(dialog_);
|
||||
for (size_t i = 0; i < buttons.size(); ++i) {
|
||||
GtkWidget* button = gtk_dialog_add_button(
|
||||
GTK_DIALOG(dialog_), TranslateToStock(i, buttons[i]), i);
|
||||
if (static_cast<int>(i) == default_id)
|
||||
gtk_widget_grab_focus(button);
|
||||
gtk_dialog_add_button(dialog, TranslateToStock(i, buttons[i]), i);
|
||||
}
|
||||
gtk_dialog_set_default_response(dialog, default_id);
|
||||
|
||||
// Parent window.
|
||||
if (parent_) {
|
||||
@@ -122,7 +138,7 @@ class GtkMessageBox : public NativeWindowObserver {
|
||||
}
|
||||
|
||||
void Show() {
|
||||
gtk_widget_show_all(dialog_);
|
||||
gtk_widget_show(dialog_);
|
||||
// We need to call gtk_window_present after making the widgets visible to
|
||||
// make sure window gets correctly raised and gets focus.
|
||||
int time = ui::X11EventSource::GetInstance()->GetTimestamp();
|
||||
@@ -195,9 +211,9 @@ int ShowMessageBox(NativeWindow* parent,
|
||||
const std::string& title,
|
||||
const std::string& message,
|
||||
const std::string& detail,
|
||||
const gfx::ImageSkia& /*icon*/) {
|
||||
const gfx::ImageSkia& icon) {
|
||||
return GtkMessageBox(parent, type, buttons, default_id, cancel_id, title,
|
||||
message, detail, "", false)
|
||||
message, detail, "", false, icon)
|
||||
.RunSynchronous();
|
||||
}
|
||||
|
||||
@@ -212,10 +228,10 @@ void ShowMessageBox(NativeWindow* parent,
|
||||
const std::string& detail,
|
||||
const std::string& checkbox_label,
|
||||
bool checkbox_checked,
|
||||
const gfx::ImageSkia& /*icon*/,
|
||||
const gfx::ImageSkia& icon,
|
||||
const MessageBoxCallback& callback) {
|
||||
(new GtkMessageBox(parent, type, buttons, default_id, cancel_id, title,
|
||||
message, detail, checkbox_label, checkbox_checked))
|
||||
message, detail, checkbox_label, checkbox_checked, icon))
|
||||
->RunAsynchronous(callback);
|
||||
}
|
||||
|
||||
@@ -223,7 +239,8 @@ void ShowErrorBox(const base::string16& title, const base::string16& content) {
|
||||
if (Browser::Get()->is_ready()) {
|
||||
GtkMessageBox(nullptr, MESSAGE_BOX_TYPE_ERROR, {"OK"}, -1, 0, "Error",
|
||||
base::UTF16ToUTF8(title).c_str(),
|
||||
base::UTF16ToUTF8(content).c_str(), "", false)
|
||||
base::UTF16ToUTF8(content).c_str(), "", false,
|
||||
gfx::ImageSkia())
|
||||
.RunSynchronous();
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
|
||||
@@ -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.7
|
||||
// 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"
|
||||
@@ -36,6 +38,7 @@
|
||||
V(atom_browser_debugger) \
|
||||
V(atom_browser_dialog) \
|
||||
V(atom_browser_download_item) \
|
||||
V(atom_browser_event) \
|
||||
V(atom_browser_global_shortcut) \
|
||||
V(atom_browser_in_app_purchase) \
|
||||
V(atom_browser_menu) \
|
||||
@@ -213,19 +216,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
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
#undef NO_RETURN
|
||||
#undef LIKELY
|
||||
#undef arraysize
|
||||
#undef debug_string // This is defined in macOS 10.9 SDK in AssertMacros.h.
|
||||
#undef debug_string // This is defined in macOS SDK in AssertMacros.h.
|
||||
#include "env-inl.h"
|
||||
#include "env.h"
|
||||
#include "node.h"
|
||||
|
||||
@@ -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[];
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "url/gurl.h"
|
||||
|
||||
#define ELECTRON_TRASH "ELECTRON_TRASH"
|
||||
#define ELECTRON_DEFAULT_TRASH "gvfs-trash"
|
||||
#define ELECTRON_DEFAULT_TRASH "gio"
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -125,12 +125,13 @@ bool MoveItemToTrash(const base::FilePath& full_path) {
|
||||
} else if (trash.compare("trash-cli") == 0) {
|
||||
argv.push_back("trash-put");
|
||||
argv.push_back(full_path.value());
|
||||
} else if (trash.compare("gio") == 0) {
|
||||
argv.push_back("gio");
|
||||
argv.push_back("trash");
|
||||
} else if (trash.compare("gvfs-trash") == 0) {
|
||||
// retain support for deprecated gvfs-trash
|
||||
argv.push_back("gvfs-trash");
|
||||
argv.push_back(full_path.value());
|
||||
} else {
|
||||
argv.push_back(ELECTRON_DEFAULT_TRASH);
|
||||
argv.push_back("trash");
|
||||
argv.push_back(full_path.value());
|
||||
}
|
||||
return XDGUtilV(argv, true);
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -514,8 +514,9 @@ void InspectableWebContentsImpl::ShowItemInFolder(
|
||||
const std::string& file_system_path) {
|
||||
if (file_system_path.empty())
|
||||
return;
|
||||
|
||||
base::FilePath path = base::FilePath::FromUTF8Unsafe(file_system_path);
|
||||
platform_util::ShowItemInFolder(path);
|
||||
platform_util::OpenItem(path);
|
||||
}
|
||||
|
||||
void InspectableWebContentsImpl::SaveToFile(const std::string& url,
|
||||
|
||||
@@ -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
|
||||
@@ -13,6 +13,11 @@ PATHS_TO_SKIP = [
|
||||
'swiftshader', #Skipping because it is an output of //ui/gl that we don't need
|
||||
'./libVkLayer_', #Skipping because these are outputs that we don't need
|
||||
'./VkLayerLayer_', #Skipping because these are outputs that we don't need
|
||||
|
||||
# //chrome/browser:resources depends on this via
|
||||
# //chrome/browser/resources/ssl/ssl_error_assistant, but we don't need to
|
||||
# ship it.
|
||||
'pyproto',
|
||||
]
|
||||
|
||||
def skip_path(dep):
|
||||
|
||||
@@ -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`.
|
||||
@@ -399,6 +398,30 @@ non-minimized.
|
||||
This event is guaranteed to be emitted after the `ready` event of `app`
|
||||
gets emitted.
|
||||
|
||||
### Event: 'remote-require'
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `webContents` [WebContents](web-contents.md)
|
||||
* `moduleName` String
|
||||
|
||||
Emitted when `remote.require()` is called in the renderer process of `webContents`.
|
||||
Calling `event.preventDefault()` will prevent the module from being returned.
|
||||
Custom value can be returned by setting `event.returnValue`.
|
||||
|
||||
### Event: 'remote-get-global'
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `webContents` [WebContents](web-contents.md)
|
||||
* `globalName` String
|
||||
|
||||
Emitted when `remote.getGlobal()` is called in the renderer process of `webContents`.
|
||||
Calling `event.preventDefault()` will prevent the global from being returned.
|
||||
Custom value can be returned by setting `event.returnValue`.
|
||||
|
||||
## Methods
|
||||
|
||||
The `app` object has the following methods:
|
||||
@@ -995,7 +1018,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)
|
||||
|
||||
@@ -32,7 +35,7 @@ app.makeSingleInstance(function (argv, cwd) {
|
||||
})
|
||||
// Replace with
|
||||
app.requestSingleInstanceLock()
|
||||
app.on('second-instance', function (argv, cwd) {
|
||||
app.on('second-instance', function (event, argv, cwd) {
|
||||
|
||||
})
|
||||
```
|
||||
|
||||
@@ -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
|
||||
@@ -58,6 +80,16 @@ Don't attach to the current console session.
|
||||
|
||||
Don't use the global menu bar on Linux.
|
||||
|
||||
### `ELECTRON_TRASH` _Linux_
|
||||
|
||||
Set the trash implementation on Linux. Default is `gio`.
|
||||
|
||||
Options:
|
||||
* `gvfs-trash`
|
||||
* `trash-cli`
|
||||
* `kioclient5`
|
||||
* `kioclient`
|
||||
|
||||
## Development Variables
|
||||
|
||||
The following environment variables are intended primarily for development and
|
||||
|
||||
@@ -21,11 +21,10 @@ win.show()
|
||||
|
||||
### Alternatives on macOS
|
||||
|
||||
On macOS 10.9 Mavericks and newer, there's an alternative way to specify
|
||||
a chromeless window. Instead of setting `frame` to `false` which disables
|
||||
both the titlebar and window controls, you may want to have the title bar
|
||||
hidden and your content extend to the full window size, yet still preserve
|
||||
the window controls ("traffic lights") for standard window actions.
|
||||
There's an alternative way to specify a chromeless window.
|
||||
Instead of setting `frame` to `false` which disables both the titlebar and window controls,
|
||||
you may want to have the title bar hidden and your content extend to the full window size,
|
||||
yet still preserve the window controls ("traffic lights") for standard window actions.
|
||||
You can do so by specifying the `titleBarStyle` option:
|
||||
|
||||
#### `hidden`
|
||||
|
||||
@@ -74,13 +74,13 @@ and replies by setting `event.returnValue`.
|
||||
**Note:** Sending a synchronous message will block the whole renderer process,
|
||||
unless you know what you are doing you should never use it.
|
||||
|
||||
### `ipcRenderer.sendTo(windowId, channel, [, arg1][, arg2][, ...])`
|
||||
### `ipcRenderer.sendTo(webContentsId, channel, [, arg1][, arg2][, ...])`
|
||||
|
||||
* `windowId` Number
|
||||
* `webContentsId` Number
|
||||
* `channel` String
|
||||
* `...args` any[]
|
||||
|
||||
Sends a message to a window with `windowid` via `channel`.
|
||||
Sends a message to a window with `webContentsId` via `channel`.
|
||||
|
||||
### `ipcRenderer.sendToHost(channel[, arg1][, arg2][, ...])`
|
||||
|
||||
|
||||
@@ -108,6 +108,8 @@ When specifying a `role` on macOS, `label` and `accelerator` are the only
|
||||
options that will affect the menu item. All other options will be ignored.
|
||||
Lowercase `role`, e.g. `toggledevtools`, is still supported.
|
||||
|
||||
**Nota Bene:** The `enabled` and `visibility` properties are not available for top-level menu items in the tray on MacOS.
|
||||
|
||||
### Instance Properties
|
||||
|
||||
The following properties are available on instances of `MenuItem`:
|
||||
|
||||
@@ -169,6 +169,7 @@ should be called with either a `String` or an object that has the `data`,
|
||||
* `handler` Function
|
||||
* `request` Object
|
||||
* `url` String
|
||||
* `headers` Object
|
||||
* `referrer` String
|
||||
* `method` String
|
||||
* `uploadData` [UploadData[]](structures/upload-data.md)
|
||||
@@ -329,6 +330,7 @@ which sends a `Buffer` as a response.
|
||||
* `handler` Function
|
||||
* `request` Object
|
||||
* `url` String
|
||||
* `headers` Object
|
||||
* `referrer` String
|
||||
* `method` String
|
||||
* `uploadData` [UploadData[]](structures/upload-data.md)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -83,6 +83,8 @@ that contains the user information dictionary sent along with the notification.
|
||||
* `callback` Function
|
||||
* `event` String
|
||||
* `userInfo` Object
|
||||
|
||||
Returns `Number` - The ID of this subscription
|
||||
|
||||
Subscribes to native notifications of macOS, `callback` will be called with
|
||||
`callback(event, userInfo)` when the corresponding `event` happens. The
|
||||
@@ -106,6 +108,8 @@ example values of `event` are:
|
||||
* `callback` Function
|
||||
* `event` String
|
||||
* `userInfo` Object
|
||||
|
||||
Returns `Number` - The ID of this subscription
|
||||
|
||||
Same as `subscribeNotification`, but uses `NSNotificationCenter` for local defaults.
|
||||
This is necessary for events such as `NSUserDefaultsDidChangeNotification`.
|
||||
|
||||
@@ -663,6 +663,28 @@ Returns:
|
||||
Emitted when the associated window logs a console message. Will not be emitted
|
||||
for windows with *offscreen rendering* enabled.
|
||||
|
||||
#### Event: 'remote-require'
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `moduleName` String
|
||||
|
||||
Emitted when `remote.require()` is called in the renderer process.
|
||||
Calling `event.preventDefault()` will prevent the module from being returned.
|
||||
Custom value can be returned by setting `event.returnValue`.
|
||||
|
||||
#### Event: 'remote-get-global'
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `globalName` String
|
||||
|
||||
Emitted when `remote.getGlobal()` is called in the renderer process.
|
||||
Calling `event.preventDefault()` will prevent the global from being returned.
|
||||
Custom value can be returned by setting `event.returnValue`.
|
||||
|
||||
### Instance Methods
|
||||
|
||||
#### `contents.loadURL(url[, options])`
|
||||
@@ -1084,7 +1106,7 @@ Use `page-break-before: always; ` CSS style to force to print to a new page.
|
||||
* `options` Object
|
||||
* `marginsType` Integer (optional) - Specifies the type of margins to use. Uses 0 for
|
||||
default margin, 1 for no margin, and 2 for minimum margin.
|
||||
* `pageSize` String (optional) - Specify page size of the generated PDF. Can be `A3`,
|
||||
* `pageSize` String | Size (optional) - Specify page size of the generated PDF. Can be `A3`,
|
||||
`A4`, `A5`, `Legal`, `Letter`, `Tabloid` or an Object containing `height`
|
||||
and `width` in microns.
|
||||
* `printBackground` Boolean (optional) - Whether to print CSS backgrounds.
|
||||
|
||||
@@ -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
|
||||
@@ -517,7 +526,7 @@ Prints `webview`'s web page. Same as `webContents.print([options])`.
|
||||
* `options` Object
|
||||
* `marginsType` Integer (optional) - Specifies the type of margins to use. Uses 0 for
|
||||
default margin, 1 for no margin, and 2 for minimum margin.
|
||||
* `pageSize` String (optional) - Specify page size of the generated PDF. Can be `A3`,
|
||||
* `pageSize` String | Size (optional) - Specify page size of the generated PDF. Can be `A3`,
|
||||
`A4`, `A5`, `Legal`, `Letter`, `Tabloid` or an Object containing `height`
|
||||
and `width` in microns.
|
||||
* `printBackground` Boolean (optional) - Whether to print CSS backgrounds.
|
||||
@@ -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:
|
||||
|
||||
@@ -7,7 +7,7 @@ rudimentary understanding of your operating system's command line client.
|
||||
|
||||
## Setting up macOS
|
||||
|
||||
> Electron supports Mac OS X 10.9 (and all versions named macOS) and up. Apple
|
||||
> Electron supports macOS 10.10 (Yosemite) and up. Apple
|
||||
does not allow running macOS in virtual machines unless the host computer is
|
||||
already an Apple computer, so if you find yourself in need of a Mac, consider
|
||||
using a cloud service that rents access to Macs (like [MacInCloud][macincloud]
|
||||
|
||||
@@ -61,7 +61,7 @@ Following platforms are supported by Electron:
|
||||
### macOS
|
||||
|
||||
Only 64bit binaries are provided for macOS, and the minimum macOS version
|
||||
supported is macOS 10.9.
|
||||
supported is macOS 10.10 (Yosemite).
|
||||
|
||||
### Windows
|
||||
|
||||
@@ -79,7 +79,7 @@ Ubuntu 12.04, the `armv7l` binary is built against ARM v7 with hard-float ABI an
|
||||
NEON for Debian Wheezy.
|
||||
|
||||
[Until the release of Electron 2.0][arm-breaking-change], Electron will also
|
||||
continue to release the `armv7l` binary with a simple `arm` suffix. Both binaries
|
||||
continue to release the `armv7l` binary with a simple `arm` suffix. Both binaries
|
||||
are identical.
|
||||
|
||||
Whether the prebuilt binary can run on a distribution depends on whether the
|
||||
|
||||
@@ -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",
|
||||
@@ -132,6 +133,7 @@ filenames = {
|
||||
"atom/browser/api/atom_api_dialog.cc",
|
||||
"atom/browser/api/atom_api_download_item.cc",
|
||||
"atom/browser/api/atom_api_download_item.h",
|
||||
"atom/browser/api/atom_api_event.cc",
|
||||
"atom/browser/api/atom_api_global_shortcut.cc",
|
||||
"atom/browser/api/atom_api_global_shortcut.h",
|
||||
"atom/browser/api/atom_api_in_app_purchase.cc",
|
||||
@@ -270,6 +272,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
|
||||
}
|
||||
|
||||
|
||||
@@ -336,6 +336,14 @@ WebContents.prototype._init = function () {
|
||||
})
|
||||
})
|
||||
|
||||
this.on('remote-require', (event, ...args) => {
|
||||
app.emit('remote-require', event, this, ...args)
|
||||
})
|
||||
|
||||
this.on('remote-get-global', (event, ...args) => {
|
||||
app.emit('remote-get-global', event, this, ...args)
|
||||
})
|
||||
|
||||
deprecate.event(this, 'did-get-response-details', '-did-get-response-details')
|
||||
deprecate.event(this, 'did-get-redirect-request', '-did-get-redirect-request')
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -7,6 +7,7 @@ const fs = require('fs')
|
||||
const os = require('os')
|
||||
const path = require('path')
|
||||
const v8Util = process.atomBinding('v8_util')
|
||||
const eventBinding = process.atomBinding('event')
|
||||
|
||||
const { isPromise } = electron
|
||||
|
||||
@@ -151,9 +152,10 @@ const throwRPCError = function (message) {
|
||||
throw error
|
||||
}
|
||||
|
||||
const removeRemoteListenersAndLogWarning = (sender, meta, callIntoRenderer) => {
|
||||
const removeRemoteListenersAndLogWarning = (sender, callIntoRenderer) => {
|
||||
const location = v8Util.getHiddenValue(callIntoRenderer, 'location')
|
||||
let message = `Attempting to call a function in a renderer window that has been closed or released.` +
|
||||
`\nFunction provided here: ${meta.location}`
|
||||
`\nFunction provided here: ${location}`
|
||||
|
||||
if (sender instanceof EventEmitter) {
|
||||
const remoteEvents = sender.eventNames().filter((eventName) => {
|
||||
@@ -213,14 +215,14 @@ const unwrapArgs = function (sender, contextId, args) {
|
||||
return rendererFunctions.get(objectId)
|
||||
}
|
||||
|
||||
const processId = sender.getProcessId()
|
||||
const callIntoRenderer = function (...args) {
|
||||
if (!sender.isDestroyed() && processId === sender.getProcessId()) {
|
||||
if (!sender.isDestroyed()) {
|
||||
sender._sendInternal('ELECTRON_RENDERER_CALLBACK', contextId, meta.id, valueToMeta(sender, contextId, args))
|
||||
} else {
|
||||
removeRemoteListenersAndLogWarning(this, meta, callIntoRenderer)
|
||||
removeRemoteListenersAndLogWarning(this, callIntoRenderer)
|
||||
}
|
||||
}
|
||||
v8Util.setHiddenValue(callIntoRenderer, 'location', meta.location)
|
||||
Object.defineProperty(callIntoRenderer, 'length', { value: meta.length })
|
||||
|
||||
v8Util.setRemoteCallbackFreer(callIntoRenderer, contextId, meta.id, sender)
|
||||
@@ -263,27 +265,64 @@ 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
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
handleRemoteCommand('ELECTRON_BROWSER_REQUIRE', function (event, contextId, module) {
|
||||
return valueToMeta(event.sender, contextId, process.mainModule.require(module))
|
||||
handleRemoteCommand('ELECTRON_BROWSER_WRONG_CONTEXT_ERROR', function (event, contextId, passedContextId, id) {
|
||||
const objectId = [passedContextId, id]
|
||||
if (!rendererFunctions.has(objectId)) {
|
||||
// Do nothing if the error has already been reported before.
|
||||
return
|
||||
}
|
||||
removeRemoteListenersAndLogWarning(event.sender, rendererFunctions.get(objectId))
|
||||
})
|
||||
|
||||
handleRemoteCommand('ELECTRON_BROWSER_REQUIRE', function (event, contextId, moduleName) {
|
||||
const customEvent = eventBinding.createWithSender(event.sender)
|
||||
event.sender.emit('remote-require', customEvent, moduleName)
|
||||
|
||||
if (customEvent.defaultPrevented) {
|
||||
if (typeof customEvent.returnValue === 'undefined') {
|
||||
throw new Error(`Invalid module: ${moduleName}`)
|
||||
}
|
||||
} else {
|
||||
customEvent.returnValue = process.mainModule.require(moduleName)
|
||||
}
|
||||
|
||||
return valueToMeta(event.sender, contextId, customEvent.returnValue)
|
||||
})
|
||||
|
||||
handleRemoteCommand('ELECTRON_BROWSER_GET_BUILTIN', function (event, contextId, module) {
|
||||
return valueToMeta(event.sender, contextId, electron[module])
|
||||
})
|
||||
|
||||
handleRemoteCommand('ELECTRON_BROWSER_GLOBAL', function (event, contextId, name) {
|
||||
return valueToMeta(event.sender, contextId, global[name])
|
||||
handleRemoteCommand('ELECTRON_BROWSER_GLOBAL', function (event, contextId, globalName) {
|
||||
const customEvent = eventBinding.createWithSender(event.sender)
|
||||
event.sender.emit('remote-get-global', customEvent, globalName)
|
||||
|
||||
if (customEvent.defaultPrevented) {
|
||||
if (typeof customEvent.returnValue === 'undefined') {
|
||||
throw new Error(`Invalid global: ${globalName}`)
|
||||
}
|
||||
} else {
|
||||
customEvent.returnValue = global[globalName]
|
||||
}
|
||||
|
||||
return valueToMeta(event.sender, contextId, customEvent.returnValue)
|
||||
})
|
||||
|
||||
handleRemoteCommand('ELECTRON_BROWSER_CURRENT_WINDOW', function (event, contextId) {
|
||||
@@ -376,7 +415,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 +467,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 +480,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 +534,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 +544,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
|
||||
|
||||
@@ -238,9 +238,9 @@
|
||||
}
|
||||
|
||||
const { lstatSync } = fs
|
||||
fs.lstatSync = pathArgument => {
|
||||
fs.lstatSync = (pathArgument, options) => {
|
||||
const { isAsar, asarPath, filePath } = splitPath(pathArgument)
|
||||
if (!isAsar) return lstatSync(pathArgument)
|
||||
if (!isAsar) return lstatSync(pathArgument, options)
|
||||
|
||||
const archive = getOrCreateArchive(asarPath)
|
||||
if (!archive) throw createError(AsarError.INVALID_ARCHIVE, { asarPath })
|
||||
@@ -252,9 +252,13 @@
|
||||
}
|
||||
|
||||
const { lstat } = fs
|
||||
fs.lstat = (pathArgument, callback) => {
|
||||
fs.lstat = function (pathArgument, options, callback) {
|
||||
const { isAsar, asarPath, filePath } = splitPath(pathArgument)
|
||||
if (!isAsar) return lstat(pathArgument, callback)
|
||||
if (typeof options === 'function') {
|
||||
callback = options
|
||||
options = {}
|
||||
}
|
||||
if (!isAsar) return lstat(pathArgument, options, callback)
|
||||
|
||||
const archive = getOrCreateArchive(asarPath)
|
||||
if (!archive) {
|
||||
@@ -275,39 +279,29 @@
|
||||
}
|
||||
|
||||
const { statSync } = fs
|
||||
fs.statSync = pathArgument => {
|
||||
fs.statSync = (pathArgument, options) => {
|
||||
const { isAsar } = splitPath(pathArgument)
|
||||
if (!isAsar) return statSync(pathArgument)
|
||||
if (!isAsar) return statSync(pathArgument, options)
|
||||
|
||||
// Do not distinguish links for now.
|
||||
return fs.lstatSync(pathArgument)
|
||||
return fs.lstatSync(pathArgument, options)
|
||||
}
|
||||
|
||||
const { stat } = fs
|
||||
fs.stat = (pathArgument, callback) => {
|
||||
fs.stat = (pathArgument, options, callback) => {
|
||||
const { isAsar } = splitPath(pathArgument)
|
||||
if (!isAsar) return stat(pathArgument, callback)
|
||||
if (typeof options === 'function') {
|
||||
callback = options
|
||||
options = {}
|
||||
}
|
||||
if (!isAsar) return stat(pathArgument, options, callback)
|
||||
|
||||
// Do not distinguish links for now.
|
||||
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)
|
||||
process.nextTick(() => fs.lstat(pathArgument, options, callback))
|
||||
}
|
||||
|
||||
const { realpathSync } = fs
|
||||
fs.realpathSync = function (pathArgument) {
|
||||
fs.realpathSync = function (pathArgument, options) {
|
||||
const { isAsar, asarPath, filePath } = splitPath(pathArgument)
|
||||
if (!isAsar) return realpathSync.apply(this, arguments)
|
||||
|
||||
@@ -321,10 +315,10 @@
|
||||
throw createError(AsarError.NOT_FOUND, { asarPath, filePath })
|
||||
}
|
||||
|
||||
return path.join(realpathSync(asarPath), fileRealPath)
|
||||
return path.join(realpathSync(asarPath, options), fileRealPath)
|
||||
}
|
||||
|
||||
fs.realpathSync.native = function (pathArgument) {
|
||||
fs.realpathSync.native = function (pathArgument, options) {
|
||||
const { isAsar, asarPath, filePath } = splitPath(pathArgument)
|
||||
if (!isAsar) return realpathSync.native.apply(this, arguments)
|
||||
|
||||
@@ -338,17 +332,17 @@
|
||||
throw createError(AsarError.NOT_FOUND, { asarPath, filePath })
|
||||
}
|
||||
|
||||
return path.join(realpathSync.native(asarPath), fileRealPath)
|
||||
return path.join(realpathSync.native(asarPath, options), fileRealPath)
|
||||
}
|
||||
|
||||
const { realpath } = fs
|
||||
fs.realpath = function (pathArgument, cache, callback) {
|
||||
fs.realpath = function (pathArgument, options, callback) {
|
||||
const { isAsar, asarPath, filePath } = splitPath(pathArgument)
|
||||
if (!isAsar) return realpath.apply(this, arguments)
|
||||
|
||||
if (typeof cache === 'function') {
|
||||
callback = cache
|
||||
cache = undefined
|
||||
if (arguments.length < 3) {
|
||||
callback = options
|
||||
options = {}
|
||||
}
|
||||
|
||||
const archive = getOrCreateArchive(asarPath)
|
||||
@@ -365,7 +359,7 @@
|
||||
return
|
||||
}
|
||||
|
||||
realpath(asarPath, (error, archiveRealPath) => {
|
||||
realpath(asarPath, options, (error, archiveRealPath) => {
|
||||
if (error === null) {
|
||||
const fullPath = path.join(archiveRealPath, fileRealPath)
|
||||
callback(null, fullPath)
|
||||
@@ -375,13 +369,13 @@
|
||||
})
|
||||
}
|
||||
|
||||
fs.realpath.native = function (pathArgument, cache, callback) {
|
||||
fs.realpath.native = function (pathArgument, options, callback) {
|
||||
const { isAsar, asarPath, filePath } = splitPath(pathArgument)
|
||||
if (!isAsar) return realpath.native.apply(this, arguments)
|
||||
|
||||
if (typeof cache === 'function') {
|
||||
callback = cache
|
||||
cache = undefined
|
||||
if (arguments.length < 3) {
|
||||
callback = options
|
||||
options = {}
|
||||
}
|
||||
|
||||
const archive = getOrCreateArchive(asarPath)
|
||||
@@ -398,7 +392,7 @@
|
||||
return
|
||||
}
|
||||
|
||||
realpath.native(asarPath, (error, archiveRealPath) => {
|
||||
realpath.native(asarPath, options, (error, archiveRealPath) => {
|
||||
if (error === null) {
|
||||
const fullPath = path.join(archiveRealPath, fileRealPath)
|
||||
callback(null, fullPath)
|
||||
@@ -616,8 +610,12 @@
|
||||
}
|
||||
|
||||
const { readdir } = fs
|
||||
fs.readdir = function (pathArgument, callback) {
|
||||
fs.readdir = function (pathArgument, options, callback) {
|
||||
const { isAsar, asarPath, filePath } = splitPath(pathArgument)
|
||||
if (typeof options === 'function') {
|
||||
callback = options
|
||||
options = {}
|
||||
}
|
||||
if (!isAsar) return readdir.apply(this, arguments)
|
||||
|
||||
const archive = getOrCreateArchive(asarPath)
|
||||
@@ -638,7 +636,7 @@
|
||||
}
|
||||
|
||||
const { readdirSync } = fs
|
||||
fs.readdirSync = function (pathArgument) {
|
||||
fs.readdirSync = function (pathArgument, options) {
|
||||
const { isAsar, asarPath, filePath } = splitPath(pathArgument)
|
||||
if (!isAsar) return readdirSync.apply(this, arguments)
|
||||
|
||||
@@ -698,14 +696,12 @@
|
||||
|
||||
// Calling mkdir for directory inside asar archive should throw ENOTDIR
|
||||
// error, but on Windows it throws ENOENT.
|
||||
// This is to work around the recursive looping bug of mkdirp since it is
|
||||
// widely used.
|
||||
if (process.platform === 'win32') {
|
||||
const { mkdir } = fs
|
||||
fs.mkdir = (pathArgument, mode, callback) => {
|
||||
if (typeof mode === 'function') {
|
||||
callback = mode
|
||||
mode = undefined
|
||||
fs.mkdir = (pathArgument, options, callback) => {
|
||||
if (typeof options === 'function') {
|
||||
callback = options
|
||||
options = {}
|
||||
}
|
||||
|
||||
const { isAsar, filePath } = splitPath(pathArgument)
|
||||
@@ -715,14 +711,14 @@
|
||||
return
|
||||
}
|
||||
|
||||
mkdir(pathArgument, mode, callback)
|
||||
mkdir(pathArgument, options, callback)
|
||||
}
|
||||
|
||||
const { mkdirSync } = fs
|
||||
fs.mkdirSync = function (pathArgument, mode) {
|
||||
fs.mkdirSync = function (pathArgument, options) {
|
||||
const { isAsar, filePath } = splitPath(pathArgument)
|
||||
if (isAsar && filePath.length) throw createError(AsarError.NOT_DIR)
|
||||
return mkdirSync(pathArgument, mode)
|
||||
return mkdirSync(pathArgument, options)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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' }
|
||||
]
|
||||
|
||||
@@ -270,9 +270,12 @@ function metaToPlainObject (meta) {
|
||||
}
|
||||
|
||||
function handleMessage (channel, handler) {
|
||||
ipcRenderer.on(channel, (event, passedContextId, ...args) => {
|
||||
ipcRenderer.on(channel, (event, passedContextId, id, ...args) => {
|
||||
if (passedContextId === contextId) {
|
||||
handler(...args)
|
||||
handler(id, ...args)
|
||||
} else {
|
||||
// Message sent to an un-exist context, notify the error to main process.
|
||||
ipcRenderer.send('ELECTRON_BROWSER_WRONG_CONTEXT_ERROR', contextId, passedContextId, id)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use strict'
|
||||
|
||||
module.exports = require('electron').remote.screen
|
||||
const { getRemoteForUsage } = require('@electron/internal/renderer/remote')
|
||||
module.exports = getRemoteForUsage('screen').screen
|
||||
|
||||
@@ -43,12 +43,12 @@ class Port {
|
||||
disconnect () {
|
||||
if (this.disconnected) return
|
||||
|
||||
ipcRenderer._sendInternalToAll(this.tabId, `CHROME_PORT_DISCONNECT_${this.portId}`)
|
||||
ipcRenderer.sendToAll(this.tabId, `CHROME_PORT_DISCONNECT_${this.portId}`)
|
||||
this._onDisconnect()
|
||||
}
|
||||
|
||||
postMessage (message) {
|
||||
ipcRenderer._sendInternalToAll(this.tabId, `CHROME_PORT_POSTMESSAGE_${this.portId}`, message)
|
||||
ipcRenderer.sendToAll(this.tabId, `CHROME_PORT_POSTMESSAGE_${this.portId}`, message)
|
||||
}
|
||||
|
||||
_onDisconnect () {
|
||||
|
||||
@@ -4,9 +4,17 @@ window.onload = function () {
|
||||
// Use menu API to show context menu.
|
||||
window.InspectorFrontendHost.showContextMenuAtPoint = createMenu
|
||||
|
||||
// correct for Chromium returning undefined for filesystem
|
||||
window.Persistence.FileSystemWorkspaceBinding.completeURL = completeURL
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// Extra / is needed as a result of MacOS requiring absolute paths
|
||||
function completeURL (project, path) {
|
||||
project = 'file:///'
|
||||
return `${project}${path}`
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
@@ -4,7 +4,7 @@ var electron = require('./')
|
||||
|
||||
var proc = require('child_process')
|
||||
|
||||
var child = proc.spawn(electron, process.argv.slice(2), { stdio: 'inherit' })
|
||||
var child = proc.spawn(electron, process.argv.slice(2), { stdio: 'inherit', windowsHide: false })
|
||||
child.on('close', function (code) {
|
||||
process.exit(code)
|
||||
})
|
||||
|
||||
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.7",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "electron",
|
||||
"version": "4.0.0-nightly.20181010",
|
||||
"version": "4.0.0-beta.7",
|
||||
"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",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user