From 17b8b551ac892bfa8d20d85c5eabbe466a0d87c9 Mon Sep 17 00:00:00 2001 From: "trop[bot]" <37223003+trop[bot]@users.noreply.github.com> Date: Tue, 10 Sep 2019 21:56:07 -0400 Subject: [PATCH 01/28] build: handle arm64 node headers (#20194) * build: handle arm64 node headers (cherry picked from commit ff1f224d96fbbd0d745483d48a7ee55dc80f8add) * node.lib for arm64 needs to go to specific dir --- script/upload-node-headers.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/script/upload-node-headers.py b/script/upload-node-headers.py index df8de4a65baf3..066a5370d4173 100755 --- a/script/upload-node-headers.py +++ b/script/upload-node-headers.py @@ -53,6 +53,10 @@ def upload_node(bucket, access_key, secret_key, version): node_lib = os.path.join(DIST_DIR, 'node.lib') iojs_lib = os.path.join(DIST_DIR, 'win-x86', 'iojs.lib') v4_node_lib = os.path.join(DIST_DIR, 'win-x86', 'node.lib') + elif get_target_arch() == 'arm64': + node_lib = os.path.join(DIST_DIR, 'arm64', 'node.lib') + iojs_lib = os.path.join(DIST_DIR, 'win-arm64', 'iojs.lib') + v4_node_lib = os.path.join(DIST_DIR, 'win-arm64', 'node.lib') else: node_lib = os.path.join(DIST_DIR, 'x64', 'node.lib') iojs_lib = os.path.join(DIST_DIR, 'win-x64', 'iojs.lib') From 407747b48c47cdeed156a73dde1c47609470c95a Mon Sep 17 00:00:00 2001 From: Electron Bot Date: Wed, 11 Sep 2019 10:30:11 -0700 Subject: [PATCH 02/28] Bump v6.0.9 --- ELECTRON_VERSION | 2 +- atom/browser/resources/mac/Info.plist | 4 ++-- atom/browser/resources/win/atom.rc | 8 ++++---- atom/common/atom_version.h | 2 +- package.json | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ELECTRON_VERSION b/ELECTRON_VERSION index a0c2cf5cd77f4..fb06ed73fadc6 100644 --- a/ELECTRON_VERSION +++ b/ELECTRON_VERSION @@ -1 +1 @@ -6.0.8 \ No newline at end of file +6.0.9 \ No newline at end of file diff --git a/atom/browser/resources/mac/Info.plist b/atom/browser/resources/mac/Info.plist index a04396920eb2b..dc27db7aa5f4c 100644 --- a/atom/browser/resources/mac/Info.plist +++ b/atom/browser/resources/mac/Info.plist @@ -17,9 +17,9 @@ CFBundleIconFile electron.icns CFBundleVersion - 6.0.8 + 6.0.9 CFBundleShortVersionString - 6.0.8 + 6.0.9 LSApplicationCategoryType public.app-category.developer-tools LSMinimumSystemVersion diff --git a/atom/browser/resources/win/atom.rc b/atom/browser/resources/win/atom.rc index dc08516c19edb..480a97c39f1bd 100644 --- a/atom/browser/resources/win/atom.rc +++ b/atom/browser/resources/win/atom.rc @@ -50,8 +50,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 6,0,8,0 - PRODUCTVERSION 6,0,8,0 + FILEVERSION 6,0,9,0 + PRODUCTVERSION 6,0,9,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -68,12 +68,12 @@ BEGIN BEGIN VALUE "CompanyName", "GitHub, Inc." VALUE "FileDescription", "Electron" - VALUE "FileVersion", "6.0.8" + VALUE "FileVersion", "6.0.9" VALUE "InternalName", "electron.exe" VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved." VALUE "OriginalFilename", "electron.exe" VALUE "ProductName", "Electron" - VALUE "ProductVersion", "6.0.8" + VALUE "ProductVersion", "6.0.9" VALUE "SquirrelAwareVersion", "1" END END diff --git a/atom/common/atom_version.h b/atom/common/atom_version.h index 89b82d52a1553..e26c0a34eb2ff 100644 --- a/atom/common/atom_version.h +++ b/atom/common/atom_version.h @@ -7,7 +7,7 @@ #define ATOM_MAJOR_VERSION 6 #define ATOM_MINOR_VERSION 0 -#define ATOM_PATCH_VERSION 8 +#define ATOM_PATCH_VERSION 9 // clang-format off // #define ATOM_PRE_RELEASE_VERSION // clang-format on diff --git a/package.json b/package.json index e928214d0649e..46b1d19feec1d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "electron", - "version": "6.0.8", + "version": "6.0.9", "repository": "https://github.com/electron/electron", "description": "Build cross platform desktop apps with JavaScript, HTML, and CSS", "devDependencies": { From e3be3239624cfb51d1066893f07f3e8e6bc08df3 Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Tue, 17 Sep 2019 07:49:08 -0700 Subject: [PATCH 03/28] docs: remove dash that broke the return type parser (#20246) --- docs/api/dialog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/dialog.md b/docs/api/dialog.md index e01fc8a3fdbfc..849e27f7283ff 100644 --- a/docs/api/dialog.md +++ b/docs/api/dialog.md @@ -117,7 +117,7 @@ dialog.showOpenDialogSync(mainWindow, { Returns `Promise` - Resolve wih an object containing the following: -* `canceled` - Boolean - whether or not the dialog was canceled. +* `canceled` Boolean - whether or not the dialog was canceled. * `filePaths` String[] (optional) - An array of file paths chosen by the user. If the dialog is cancelled this will be an empty array. * `bookmarks` String[] (optional) _macOS_ _mas_ - An array matching the `filePaths` array of base64 encoded strings which contains security scoped bookmark data. `securityScopedBookmarks` must be enabled for this to be populated. From f2d1abd0e37430bf983ebf60bcfab694dc567517 Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Tue, 17 Sep 2019 10:53:04 -0700 Subject: [PATCH 04/28] fix: Add more checks in MojoCdmService. (#20219) Applies https://chromium.googlesource.com/chromium/src.git/+/b7b305f3389017cc42e2cfac6e7a319f42d5bde3%5E%21/ --- patches/common/chromium/.patches | 1 + ...leges_in_unsandboxed_child_processes.patch | 2 +- ...ix_add_more_checks_in_mojocdmservice.patch | 43 +++++++++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 patches/common/chromium/fix_add_more_checks_in_mojocdmservice.patch diff --git a/patches/common/chromium/.patches b/patches/common/chromium/.patches index 8923c308eb9e0..06f8cbd21a607 100644 --- a/patches/common/chromium/.patches +++ b/patches/common/chromium/.patches @@ -83,3 +83,4 @@ crashpad_pid_check.patch fix_use_weakptr_to_detect_deletion.patch fix_disabling_compositor_recycling.patch allow_new_privileges_in_unsandboxed_child_processes.patch +fix_add_more_checks_in_mojocdmservice.patch diff --git a/patches/common/chromium/allow_new_privileges_in_unsandboxed_child_processes.patch b/patches/common/chromium/allow_new_privileges_in_unsandboxed_child_processes.patch index ea300c62f925b..6add50a01bdd4 100644 --- a/patches/common/chromium/allow_new_privileges_in_unsandboxed_child_processes.patch +++ b/patches/common/chromium/allow_new_privileges_in_unsandboxed_child_processes.patch @@ -6,7 +6,7 @@ Subject: allow new privileges in unsandboxed child processes This allows unsandboxed renderers to launch setuid processes on Linux. diff --git a/content/browser/child_process_launcher_helper_linux.cc b/content/browser/child_process_launcher_helper_linux.cc -index 720b92a1a3a7ab5512f839005b272e4989d2ac65..b1759109627cd00053489dcdd397e942fa9d289f 100644 +index 5b82388932eb845a0cf932ee2b04ece51c474d1c..6cfa4c8f34fe382fe5db6cd31dd56967a45f3bf4 100644 --- a/content/browser/child_process_launcher_helper_linux.cc +++ b/content/browser/child_process_launcher_helper_linux.cc @@ -54,6 +54,18 @@ bool ChildProcessLauncherHelper::BeforeLaunchOnLauncherThread( diff --git a/patches/common/chromium/fix_add_more_checks_in_mojocdmservice.patch b/patches/common/chromium/fix_add_more_checks_in_mojocdmservice.patch new file mode 100644 index 0000000000000..eaddde127dd45 --- /dev/null +++ b/patches/common/chromium/fix_add_more_checks_in_mojocdmservice.patch @@ -0,0 +1,43 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Pedro Pontes +Date: Thu, 12 Sep 2019 16:28:47 +0200 +Subject: fix: Add more checks in MojoCdmService. + +Applies https://chromium.googlesource.com/chromium/src.git/+/b7b305f3389017cc42e2cfac6e7a319f42d5bde3%5E%21/ + +diff --git a/media/mojo/services/mojo_cdm_service.cc b/media/mojo/services/mojo_cdm_service.cc +index 1ccfd2f05a7c56d6a867bbcc7b04aed948b73b15..a3f8332768b2e1c6375b5f643acb197a55521f83 100644 +--- a/media/mojo/services/mojo_cdm_service.cc ++++ b/media/mojo/services/mojo_cdm_service.cc +@@ -63,7 +63,9 @@ void MojoCdmService::Initialize(const std::string& key_system, + const CdmConfig& cdm_config, + InitializeCallback callback) { + DVLOG(1) << __func__ << ": " << key_system; +- DCHECK(!cdm_); ++ ++ CHECK(!has_initialize_been_called_) << "Initialize should only happen once"; ++ has_initialize_been_called_ = true; + + auto weak_this = weak_factory_.GetWeakPtr(); + cdm_factory_->Create( +@@ -157,6 +159,7 @@ void MojoCdmService::OnCdmCreated( + return; + } + ++ CHECK(!cdm_) << "CDM should only be created once."; + cdm_ = cdm; + + if (context_) { +diff --git a/media/mojo/services/mojo_cdm_service.h b/media/mojo/services/mojo_cdm_service.h +index fd265467859f86c97f16f6abb2cef19ad5b3e139..1e575474f5bcde434af1f55c0361a30e42ac6f29 100644 +--- a/media/mojo/services/mojo_cdm_service.h ++++ b/media/mojo/services/mojo_cdm_service.h +@@ -101,6 +101,8 @@ class MEDIA_MOJO_EXPORT MojoCdmService : public mojom::ContentDecryptionModule { + // Callback for when |decryptor_| loses connectivity. + void OnDecryptorConnectionError(); + ++ bool has_initialize_been_called_ = false; ++ + CdmFactory* cdm_factory_; + MojoCdmServiceContext* const context_ = nullptr; + scoped_refptr<::media::ContentDecryptionModule> cdm_; From fc7ef4cc1cdfdc54a69cca26f50287d523cbc7e7 Mon Sep 17 00:00:00 2001 From: "trop[bot]" <37223003+trop[bot]@users.noreply.github.com> Date: Wed, 18 Sep 2019 09:43:52 -0700 Subject: [PATCH 05/28] fix: strip chrome-sandbox typo (#20257) --- script/strip-binaries.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/strip-binaries.py b/script/strip-binaries.py index dbd40dae557fb..b6b9a183ae9d7 100755 --- a/script/strip-binaries.py +++ b/script/strip-binaries.py @@ -7,7 +7,7 @@ LINUX_BINARIES_TO_STRIP = [ 'electron', - 'chrome_sandbox', + 'chrome-sandbox', 'libffmpeg.so', 'libGLESv2.so', 'libEGL.so', From 690271e38c5c1131f1a20675aad8d9014b8c1fcf Mon Sep 17 00:00:00 2001 From: "trop[bot]" <37223003+trop[bot]@users.noreply.github.com> Date: Wed, 18 Sep 2019 10:21:46 -0700 Subject: [PATCH 06/28] build: add WOA node headers to checksum file (#20260) --- script/upload-node-checksums.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/script/upload-node-checksums.py b/script/upload-node-checksums.py index 4d301ce2b937a..446bf0dafbb75 100755 --- a/script/upload-node-checksums.py +++ b/script/upload-node-checksums.py @@ -59,7 +59,10 @@ def get_files_list(version): { "filename": 'win-x86/iojs.lib', "required": False }, { "filename": 'win-x64/iojs.lib', "required": False }, { "filename": 'win-x86/node.lib', "required": False }, - { "filename": 'win-x64/node.lib', "required": False } + { "filename": 'win-x64/node.lib', "required": False }, + { "filename": 'arm64/node.lib', "required": False }, + { "filename": 'win-arm64/iojs.lib', "required": False }, + { "filename": 'win-arm64/node.lib', "required": False } ] From 10a9e9c043661924a942f2478c5ab0748d282efc Mon Sep 17 00:00:00 2001 From: Electron Bot Date: Wed, 18 Sep 2019 12:48:43 -0700 Subject: [PATCH 07/28] Bump v6.0.10 --- ELECTRON_VERSION | 2 +- atom/browser/resources/mac/Info.plist | 4 ++-- atom/browser/resources/win/atom.rc | 8 ++++---- atom/common/atom_version.h | 2 +- package.json | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ELECTRON_VERSION b/ELECTRON_VERSION index fb06ed73fadc6..c5a1e4c4361df 100644 --- a/ELECTRON_VERSION +++ b/ELECTRON_VERSION @@ -1 +1 @@ -6.0.9 \ No newline at end of file +6.0.10 \ No newline at end of file diff --git a/atom/browser/resources/mac/Info.plist b/atom/browser/resources/mac/Info.plist index dc27db7aa5f4c..47f87cb46f686 100644 --- a/atom/browser/resources/mac/Info.plist +++ b/atom/browser/resources/mac/Info.plist @@ -17,9 +17,9 @@ CFBundleIconFile electron.icns CFBundleVersion - 6.0.9 + 6.0.10 CFBundleShortVersionString - 6.0.9 + 6.0.10 LSApplicationCategoryType public.app-category.developer-tools LSMinimumSystemVersion diff --git a/atom/browser/resources/win/atom.rc b/atom/browser/resources/win/atom.rc index 480a97c39f1bd..6f5ebfccfafd7 100644 --- a/atom/browser/resources/win/atom.rc +++ b/atom/browser/resources/win/atom.rc @@ -50,8 +50,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 6,0,9,0 - PRODUCTVERSION 6,0,9,0 + FILEVERSION 6,0,10,0 + PRODUCTVERSION 6,0,10,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -68,12 +68,12 @@ BEGIN BEGIN VALUE "CompanyName", "GitHub, Inc." VALUE "FileDescription", "Electron" - VALUE "FileVersion", "6.0.9" + VALUE "FileVersion", "6.0.10" VALUE "InternalName", "electron.exe" VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved." VALUE "OriginalFilename", "electron.exe" VALUE "ProductName", "Electron" - VALUE "ProductVersion", "6.0.9" + VALUE "ProductVersion", "6.0.10" VALUE "SquirrelAwareVersion", "1" END END diff --git a/atom/common/atom_version.h b/atom/common/atom_version.h index e26c0a34eb2ff..182a5a53cd67d 100644 --- a/atom/common/atom_version.h +++ b/atom/common/atom_version.h @@ -7,7 +7,7 @@ #define ATOM_MAJOR_VERSION 6 #define ATOM_MINOR_VERSION 0 -#define ATOM_PATCH_VERSION 9 +#define ATOM_PATCH_VERSION 10 // clang-format off // #define ATOM_PRE_RELEASE_VERSION // clang-format on diff --git a/package.json b/package.json index 46b1d19feec1d..0d2e4e4b405b9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "electron", - "version": "6.0.9", + "version": "6.0.10", "repository": "https://github.com/electron/electron", "description": "Build cross platform desktop apps with JavaScript, HTML, and CSS", "devDependencies": { From dbd72b226564d37db093c878f7d7bf580e05ef0e Mon Sep 17 00:00:00 2001 From: Shelley Vohr Date: Thu, 19 Sep 2019 06:57:09 -0700 Subject: [PATCH 08/28] docs: improve and add examples for clipboard (#20224) (#20283) * docs: improve and add examples for clipboard * address feedback from jkleinsc review --- docs/api/clipboard.md | 161 +++++++++++++++++++++++++++++++++--------- 1 file changed, 128 insertions(+), 33 deletions(-) diff --git a/docs/api/clipboard.md b/docs/api/clipboard.md index adf64630c2c69..1a673260bd166 100644 --- a/docs/api/clipboard.md +++ b/docs/api/clipboard.md @@ -4,18 +4,12 @@ Process: [Main](../glossary.md#main-process), [Renderer](../glossary.md#renderer-process) -The following example shows how to write a string to the clipboard: - -```javascript -const { clipboard } = require('electron') -clipboard.writeText('Example String') -``` - On Linux, there is also a `selection` clipboard. To manipulate it you need to pass `selection` to each method: ```javascript const { clipboard } = require('electron') + clipboard.writeText('Example String', 'selection') console.log(clipboard.readText('selection')) ``` @@ -28,56 +22,106 @@ The `clipboard` module has the following methods: ### `clipboard.readText([type])` -* `type` String (optional) - Can be `selection` or `clipboard`. `selection` is only available on Linux. +* `type` String (optional) - Can be `selection` or `clipboard`; default is 'clipboard'. `selection` is only available on Linux. Returns `String` - The content in the clipboard as plain text. +```js +const { clipboard } = require('electron') + +clipboard.writeText('hello i am a bit of text!') + +const text = clipboard.readText() +console.log(text) +// hello i am a bit of text!' +``` + ### `clipboard.writeText(text[, type])` * `text` String -* `type` String (optional) - Can be `selection` or `clipboard`. `selection` is only available on Linux. +* `type` String (optional) - Can be `selection` or `clipboard`; default is 'clipboard'. `selection` is only available on Linux. Writes the `text` into the clipboard as plain text. +```js +const { clipboard } = require('electron') + +const text = 'hello i am a bit of text!' +clipboard.writeText(text) +``` + ### `clipboard.readHTML([type])` -* `type` String (optional) - Can be `selection` or `clipboard`. `selection` is only available on Linux. +* `type` String (optional) - Can be `selection` or `clipboard`; default is 'clipboard'. `selection` is only available on Linux. Returns `String` - The content in the clipboard as markup. +```js +const { clipboard } = require('electron') + +clipboard.writeHTML('Hi') +const html = clipboard.readHTML() + +console.log(html) +// Hi +``` + ### `clipboard.writeHTML(markup[, type])` * `markup` String -* `type` String (optional) - Can be `selection` or `clipboard`. `selection` is only available on Linux. +* `type` String (optional) - Can be `selection` or `clipboard`; default is 'clipboard'. `selection` is only available on Linux. Writes `markup` to the clipboard. +```js +const { clipboard } = require('electron') + +clipboard.writeHTML('Hiselection

')) + +const hasFormat = clipboard.has('

selection

') +console.log(hasFormat) +// 'true' or 'false ``` ### `clipboard.read(format)` _Experimental_ @@ -157,14 +214,33 @@ Returns `String` - Reads `format` type from the clipboard. Returns `Buffer` - Reads `format` type from the clipboard. +```js +const { clipboard } = require('electron') + +const buffer = Buffer.from('this is binary', 'utf8') +clipboard.writeBuffer('public.utf8-plain-text', buffer) + +const ret = clipboard.readBuffer('public.utf8-plain-text') + +console.log(buffer.equals(out)) +// true +``` + ### `clipboard.writeBuffer(format, buffer[, type])` _Experimental_ * `format` String * `buffer` Buffer -* `type` String (optional) - Can be `selection` or `clipboard`. `selection` is only available on Linux. +* `type` String (optional) - Can be `selection` or `clipboard`; default is 'clipboard'. `selection` is only available on Linux. Writes the `buffer` into the clipboard as `format`. +```js +const { clipboard } = require('electron') + +const buffer = Buffer.from('writeBuffer', 'utf8') +clipboard.writeBuffer('public.utf8-plain-text', buffer) +``` + ### `clipboard.write(data[, type])` * `data` Object @@ -172,11 +248,30 @@ Writes the `buffer` into the clipboard as `format`. * `html` String (optional) * `image` [NativeImage](native-image.md) (optional) * `rtf` String (optional) - * `bookmark` String (optional) - The title of the url at `text`. -* `type` String (optional) - Can be `selection` or `clipboard`. `selection` is only available on Linux. + * `bookmark` String (optional) - The title of the URL at `text`. +* `type` String (optional) - Can be `selection` or `clipboard`; default is 'clipboard'. `selection` is only available on Linux. -```javascript +Writes `data` to the clipboard. + +```js const { clipboard } = require('electron') -clipboard.write({ text: 'test', html: 'test' }) + +clipboard.write({ + text: 'test', + html: 'Hi', + rtf: '{\\rtf1\\utf8 text}', + bookmark: 'a title' +}) + +console.log(clipboard.readText()) +// 'test' + +console.log(clipboard.readHTML()) +// Hi + +console.log(clipboard.readRTF()) +// '{\\rtf1\\utf8 text}' + +console.log(clipboard.readBookmark()) +// { title: 'a title', url: 'test' } ``` -Writes `data` to the clipboard. From 15c89c8262e42e0f1f5ab36f91676ca3f3b24967 Mon Sep 17 00:00:00 2001 From: Shelley Vohr Date: Thu, 19 Sep 2019 11:29:35 -0700 Subject: [PATCH 09/28] fix: crash when exiting simple fullscreen on macOS (#20144) (#20282) --- atom/browser/native_window_mac.h | 2 +- atom/browser/ui/cocoa/atom_ns_window.mm | 10 ++++++++-- spec/api-browser-window-spec.js | 11 +++++++++++ 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/atom/browser/native_window_mac.h b/atom/browser/native_window_mac.h index 7fcb51713161f..4ed66ecffd35c 100644 --- a/atom/browser/native_window_mac.h +++ b/atom/browser/native_window_mac.h @@ -157,7 +157,7 @@ class NativeWindowMac : public NativeWindow { AtomTouchBar* touch_bar() const { return touch_bar_.get(); } bool zoom_to_page_width() const { return zoom_to_page_width_; } bool fullscreen_window_title() const { return fullscreen_window_title_; } - bool simple_fullscreen() const { return always_simple_fullscreen_; } + bool always_simple_fullscreen() const { return always_simple_fullscreen_; } protected: // views::WidgetDelegate: diff --git a/atom/browser/ui/cocoa/atom_ns_window.mm b/atom/browser/ui/cocoa/atom_ns_window.mm index 9531ab7803f30..4ccd8a15beff1 100644 --- a/atom/browser/ui/cocoa/atom_ns_window.mm +++ b/atom/browser/ui/cocoa/atom_ns_window.mm @@ -174,8 +174,14 @@ - (void)performClose:(id)sender { } - (void)toggleFullScreenMode:(id)sender { - if (shell_->simple_fullscreen()) - shell_->SetSimpleFullScreen(!shell_->IsSimpleFullScreen()); + bool is_simple_fs = shell_->IsSimpleFullScreen(); + bool always_simple_fs = shell_->always_simple_fullscreen(); + + // If we're in simple fullscreen mode and trying to exit it + // we need to ensure we exit it properly to prevent a crash + // with NSWindowStyleMaskTitled mode + if (is_simple_fs || always_simple_fs) + shell_->SetSimpleFullScreen(!is_simple_fs); else [super toggleFullScreen:sender]; } diff --git a/spec/api-browser-window-spec.js b/spec/api-browser-window-spec.js index 53b9e1de64b00..b99bcbfb7687e 100644 --- a/spec/api-browser-window-spec.js +++ b/spec/api-browser-window-spec.js @@ -3090,6 +3090,17 @@ describe('BrowserWindow module', () => { w.setFullScreen(true) }) + it('does not crash when exiting simpleFullScreen', (done) => { + w.destroy() + w = new BrowserWindow() + w.setSimpleFullScreen(true) + + setTimeout(() => { + w.setFullScreen(!w.isFullScreen()) + done() + }, 1000) + }) + it('should not be changed by setKiosk method', (done) => { w.destroy() w = new BrowserWindow() From ce31dc359181f5a2a610bd4ad821a61aef15f905 Mon Sep 17 00:00:00 2001 From: "trop[bot]" <37223003+trop[bot]@users.noreply.github.com> Date: Fri, 20 Sep 2019 10:20:19 -0400 Subject: [PATCH 10/28] ci: actually kill leftover processes on WOA testing (#20292) * ci: only kill WOA processes if they are running (cherry picked from commit 844752cd97c4b010f0467bbfdfe4940934945523) * ci: actually kill leftover processes on WOA testing (cherry picked from commit a76d2d8e53458447579b865febbfaef5b2921f94) --- azure-pipelines-woa.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/azure-pipelines-woa.yml b/azure-pipelines-woa.yml index f347dc121bd9d..352123cd04130 100644 --- a/azure-pipelines-woa.yml +++ b/azure-pipelines-woa.yml @@ -77,8 +77,8 @@ steps: python electron\script\verify-ffmpeg.py --build-dir out\Default --source-root %cd% --ffmpeg-path out\ffmpeg displayName: 'Verify ffmpeg' -- script: | - taskkill /F /IM electron.exe - taskkill /F /IM MicrosoftEdge.exe +- powershell: | + Get-Process | Where Name –Like "electron*" | Stop-Process + Get-Process | Where Name –Like "MicrosoftEdge*" | Stop-Process displayName: 'Kill processes left running from last test run' condition: always() \ No newline at end of file From 0450ee952456b204481b086234d0a7195b1cfe93 Mon Sep 17 00:00:00 2001 From: "trop[bot]" <37223003+trop[bot]@users.noreply.github.com> Date: Fri, 20 Sep 2019 07:44:21 -0700 Subject: [PATCH 11/28] fix: correct 'Entire screen' to ' Entire Screen' (#20301) --- electron_strings.grdp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/electron_strings.grdp b/electron_strings.grdp index 78324e76f5ae8..f827eed718b08 100644 --- a/electron_strings.grdp +++ b/electron_strings.grdp @@ -13,7 +13,7 @@ - Entire screen + Entire Screen {SCREEN_INDEX, plural, =1{Screen #} other{Screen #}} From 886e636b1357d3fe5cb4eaf51889ac89b9e7179a Mon Sep 17 00:00:00 2001 From: Birunthan Mohanathas Date: Mon, 30 Sep 2019 10:46:41 -0700 Subject: [PATCH 12/28] fix: Make the `--disable-color-correct-rendering` switch work again (backport) (#20358) --- .../disable_color_correct_rendering.patch | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/patches/common/chromium/disable_color_correct_rendering.patch b/patches/common/chromium/disable_color_correct_rendering.patch index 40ab3205de110..4a024fdc19039 100644 --- a/patches/common/chromium/disable_color_correct_rendering.patch +++ b/patches/common/chromium/disable_color_correct_rendering.patch @@ -18,6 +18,23 @@ This can be removed once web content (including WebGL) learn how to deal with color spaces. That is being tracked at https://crbug.com/634542 and https://crbug.com/711107. +diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc +index e2921219d253dbb198bd089811cc102aeec594cc..62290a30dee8d51df6e1f771894832b4105c2dd3 100644 +--- a/cc/trees/layer_tree_host_impl.cc ++++ b/cc/trees/layer_tree_host_impl.cc +@@ -1625,6 +1625,12 @@ const gfx::ColorSpace& LayerTreeHostImpl::GetRasterColorSpace() const { + + const gfx::ColorSpace& LayerTreeHostImpl::GetRasterColorSpaceAndId( + int* id) const { ++ if (!settings_.enable_color_correct_rendering) { ++ static gfx::ColorSpace invalid_color_space; ++ *id = -1; ++ return invalid_color_space; ++ } ++ + const gfx::ColorSpace* result = nullptr; + // The pending tree will have the most recently updated color space, so + // prefer that. diff --git a/cc/trees/layer_tree_settings.h b/cc/trees/layer_tree_settings.h index 092fb1b7ea3626b7649472c35ec20bf1a6aaf4cd..fed8dd322faba387ebd0508228f847766a76011e 100644 --- a/cc/trees/layer_tree_settings.h @@ -248,6 +265,42 @@ index a450561913e274b36ece94c22bae7b14930db36e..3b9a0a5cef0ec2fc02d4e2d1b0e4e1da // Checkerimaging is not supported for synchronous single-threaded mode, which // is what the renderer uses if its not threaded. settings.enable_checker_imaging = +diff --git a/third_party/blink/renderer/platform/graphics/canvas_color_params.cc b/third_party/blink/renderer/platform/graphics/canvas_color_params.cc +index 9e5b58dc78b05491d1154b25b5b9c8c55b883b07..8524fd9f090fbb5cb0e37b1a6205d77917e9f221 100644 +--- a/third_party/blink/renderer/platform/graphics/canvas_color_params.cc ++++ b/third_party/blink/renderer/platform/graphics/canvas_color_params.cc +@@ -11,6 +11,7 @@ + #include "third_party/khronos/GLES3/gl3.h" + #include "third_party/skia/include/core/SkSurfaceProps.h" + #include "ui/gfx/color_space.h" ++#include "ui/gfx/switches.h" + + namespace blink { + +@@ -81,6 +82,11 @@ uint8_t CanvasColorParams::BytesPerPixel() const { + } + + gfx::ColorSpace CanvasColorParams::GetSamplerGfxColorSpace() const { ++ auto* cmd_line = base::CommandLine::ForCurrentProcess(); ++ if (cmd_line->HasSwitch(switches::kDisableColorCorrectRendering)) { ++ return gfx::ColorSpace(); ++ } ++ + gfx::ColorSpace::PrimaryID primary_id = GetPrimaryID(color_space_); + + // TODO(ccameron): This needs to take into account whether or not this texture +@@ -94,6 +100,11 @@ gfx::ColorSpace CanvasColorParams::GetSamplerGfxColorSpace() const { + } + + gfx::ColorSpace CanvasColorParams::GetStorageGfxColorSpace() const { ++ auto* cmd_line = base::CommandLine::ForCurrentProcess(); ++ if (cmd_line->HasSwitch(switches::kDisableColorCorrectRendering)) { ++ return gfx::ColorSpace(); ++ } ++ + gfx::ColorSpace::PrimaryID primary_id = GetPrimaryID(color_space_); + + gfx::ColorSpace::TransferID transfer_id = diff --git a/ui/gfx/mac/io_surface.cc b/ui/gfx/mac/io_surface.cc index 88ec94963569588ed2882193a28197879dcb1090..eae37577bc9b1872c0162f55de218553eed61587 100644 --- a/ui/gfx/mac/io_surface.cc From e472efbea20097de9f78a1e68b16030087c28323 Mon Sep 17 00:00:00 2001 From: "trop[bot]" <37223003+trop[bot]@users.noreply.github.com> Date: Tue, 1 Oct 2019 15:06:23 -0400 Subject: [PATCH 13/28] fix: correctly crash when there is no crashReporter (#20396) * fix: correctly crash when there is no crashReporter * test: correctly crash when there is crashReporter --- atom/common/crash_reporter/crash_reporter_win.cc | 12 ++++++++++-- spec/api-crash-reporter-spec.js | 10 ++++++++++ spec/fixtures/crash-app/main.js | 5 +++++ spec/fixtures/crash-app/package.json | 4 ++++ 4 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 spec/fixtures/crash-app/main.js create mode 100644 spec/fixtures/crash-app/package.json diff --git a/atom/common/crash_reporter/crash_reporter_win.cc b/atom/common/crash_reporter/crash_reporter_win.cc index 6d48b9533c2ef..34d7999d8d23b 100644 --- a/atom/common/crash_reporter/crash_reporter_win.cc +++ b/atom/common/crash_reporter/crash_reporter_win.cc @@ -28,9 +28,17 @@ namespace { #if defined(_WIN64) int CrashForException(EXCEPTION_POINTERS* info) { auto* reporter = crash_reporter::CrashReporterWin::GetInstance(); - if (reporter->IsInitialized()) + if (reporter->IsInitialized()) { reporter->GetCrashpadClient().DumpAndCrash(info); - return EXCEPTION_CONTINUE_SEARCH; + return EXCEPTION_CONTINUE_SEARCH; + } + + // When there is exception and we do not have crashReporter set up, we just + // let the execution continue and crash, which is the default behavior. + // + // We must not return EXCEPTION_CONTINUE_SEARCH here, as it would end up with + // busy loop when there is no exception handler in the program. + return EXCEPTION_CONTINUE_EXECUTION; } #endif diff --git a/spec/api-crash-reporter-spec.js b/spec/api-crash-reporter-spec.js index bbff0a25cd79e..2a2046ef56640 100644 --- a/spec/api-crash-reporter-spec.js +++ b/spec/api-crash-reporter-spec.js @@ -373,6 +373,16 @@ describe('crashReporter module', () => { assert(!('hello' in crashReporter.getParameters())) }) }) + + describe('when not started', () => { + it('does not prevent process from crashing', (done) => { + const appPath = path.join(fixtures, 'api', 'cookie-app') + const appProcess = childProcess.spawn(process.execPath, [appPath]) + appProcess.once('close', () => { + done() + }) + }) + }) }) const waitForCrashReport = () => { diff --git a/spec/fixtures/crash-app/main.js b/spec/fixtures/crash-app/main.js new file mode 100644 index 0000000000000..e279216218822 --- /dev/null +++ b/spec/fixtures/crash-app/main.js @@ -0,0 +1,5 @@ +const { app } = require('electron') + +app.on('ready', () => { + process.crash() +}) diff --git a/spec/fixtures/crash-app/package.json b/spec/fixtures/crash-app/package.json new file mode 100644 index 0000000000000..e03fc08f1f79f --- /dev/null +++ b/spec/fixtures/crash-app/package.json @@ -0,0 +1,4 @@ +{ + "name": "electron-crash-app", + "main": "main.js" +} From 4e417e21b8700772627753916032648c524f27e2 Mon Sep 17 00:00:00 2001 From: Electron Bot Date: Tue, 1 Oct 2019 12:08:35 -0700 Subject: [PATCH 14/28] Bump v6.0.11 --- ELECTRON_VERSION | 2 +- atom/browser/resources/mac/Info.plist | 4 ++-- atom/browser/resources/win/atom.rc | 8 ++++---- atom/common/atom_version.h | 2 +- package.json | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ELECTRON_VERSION b/ELECTRON_VERSION index c5a1e4c4361df..cb372c07bfa82 100644 --- a/ELECTRON_VERSION +++ b/ELECTRON_VERSION @@ -1 +1 @@ -6.0.10 \ No newline at end of file +6.0.11 \ No newline at end of file diff --git a/atom/browser/resources/mac/Info.plist b/atom/browser/resources/mac/Info.plist index 47f87cb46f686..d3efa6a713058 100644 --- a/atom/browser/resources/mac/Info.plist +++ b/atom/browser/resources/mac/Info.plist @@ -17,9 +17,9 @@ CFBundleIconFile electron.icns CFBundleVersion - 6.0.10 + 6.0.11 CFBundleShortVersionString - 6.0.10 + 6.0.11 LSApplicationCategoryType public.app-category.developer-tools LSMinimumSystemVersion diff --git a/atom/browser/resources/win/atom.rc b/atom/browser/resources/win/atom.rc index 6f5ebfccfafd7..f378c8dc44a2b 100644 --- a/atom/browser/resources/win/atom.rc +++ b/atom/browser/resources/win/atom.rc @@ -50,8 +50,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 6,0,10,0 - PRODUCTVERSION 6,0,10,0 + FILEVERSION 6,0,11,0 + PRODUCTVERSION 6,0,11,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -68,12 +68,12 @@ BEGIN BEGIN VALUE "CompanyName", "GitHub, Inc." VALUE "FileDescription", "Electron" - VALUE "FileVersion", "6.0.10" + VALUE "FileVersion", "6.0.11" VALUE "InternalName", "electron.exe" VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved." VALUE "OriginalFilename", "electron.exe" VALUE "ProductName", "Electron" - VALUE "ProductVersion", "6.0.10" + VALUE "ProductVersion", "6.0.11" VALUE "SquirrelAwareVersion", "1" END END diff --git a/atom/common/atom_version.h b/atom/common/atom_version.h index 182a5a53cd67d..2929e61ed841d 100644 --- a/atom/common/atom_version.h +++ b/atom/common/atom_version.h @@ -7,7 +7,7 @@ #define ATOM_MAJOR_VERSION 6 #define ATOM_MINOR_VERSION 0 -#define ATOM_PATCH_VERSION 10 +#define ATOM_PATCH_VERSION 11 // clang-format off // #define ATOM_PRE_RELEASE_VERSION // clang-format on diff --git a/package.json b/package.json index 0d2e4e4b405b9..f332706dc9e8b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "electron", - "version": "6.0.10", + "version": "6.0.11", "repository": "https://github.com/electron/electron", "description": "Build cross platform desktop apps with JavaScript, HTML, and CSS", "devDependencies": { From 99a0581d0d0e6735abc6ab5dd4b4af97b61fa7d8 Mon Sep 17 00:00:00 2001 From: Milan Burda Date: Wed, 2 Oct 2019 11:03:18 +0200 Subject: [PATCH 15/28] fix: allow paths to asar archives to contain the .asar extension in directories (#20342) (#20402) --- atom/common/api/atom_api_asar.cc | 16 + atom/common/asar/asar_util.cc | 20 +- atom/common/asar/asar_util.h | 3 +- lib/common/asar.js | 19 +- spec/api-protocol-spec.js | 4 +- spec/asar-spec.js | 311 +++++++++--------- spec/fixtures/module/no-asar.js | 2 +- spec/fixtures/no-proprietary-codecs.js | 2 +- spec/fixtures/{asar => test.asar}/a.asar | Bin spec/fixtures/{asar => test.asar}/echo.asar | Bin spec/fixtures/{asar => test.asar}/empty.asar | Bin spec/fixtures/{asar => test.asar}/file | 0 spec/fixtures/{asar => test.asar}/logo.asar | Bin spec/fixtures/{asar => test.asar}/script.asar | Bin spec/fixtures/{asar => test.asar}/unpack.asar | Bin .../unpack.asar.unpacked/a.txt | 0 .../unpack.asar.unpacked/atom.png | Bin spec/fixtures/{asar => test.asar}/video.asar | Bin spec/fixtures/{asar => test.asar}/web.asar | Bin 19 files changed, 196 insertions(+), 181 deletions(-) rename spec/fixtures/{asar => test.asar}/a.asar (100%) rename spec/fixtures/{asar => test.asar}/echo.asar (100%) rename spec/fixtures/{asar => test.asar}/empty.asar (100%) rename spec/fixtures/{asar => test.asar}/file (100%) rename spec/fixtures/{asar => test.asar}/logo.asar (100%) rename spec/fixtures/{asar => test.asar}/script.asar (100%) rename spec/fixtures/{asar => test.asar}/unpack.asar (100%) rename spec/fixtures/{asar => test.asar}/unpack.asar.unpacked/a.txt (100%) rename spec/fixtures/{asar => test.asar}/unpack.asar.unpacked/atom.png (100%) rename spec/fixtures/{asar => test.asar}/video.asar (100%) rename spec/fixtures/{asar => test.asar}/web.asar (100%) diff --git a/atom/common/api/atom_api_asar.cc b/atom/common/api/atom_api_asar.cc index 00fad1275f297..0551bc8834a1b 100644 --- a/atom/common/api/atom_api_asar.cc +++ b/atom/common/api/atom_api_asar.cc @@ -7,6 +7,7 @@ #include #include "atom/common/asar/archive.h" +#include "atom/common/asar/asar_util.h" #include "atom/common/native_mate_converters/callback.h" #include "atom/common/native_mate_converters/file_path_converter.h" #include "atom/common/node_includes.h" @@ -127,12 +128,27 @@ void InitAsarSupport(v8::Isolate* isolate, v8::Local require) { &asar_init_params, &asar_init_args, nullptr); } +v8::Local SplitPath(v8::Isolate* isolate, + const base::FilePath& path) { + mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate); + base::FilePath asar_path, file_path; + if (asar::GetAsarArchivePath(path, &asar_path, &file_path, true)) { + dict.Set("isAsar", true); + dict.Set("asarPath", asar_path); + dict.Set("filePath", file_path); + } else { + dict.Set("isAsar", false); + } + return dict.GetHandle(); +} + void Initialize(v8::Local exports, v8::Local unused, v8::Local context, void* priv) { mate::Dictionary dict(context->GetIsolate(), exports); dict.SetMethod("createArchive", &Archive::Create); + dict.SetMethod("splitPath", &SplitPath); dict.SetMethod("initAsarSupport", &InitAsarSupport); } diff --git a/atom/common/asar/asar_util.cc b/atom/common/asar/asar_util.cc index b564a75dc7223..7934c3183a2e9 100644 --- a/atom/common/asar/asar_util.cc +++ b/atom/common/asar/asar_util.cc @@ -13,6 +13,7 @@ #include "base/lazy_instance.h" #include "base/stl_util.h" #include "base/threading/thread_local.h" +#include "base/threading/thread_restrictions.h" namespace asar { @@ -25,6 +26,17 @@ base::LazyInstance>::Leaky const base::FilePath::CharType kAsarExtension[] = FILE_PATH_LITERAL(".asar"); +std::map g_is_directory_cache; + +bool IsDirectoryCached(const base::FilePath& path) { + auto it = g_is_directory_cache.find(path); + if (it != g_is_directory_cache.end()) { + return it->second; + } + base::ThreadRestrictions::ScopedAllowIO allow_io; + return g_is_directory_cache[path] = base::DirectoryExists(path); +} + } // namespace std::shared_ptr GetOrCreateAsarArchive(const base::FilePath& path) { @@ -47,11 +59,12 @@ void ClearArchives() { bool GetAsarArchivePath(const base::FilePath& full_path, base::FilePath* asar_path, - base::FilePath* relative_path) { + base::FilePath* relative_path, + bool allow_root) { base::FilePath iter = full_path; while (true) { base::FilePath dirname = iter.DirName(); - if (iter.MatchesExtension(kAsarExtension)) + if (iter.MatchesExtension(kAsarExtension) && !IsDirectoryCached(iter)) break; else if (iter == dirname) return false; @@ -59,7 +72,8 @@ bool GetAsarArchivePath(const base::FilePath& full_path, } base::FilePath tail; - if (!iter.AppendRelativePath(full_path, &tail)) + if (!((allow_root && iter == full_path) || + iter.AppendRelativePath(full_path, &tail))) return false; *asar_path = iter; diff --git a/atom/common/asar/asar_util.h b/atom/common/asar/asar_util.h index 90ffb9b46a300..f934845e514d0 100644 --- a/atom/common/asar/asar_util.h +++ b/atom/common/asar/asar_util.h @@ -25,7 +25,8 @@ void ClearArchives(); // Separates the path to Archive out. bool GetAsarArchivePath(const base::FilePath& full_path, base::FilePath* asar_path, - base::FilePath* relative_path); + base::FilePath* relative_path, + bool allow_root = false); // Same with base::ReadFileToString but supports asar Archive. bool ReadFileToString(const base::FilePath& path, std::string* contents); diff --git a/lib/common/asar.js b/lib/common/asar.js index f0977753d0704..caf18c2c4c9c7 100644 --- a/lib/common/asar.js +++ b/lib/common/asar.js @@ -40,8 +40,6 @@ return newArchive } - const ASAR_EXTENSION = '.asar' - // Separate asar package's path from full path. const splitPath = archivePathOrBuffer => { // Shortcut for disabled asar. @@ -54,22 +52,7 @@ } if (typeof archivePath !== 'string') return { isAsar: false } - if (archivePath.endsWith(ASAR_EXTENSION)) { - return { isAsar: true, asarPath: archivePath, filePath: '' } - } - - archivePath = path.normalize(archivePath) - const index = archivePath.lastIndexOf(`${ASAR_EXTENSION}${path.sep}`) - if (index === -1) return { isAsar: false } - - // E.g. for "//some/path/to/archive.asar/then/internal.file"... - return { - isAsar: true, - // "//some/path/to/archive.asar" - asarPath: archivePath.substr(0, index + ASAR_EXTENSION.length), - // "then/internal.file" (with a path separator excluded) - filePath: archivePath.substr(index + ASAR_EXTENSION.length + 1) - } + return asar.splitPath(path.normalize(archivePath)) } // Convert asar archive's Stats object to fs's Stats object. diff --git a/spec/api-protocol-spec.js b/spec/api-protocol-spec.js index 8b53567894b41..dec87a03c3c91 100644 --- a/spec/api-protocol-spec.js +++ b/spec/api-protocol-spec.js @@ -280,7 +280,7 @@ describe('protocol module', () => { }) describe('protocol.registerFileProtocol', () => { - const filePath = path.join(__dirname, 'fixtures', 'asar', 'a.asar', 'file1') + const filePath = path.join(__dirname, 'fixtures', 'test.asar', 'a.asar', 'file1') const fileContent = require('fs').readFileSync(filePath) const normalPath = path.join(__dirname, 'fixtures', 'pages', 'a.html') const normalContent = require('fs').readFileSync(normalPath) @@ -394,7 +394,7 @@ describe('protocol module', () => { }) it('fails when sending unexist-file', (done) => { - const fakeFilePath = path.join(__dirname, 'fixtures', 'asar', 'a.asar', 'not-exist') + const fakeFilePath = path.join(__dirname, 'fixtures', 'test.asar', 'a.asar', 'not-exist') const handler = (request, callback) => callback(fakeFilePath) protocol.registerFileProtocol(protocolName, handler, (error) => { if (error) return done(error) diff --git a/spec/asar-spec.js b/spec/asar-spec.js index a8a7b4aa07246..37e13a93d1ba4 100644 --- a/spec/asar-spec.js +++ b/spec/asar-spec.js @@ -28,10 +28,11 @@ async function expectToThrowErrorWithCode (func, code) { describe('asar package', function () { const fixtures = path.join(__dirname, 'fixtures') + const asarDir = path.join(fixtures, 'test.asar') describe('node api', function () { it('supports paths specified as a Buffer', function () { - const file = Buffer.from(path.join(fixtures, 'asar', 'a.asar', 'file1')) + const file = Buffer.from(path.join(asarDir, 'a.asar', 'file1')) assert.strictEqual(fs.existsSync(file), true) }) @@ -45,35 +46,35 @@ describe('asar package', function () { }) it('reads a normal file', function () { - const file1 = path.join(fixtures, 'asar', 'a.asar', 'file1') + const file1 = path.join(asarDir, 'a.asar', 'file1') assert.strictEqual(fs.readFileSync(file1).toString().trim(), 'file1') - const file2 = path.join(fixtures, 'asar', 'a.asar', 'file2') + const file2 = path.join(asarDir, 'a.asar', 'file2') assert.strictEqual(fs.readFileSync(file2).toString().trim(), 'file2') - const file3 = path.join(fixtures, 'asar', 'a.asar', 'file3') + const file3 = path.join(asarDir, 'a.asar', 'file3') assert.strictEqual(fs.readFileSync(file3).toString().trim(), 'file3') }) it('reads from a empty file', function () { - const file = path.join(fixtures, 'asar', 'empty.asar', 'file1') + const file = path.join(asarDir, 'empty.asar', 'file1') const buffer = fs.readFileSync(file) assert.strictEqual(buffer.length, 0) assert.strictEqual(buffer.toString(), '') }) it('reads a linked file', function () { - const p = path.join(fixtures, 'asar', 'a.asar', 'link1') + const p = path.join(asarDir, 'a.asar', 'link1') assert.strictEqual(fs.readFileSync(p).toString().trim(), 'file1') }) it('reads a file from linked directory', function () { - const p1 = path.join(fixtures, 'asar', 'a.asar', 'link2', 'file1') + const p1 = path.join(asarDir, 'a.asar', 'link2', 'file1') assert.strictEqual(fs.readFileSync(p1).toString().trim(), 'file1') - const p2 = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2', 'file1') + const p2 = path.join(asarDir, 'a.asar', 'link2', 'link2', 'file1') assert.strictEqual(fs.readFileSync(p2).toString().trim(), 'file1') }) it('throws ENOENT error when can not find file', function () { - const p = path.join(fixtures, 'asar', 'a.asar', 'not-exist') + const p = path.join(asarDir, 'a.asar', 'not-exist') const throws = function () { fs.readFileSync(p) } @@ -81,7 +82,7 @@ describe('asar package', function () { }) it('passes ENOENT error to callback when can not find file', function () { - const p = path.join(fixtures, 'asar', 'a.asar', 'not-exist') + const p = path.join(asarDir, 'a.asar', 'not-exist') let async = false fs.readFile(p, function (e) { assert(async) @@ -91,14 +92,14 @@ describe('asar package', function () { }) it('reads a normal file with unpacked files', function () { - const p = path.join(fixtures, 'asar', 'unpack.asar', 'a.txt') + const p = path.join(asarDir, 'unpack.asar', 'a.txt') assert.strictEqual(fs.readFileSync(p).toString().trim(), 'a') }) }) describe('fs.readFile', function () { it('reads a normal file', function (done) { - const p = path.join(fixtures, 'asar', 'a.asar', 'file1') + const p = path.join(asarDir, 'a.asar', 'file1') fs.readFile(p, function (err, content) { assert.strictEqual(err, null) assert.strictEqual(String(content).trim(), 'file1') @@ -107,7 +108,7 @@ describe('asar package', function () { }) it('reads from a empty file', function (done) { - const p = path.join(fixtures, 'asar', 'empty.asar', 'file1') + const p = path.join(asarDir, 'empty.asar', 'file1') fs.readFile(p, function (err, content) { assert.strictEqual(err, null) assert.strictEqual(String(content), '') @@ -116,7 +117,7 @@ describe('asar package', function () { }) it('reads from a empty file with encoding', function (done) { - const p = path.join(fixtures, 'asar', 'empty.asar', 'file1') + const p = path.join(asarDir, 'empty.asar', 'file1') fs.readFile(p, 'utf8', function (err, content) { assert.strictEqual(err, null) assert.strictEqual(content, '') @@ -125,7 +126,7 @@ describe('asar package', function () { }) it('reads a linked file', function (done) { - const p = path.join(fixtures, 'asar', 'a.asar', 'link1') + const p = path.join(asarDir, 'a.asar', 'link1') fs.readFile(p, function (err, content) { assert.strictEqual(err, null) assert.strictEqual(String(content).trim(), 'file1') @@ -134,7 +135,7 @@ describe('asar package', function () { }) it('reads a file from linked directory', function (done) { - const p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2', 'file1') + const p = path.join(asarDir, 'a.asar', 'link2', 'link2', 'file1') fs.readFile(p, function (err, content) { assert.strictEqual(err, null) assert.strictEqual(String(content).trim(), 'file1') @@ -143,7 +144,7 @@ describe('asar package', function () { }) it('throws ENOENT error when can not find file', function (done) { - const p = path.join(fixtures, 'asar', 'a.asar', 'not-exist') + const p = path.join(asarDir, 'a.asar', 'not-exist') fs.readFile(p, function (err) { assert.strictEqual(err.code, 'ENOENT') done() @@ -153,44 +154,44 @@ describe('asar package', function () { describe('fs.promises.readFile', function () { it('reads a normal file', async function () { - const p = path.join(fixtures, 'asar', 'a.asar', 'file1') + const p = path.join(asarDir, 'a.asar', 'file1') const content = await fs.promises.readFile(p) assert.strictEqual(String(content).trim(), 'file1') }) it('reads from a empty file', async function () { - const p = path.join(fixtures, 'asar', 'empty.asar', 'file1') + const p = path.join(asarDir, 'empty.asar', 'file1') const content = await fs.promises.readFile(p) assert.strictEqual(String(content), '') }) it('reads from a empty file with encoding', async function () { - const p = path.join(fixtures, 'asar', 'empty.asar', 'file1') + const p = path.join(asarDir, 'empty.asar', 'file1') const content = await fs.promises.readFile(p, 'utf8') assert.strictEqual(content, '') }) it('reads a linked file', async function () { - const p = path.join(fixtures, 'asar', 'a.asar', 'link1') + const p = path.join(asarDir, 'a.asar', 'link1') const content = await fs.promises.readFile(p) assert.strictEqual(String(content).trim(), 'file1') }) it('reads a file from linked directory', async function () { - const p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2', 'file1') + const p = path.join(asarDir, 'a.asar', 'link2', 'link2', 'file1') const content = await fs.promises.readFile(p) assert.strictEqual(String(content).trim(), 'file1') }) it('throws ENOENT error when can not find file', async function () { - const p = path.join(fixtures, 'asar', 'a.asar', 'not-exist') + const p = path.join(asarDir, 'a.asar', 'not-exist') await expectToThrowErrorWithCode(() => fs.promises.readFile(p), 'ENOENT') }) }) describe('fs.copyFile', function () { it('copies a normal file', function (done) { - const p = path.join(fixtures, 'asar', 'a.asar', 'file1') + const p = path.join(asarDir, 'a.asar', 'file1') const dest = temp.path() fs.copyFile(p, dest, function (err) { assert.strictEqual(err, null) @@ -200,7 +201,7 @@ describe('asar package', function () { }) it('copies a unpacked file', function (done) { - const p = path.join(fixtures, 'asar', 'unpack.asar', 'a.txt') + const p = path.join(asarDir, 'unpack.asar', 'a.txt') const dest = temp.path() fs.copyFile(p, dest, function (err) { assert.strictEqual(err, null) @@ -212,14 +213,14 @@ describe('asar package', function () { describe('fs.promises.copyFile', function () { it('copies a normal file', async function () { - const p = path.join(fixtures, 'asar', 'a.asar', 'file1') + const p = path.join(asarDir, 'a.asar', 'file1') const dest = temp.path() await fs.promises.copyFile(p, dest) assert(fs.readFileSync(p).equals(fs.readFileSync(dest))) }) it('copies a unpacked file', async function () { - const p = path.join(fixtures, 'asar', 'unpack.asar', 'a.txt') + const p = path.join(asarDir, 'unpack.asar', 'a.txt') const dest = temp.path() await fs.promises.copyFile(p, dest) assert(fs.readFileSync(p).equals(fs.readFileSync(dest))) @@ -228,14 +229,14 @@ describe('asar package', function () { describe('fs.copyFileSync', function () { it('copies a normal file', function () { - const p = path.join(fixtures, 'asar', 'a.asar', 'file1') + const p = path.join(asarDir, 'a.asar', 'file1') const dest = temp.path() fs.copyFileSync(p, dest) assert(fs.readFileSync(p).equals(fs.readFileSync(dest))) }) it('copies a unpacked file', function () { - const p = path.join(fixtures, 'asar', 'unpack.asar', 'a.txt') + const p = path.join(asarDir, 'unpack.asar', 'a.txt') const dest = temp.path() fs.copyFileSync(p, dest) assert(fs.readFileSync(p).equals(fs.readFileSync(dest))) @@ -244,13 +245,13 @@ describe('asar package', function () { describe('fs.lstatSync', function () { it('handles path with trailing slash correctly', function () { - const p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2', 'file1') + const p = path.join(asarDir, 'a.asar', 'link2', 'link2', 'file1') fs.lstatSync(p) fs.lstatSync(p + '/') }) it('returns information of root', function () { - const p = path.join(fixtures, 'asar', 'a.asar') + const p = path.join(asarDir, 'a.asar') const stats = fs.lstatSync(p) assert.strictEqual(stats.isFile(), false) assert.strictEqual(stats.isDirectory(), true) @@ -259,7 +260,7 @@ describe('asar package', function () { }) it('returns information of root with stats as bigint', function () { - const p = path.join(fixtures, 'asar', 'a.asar') + const p = path.join(asarDir, 'a.asar') const stats = fs.lstatSync(p, { bigint: false }) assert.strictEqual(stats.isFile(), false) assert.strictEqual(stats.isDirectory(), true) @@ -271,7 +272,7 @@ describe('asar package', function () { const ref2 = ['file1', 'file2', 'file3', path.join('dir1', 'file1'), path.join('link2', 'file1')] for (let j = 0, len = ref2.length; j < len; j++) { const file = ref2[j] - const p = path.join(fixtures, 'asar', 'a.asar', file) + const p = path.join(asarDir, 'a.asar', file) const stats = fs.lstatSync(p) assert.strictEqual(stats.isFile(), true) assert.strictEqual(stats.isDirectory(), false) @@ -284,7 +285,7 @@ describe('asar package', function () { const ref2 = ['dir1', 'dir2', 'dir3'] for (let j = 0, len = ref2.length; j < len; j++) { const file = ref2[j] - const p = path.join(fixtures, 'asar', 'a.asar', file) + const p = path.join(asarDir, 'a.asar', file) const stats = fs.lstatSync(p) assert.strictEqual(stats.isFile(), false) assert.strictEqual(stats.isDirectory(), true) @@ -297,7 +298,7 @@ describe('asar package', function () { const ref2 = ['link1', path.join('dir1', 'link1'), path.join('link2', 'link2')] for (let j = 0, len = ref2.length; j < len; j++) { const file = ref2[j] - const p = path.join(fixtures, 'asar', 'a.asar', file) + const p = path.join(asarDir, 'a.asar', file) const stats = fs.lstatSync(p) assert.strictEqual(stats.isFile(), false) assert.strictEqual(stats.isDirectory(), false) @@ -310,7 +311,7 @@ describe('asar package', function () { const ref2 = ['link2', path.join('dir1', 'link2'), path.join('link2', 'link2')] for (let j = 0, len = ref2.length; j < len; j++) { const file = ref2[j] - const p = path.join(fixtures, 'asar', 'a.asar', file) + const p = path.join(asarDir, 'a.asar', file) const stats = fs.lstatSync(p) assert.strictEqual(stats.isFile(), false) assert.strictEqual(stats.isDirectory(), false) @@ -323,7 +324,7 @@ describe('asar package', function () { const ref2 = ['file4', 'file5', path.join('dir1', 'file4')] for (let j = 0, len = ref2.length; j < len; j++) { const file = ref2[j] - const p = path.join(fixtures, 'asar', 'a.asar', file) + const p = path.join(asarDir, 'a.asar', file) const throws = function () { fs.lstatSync(p) } @@ -334,12 +335,12 @@ describe('asar package', function () { describe('fs.lstat', function () { it('handles path with trailing slash correctly', function (done) { - const p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2', 'file1') + const p = path.join(asarDir, 'a.asar', 'link2', 'link2', 'file1') fs.lstat(p + '/', done) }) it('returns information of root', function (done) { - const p = path.join(fixtures, 'asar', 'a.asar') + const p = path.join(asarDir, 'a.asar') fs.lstat(p, function (err, stats) { assert.strictEqual(err, null) assert.strictEqual(stats.isFile(), false) @@ -351,7 +352,7 @@ describe('asar package', function () { }) it('returns information of root with stats as bigint', function (done) { - const p = path.join(fixtures, 'asar', 'a.asar') + const p = path.join(asarDir, 'a.asar') fs.lstat(p, { bigint: false }, function (err, stats) { assert.strictEqual(err, null) assert.strictEqual(stats.isFile(), false) @@ -363,7 +364,7 @@ describe('asar package', function () { }) it('returns information of a normal file', function (done) { - const p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'file1') + const p = path.join(asarDir, 'a.asar', 'link2', 'file1') fs.lstat(p, function (err, stats) { assert.strictEqual(err, null) assert.strictEqual(stats.isFile(), true) @@ -375,7 +376,7 @@ describe('asar package', function () { }) it('returns information of a normal directory', function (done) { - const p = path.join(fixtures, 'asar', 'a.asar', 'dir1') + const p = path.join(asarDir, 'a.asar', 'dir1') fs.lstat(p, function (err, stats) { assert.strictEqual(err, null) assert.strictEqual(stats.isFile(), false) @@ -387,7 +388,7 @@ describe('asar package', function () { }) it('returns information of a linked file', function (done) { - const p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link1') + const p = path.join(asarDir, 'a.asar', 'link2', 'link1') fs.lstat(p, function (err, stats) { assert.strictEqual(err, null) assert.strictEqual(stats.isFile(), false) @@ -399,7 +400,7 @@ describe('asar package', function () { }) it('returns information of a linked directory', function (done) { - const p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2') + const p = path.join(asarDir, 'a.asar', 'link2', 'link2') fs.lstat(p, function (err, stats) { assert.strictEqual(err, null) assert.strictEqual(stats.isFile(), false) @@ -411,7 +412,7 @@ describe('asar package', function () { }) it('throws ENOENT error when can not find file', function (done) { - const p = path.join(fixtures, 'asar', 'a.asar', 'file4') + const p = path.join(asarDir, 'a.asar', 'file4') fs.lstat(p, function (err) { assert.strictEqual(err.code, 'ENOENT') done() @@ -421,12 +422,12 @@ describe('asar package', function () { describe('fs.promises.lstat', function () { it('handles path with trailing slash correctly', async function () { - const p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2', 'file1') + const p = path.join(asarDir, 'a.asar', 'link2', 'link2', 'file1') await fs.promises.lstat(p + '/') }) it('returns information of root', async function () { - const p = path.join(fixtures, 'asar', 'a.asar') + const p = path.join(asarDir, 'a.asar') const stats = await fs.promises.lstat(p) assert.strictEqual(stats.isFile(), false) assert.strictEqual(stats.isDirectory(), true) @@ -435,7 +436,7 @@ describe('asar package', function () { }) it('returns information of root with stats as bigint', async function () { - const p = path.join(fixtures, 'asar', 'a.asar') + const p = path.join(asarDir, 'a.asar') const stats = await fs.promises.lstat(p, { bigint: false }) assert.strictEqual(stats.isFile(), false) assert.strictEqual(stats.isDirectory(), true) @@ -444,7 +445,7 @@ describe('asar package', function () { }) it('returns information of a normal file', async function () { - const p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'file1') + const p = path.join(asarDir, 'a.asar', 'link2', 'file1') const stats = await fs.promises.lstat(p) assert.strictEqual(stats.isFile(), true) assert.strictEqual(stats.isDirectory(), false) @@ -453,7 +454,7 @@ describe('asar package', function () { }) it('returns information of a normal directory', async function () { - const p = path.join(fixtures, 'asar', 'a.asar', 'dir1') + const p = path.join(asarDir, 'a.asar', 'dir1') const stats = await fs.promises.lstat(p) assert.strictEqual(stats.isFile(), false) assert.strictEqual(stats.isDirectory(), true) @@ -462,7 +463,7 @@ describe('asar package', function () { }) it('returns information of a linked file', async function () { - const p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link1') + const p = path.join(asarDir, 'a.asar', 'link2', 'link1') const stats = await fs.promises.lstat(p) assert.strictEqual(stats.isFile(), false) assert.strictEqual(stats.isDirectory(), false) @@ -471,7 +472,7 @@ describe('asar package', function () { }) it('returns information of a linked directory', async function () { - const p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2') + const p = path.join(asarDir, 'a.asar', 'link2', 'link2') const stats = await fs.promises.lstat(p) assert.strictEqual(stats.isFile(), false) assert.strictEqual(stats.isDirectory(), false) @@ -480,56 +481,56 @@ describe('asar package', function () { }) it('throws ENOENT error when can not find file', async function () { - const p = path.join(fixtures, 'asar', 'a.asar', 'file4') + const p = path.join(asarDir, 'a.asar', 'file4') await expectToThrowErrorWithCode(() => fs.promises.lstat(p), 'ENOENT') }) }) describe('fs.realpathSync', () => { it('returns real path root', () => { - const parent = fs.realpathSync(path.join(fixtures, 'asar')) + const parent = fs.realpathSync(asarDir) const p = 'a.asar' const r = fs.realpathSync(path.join(parent, p)) assert.strictEqual(r, path.join(parent, p)) }) it('returns real path of a normal file', () => { - const parent = fs.realpathSync(path.join(fixtures, 'asar')) + const parent = fs.realpathSync(asarDir) const p = path.join('a.asar', 'file1') const r = fs.realpathSync(path.join(parent, p)) assert.strictEqual(r, path.join(parent, p)) }) it('returns real path of a normal directory', () => { - const parent = fs.realpathSync(path.join(fixtures, 'asar')) + const parent = fs.realpathSync(asarDir) const p = path.join('a.asar', 'dir1') const r = fs.realpathSync(path.join(parent, p)) assert.strictEqual(r, path.join(parent, p)) }) it('returns real path of a linked file', () => { - const parent = fs.realpathSync(path.join(fixtures, 'asar')) + const parent = fs.realpathSync(asarDir) const p = path.join('a.asar', 'link2', 'link1') const r = fs.realpathSync(path.join(parent, p)) assert.strictEqual(r, path.join(parent, 'a.asar', 'file1')) }) it('returns real path of a linked directory', () => { - const parent = fs.realpathSync(path.join(fixtures, 'asar')) + const parent = fs.realpathSync(asarDir) const p = path.join('a.asar', 'link2', 'link2') const r = fs.realpathSync(path.join(parent, p)) assert.strictEqual(r, path.join(parent, 'a.asar', 'dir1')) }) it('returns real path of an unpacked file', () => { - const parent = fs.realpathSync(path.join(fixtures, 'asar')) + const parent = fs.realpathSync(asarDir) const p = path.join('unpack.asar', 'a.txt') const r = fs.realpathSync(path.join(parent, p)) assert.strictEqual(r, path.join(parent, p)) }) it('throws ENOENT error when can not find file', () => { - const parent = fs.realpathSync(path.join(fixtures, 'asar')) + const parent = fs.realpathSync(asarDir) const p = path.join('a.asar', 'not-exist') const throws = () => fs.realpathSync(path.join(parent, p)) assert.throws(throws, /ENOENT/) @@ -538,49 +539,49 @@ describe('asar package', function () { describe('fs.realpathSync.native', () => { it('returns real path root', () => { - const parent = fs.realpathSync.native(path.join(fixtures, 'asar')) + const parent = fs.realpathSync.native(asarDir) const p = 'a.asar' const r = fs.realpathSync.native(path.join(parent, p)) assert.strictEqual(r, path.join(parent, p)) }) it('returns real path of a normal file', () => { - const parent = fs.realpathSync.native(path.join(fixtures, 'asar')) + const parent = fs.realpathSync.native(asarDir) const p = path.join('a.asar', 'file1') const r = fs.realpathSync.native(path.join(parent, p)) assert.strictEqual(r, path.join(parent, p)) }) it('returns real path of a normal directory', () => { - const parent = fs.realpathSync.native(path.join(fixtures, 'asar')) + const parent = fs.realpathSync.native(asarDir) const p = path.join('a.asar', 'dir1') const r = fs.realpathSync.native(path.join(parent, p)) assert.strictEqual(r, path.join(parent, p)) }) it('returns real path of a linked file', () => { - const parent = fs.realpathSync.native(path.join(fixtures, 'asar')) + const parent = fs.realpathSync.native(asarDir) const p = path.join('a.asar', 'link2', 'link1') const r = fs.realpathSync.native(path.join(parent, p)) assert.strictEqual(r, path.join(parent, 'a.asar', 'file1')) }) it('returns real path of a linked directory', () => { - const parent = fs.realpathSync.native(path.join(fixtures, 'asar')) + const parent = fs.realpathSync.native(asarDir) const p = path.join('a.asar', 'link2', 'link2') const r = fs.realpathSync.native(path.join(parent, p)) assert.strictEqual(r, path.join(parent, 'a.asar', 'dir1')) }) it('returns real path of an unpacked file', () => { - const parent = fs.realpathSync.native(path.join(fixtures, 'asar')) + const parent = fs.realpathSync.native(asarDir) const p = path.join('unpack.asar', 'a.txt') const r = fs.realpathSync.native(path.join(parent, p)) assert.strictEqual(r, path.join(parent, p)) }) it('throws ENOENT error when can not find file', () => { - const parent = fs.realpathSync.native(path.join(fixtures, 'asar')) + const parent = fs.realpathSync.native(asarDir) const p = path.join('a.asar', 'not-exist') const throws = () => fs.realpathSync.native(path.join(parent, p)) assert.throws(throws, /ENOENT/) @@ -589,7 +590,7 @@ describe('asar package', function () { describe('fs.realpath', () => { it('returns real path root', done => { - const parent = fs.realpathSync(path.join(fixtures, 'asar')) + const parent = fs.realpathSync(asarDir) const p = 'a.asar' fs.realpath(path.join(parent, p), (err, r) => { assert.strictEqual(err, null) @@ -599,7 +600,7 @@ describe('asar package', function () { }) it('returns real path of a normal file', done => { - const parent = fs.realpathSync(path.join(fixtures, 'asar')) + const parent = fs.realpathSync(asarDir) const p = path.join('a.asar', 'file1') fs.realpath(path.join(parent, p), (err, r) => { assert.strictEqual(err, null) @@ -609,7 +610,7 @@ describe('asar package', function () { }) it('returns real path of a normal directory', done => { - const parent = fs.realpathSync(path.join(fixtures, 'asar')) + const parent = fs.realpathSync(asarDir) const p = path.join('a.asar', 'dir1') fs.realpath(path.join(parent, p), (err, r) => { assert.strictEqual(err, null) @@ -619,7 +620,7 @@ describe('asar package', function () { }) it('returns real path of a linked file', done => { - const parent = fs.realpathSync(path.join(fixtures, 'asar')) + const parent = fs.realpathSync(asarDir) const p = path.join('a.asar', 'link2', 'link1') fs.realpath(path.join(parent, p), (err, r) => { assert.strictEqual(err, null) @@ -629,7 +630,7 @@ describe('asar package', function () { }) it('returns real path of a linked directory', done => { - const parent = fs.realpathSync(path.join(fixtures, 'asar')) + const parent = fs.realpathSync(asarDir) const p = path.join('a.asar', 'link2', 'link2') fs.realpath(path.join(parent, p), (err, r) => { assert.strictEqual(err, null) @@ -639,7 +640,7 @@ describe('asar package', function () { }) it('returns real path of an unpacked file', done => { - const parent = fs.realpathSync(path.join(fixtures, 'asar')) + const parent = fs.realpathSync(asarDir) const p = path.join('unpack.asar', 'a.txt') fs.realpath(path.join(parent, p), (err, r) => { assert.strictEqual(err, null) @@ -649,7 +650,7 @@ describe('asar package', function () { }) it('throws ENOENT error when can not find file', done => { - const parent = fs.realpathSync(path.join(fixtures, 'asar')) + const parent = fs.realpathSync(asarDir) const p = path.join('a.asar', 'not-exist') fs.realpath(path.join(parent, p), err => { assert.strictEqual(err.code, 'ENOENT') @@ -660,49 +661,49 @@ describe('asar package', function () { describe('fs.promises.realpath', () => { it('returns real path root', async () => { - const parent = fs.realpathSync(path.join(fixtures, 'asar')) + const parent = fs.realpathSync(asarDir) const p = 'a.asar' const r = await fs.promises.realpath(path.join(parent, p)) assert.strictEqual(r, path.join(parent, p)) }) it('returns real path of a normal file', async () => { - const parent = fs.realpathSync(path.join(fixtures, 'asar')) + const parent = fs.realpathSync(asarDir) const p = path.join('a.asar', 'file1') const r = await fs.promises.realpath(path.join(parent, p)) assert.strictEqual(r, path.join(parent, p)) }) it('returns real path of a normal directory', async () => { - const parent = fs.realpathSync(path.join(fixtures, 'asar')) + const parent = fs.realpathSync(asarDir) const p = path.join('a.asar', 'dir1') const r = await fs.promises.realpath(path.join(parent, p)) assert.strictEqual(r, path.join(parent, p)) }) it('returns real path of a linked file', async () => { - const parent = fs.realpathSync(path.join(fixtures, 'asar')) + const parent = fs.realpathSync(asarDir) const p = path.join('a.asar', 'link2', 'link1') const r = await fs.promises.realpath(path.join(parent, p)) assert.strictEqual(r, path.join(parent, 'a.asar', 'file1')) }) it('returns real path of a linked directory', async () => { - const parent = fs.realpathSync(path.join(fixtures, 'asar')) + const parent = fs.realpathSync(asarDir) const p = path.join('a.asar', 'link2', 'link2') const r = await fs.promises.realpath(path.join(parent, p)) assert.strictEqual(r, path.join(parent, 'a.asar', 'dir1')) }) it('returns real path of an unpacked file', async () => { - const parent = fs.realpathSync(path.join(fixtures, 'asar')) + const parent = fs.realpathSync(asarDir) const p = path.join('unpack.asar', 'a.txt') const r = await fs.promises.realpath(path.join(parent, p)) assert.strictEqual(r, path.join(parent, p)) }) it('throws ENOENT error when can not find file', async () => { - const parent = fs.realpathSync(path.join(fixtures, 'asar')) + const parent = fs.realpathSync(asarDir) const p = path.join('a.asar', 'not-exist') await expectToThrowErrorWithCode(() => fs.promises.realpath(path.join(parent, p)), 'ENOENT') }) @@ -710,7 +711,7 @@ describe('asar package', function () { describe('fs.realpath.native', () => { it('returns real path root', done => { - const parent = fs.realpathSync.native(path.join(fixtures, 'asar')) + const parent = fs.realpathSync.native(asarDir) const p = 'a.asar' fs.realpath.native(path.join(parent, p), (err, r) => { assert.strictEqual(err, null) @@ -720,7 +721,7 @@ describe('asar package', function () { }) it('returns real path of a normal file', done => { - const parent = fs.realpathSync.native(path.join(fixtures, 'asar')) + const parent = fs.realpathSync.native(asarDir) const p = path.join('a.asar', 'file1') fs.realpath.native(path.join(parent, p), (err, r) => { assert.strictEqual(err, null) @@ -730,7 +731,7 @@ describe('asar package', function () { }) it('returns real path of a normal directory', done => { - const parent = fs.realpathSync.native(path.join(fixtures, 'asar')) + const parent = fs.realpathSync.native(asarDir) const p = path.join('a.asar', 'dir1') fs.realpath.native(path.join(parent, p), (err, r) => { assert.strictEqual(err, null) @@ -740,7 +741,7 @@ describe('asar package', function () { }) it('returns real path of a linked file', done => { - const parent = fs.realpathSync.native(path.join(fixtures, 'asar')) + const parent = fs.realpathSync.native(asarDir) const p = path.join('a.asar', 'link2', 'link1') fs.realpath.native(path.join(parent, p), (err, r) => { assert.strictEqual(err, null) @@ -750,7 +751,7 @@ describe('asar package', function () { }) it('returns real path of a linked directory', done => { - const parent = fs.realpathSync.native(path.join(fixtures, 'asar')) + const parent = fs.realpathSync.native(asarDir) const p = path.join('a.asar', 'link2', 'link2') fs.realpath.native(path.join(parent, p), (err, r) => { assert.strictEqual(err, null) @@ -760,7 +761,7 @@ describe('asar package', function () { }) it('returns real path of an unpacked file', done => { - const parent = fs.realpathSync.native(path.join(fixtures, 'asar')) + const parent = fs.realpathSync.native(asarDir) const p = path.join('unpack.asar', 'a.txt') fs.realpath.native(path.join(parent, p), (err, r) => { assert.strictEqual(err, null) @@ -770,7 +771,7 @@ describe('asar package', function () { }) it('throws ENOENT error when can not find file', done => { - const parent = fs.realpathSync.native(path.join(fixtures, 'asar')) + const parent = fs.realpathSync.native(asarDir) const p = path.join('a.asar', 'not-exist') fs.realpath.native(path.join(parent, p), err => { assert.strictEqual(err.code, 'ENOENT') @@ -781,25 +782,25 @@ describe('asar package', function () { describe('fs.readdirSync', function () { it('reads dirs from root', function () { - const p = path.join(fixtures, 'asar', 'a.asar') + const p = path.join(asarDir, 'a.asar') const dirs = fs.readdirSync(p) assert.deepStrictEqual(dirs, ['dir1', 'dir2', 'dir3', 'file1', 'file2', 'file3', 'link1', 'link2', 'ping.js']) }) it('reads dirs from a normal dir', function () { - const p = path.join(fixtures, 'asar', 'a.asar', 'dir1') + const p = path.join(asarDir, 'a.asar', 'dir1') const dirs = fs.readdirSync(p) assert.deepStrictEqual(dirs, ['file1', 'file2', 'file3', 'link1', 'link2']) }) it('reads dirs from a linked dir', function () { - const p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2') + const p = path.join(asarDir, 'a.asar', 'link2', 'link2') const dirs = fs.readdirSync(p) assert.deepStrictEqual(dirs, ['file1', 'file2', 'file3', 'link1', 'link2']) }) it('throws ENOENT error when can not find file', function () { - const p = path.join(fixtures, 'asar', 'a.asar', 'not-exist') + const p = path.join(asarDir, 'a.asar', 'not-exist') const throws = function () { fs.readdirSync(p) } @@ -809,7 +810,7 @@ describe('asar package', function () { describe('fs.readdir', function () { it('reads dirs from root', function (done) { - const p = path.join(fixtures, 'asar', 'a.asar') + const p = path.join(asarDir, 'a.asar') fs.readdir(p, function (err, dirs) { assert.strictEqual(err, null) assert.deepStrictEqual(dirs, ['dir1', 'dir2', 'dir3', 'file1', 'file2', 'file3', 'link1', 'link2', 'ping.js']) @@ -818,7 +819,7 @@ describe('asar package', function () { }) it('reads dirs from a normal dir', function (done) { - const p = path.join(fixtures, 'asar', 'a.asar', 'dir1') + const p = path.join(asarDir, 'a.asar', 'dir1') fs.readdir(p, function (err, dirs) { assert.strictEqual(err, null) assert.deepStrictEqual(dirs, ['file1', 'file2', 'file3', 'link1', 'link2']) @@ -826,7 +827,7 @@ describe('asar package', function () { }) }) it('reads dirs from a linked dir', function (done) { - const p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2') + const p = path.join(asarDir, 'a.asar', 'link2', 'link2') fs.readdir(p, function (err, dirs) { assert.strictEqual(err, null) assert.deepStrictEqual(dirs, ['file1', 'file2', 'file3', 'link1', 'link2']) @@ -835,7 +836,7 @@ describe('asar package', function () { }) it('throws ENOENT error when can not find file', function (done) { - const p = path.join(fixtures, 'asar', 'a.asar', 'not-exist') + const p = path.join(asarDir, 'a.asar', 'not-exist') fs.readdir(p, function (err) { assert.strictEqual(err.code, 'ENOENT') done() @@ -845,25 +846,25 @@ describe('asar package', function () { describe('fs.promises.readdir', function () { it('reads dirs from root', async function () { - const p = path.join(fixtures, 'asar', 'a.asar') + const p = path.join(asarDir, 'a.asar') const dirs = await fs.promises.readdir(p) assert.deepStrictEqual(dirs, ['dir1', 'dir2', 'dir3', 'file1', 'file2', 'file3', 'link1', 'link2', 'ping.js']) }) it('reads dirs from a normal dir', async function () { - const p = path.join(fixtures, 'asar', 'a.asar', 'dir1') + const p = path.join(asarDir, 'a.asar', 'dir1') const dirs = await fs.promises.readdir(p) assert.deepStrictEqual(dirs, ['file1', 'file2', 'file3', 'link1', 'link2']) }) it('reads dirs from a linked dir', async function () { - const p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2') + const p = path.join(asarDir, 'a.asar', 'link2', 'link2') const dirs = await fs.promises.readdir(p) assert.deepStrictEqual(dirs, ['file1', 'file2', 'file3', 'link1', 'link2']) }) it('throws ENOENT error when can not find file', async function () { - const p = path.join(fixtures, 'asar', 'a.asar', 'not-exist') + const p = path.join(asarDir, 'a.asar', 'not-exist') await expectToThrowErrorWithCode(() => fs.promises.readdir(p), 'ENOENT') }) }) @@ -873,7 +874,7 @@ describe('asar package', function () { const ref2 = ['file1', 'link1', path.join('link2', 'file1')] for (let j = 0, len = ref2.length; j < len; j++) { const file = ref2[j] - const p = path.join(fixtures, 'asar', 'a.asar', file) + const p = path.join(asarDir, 'a.asar', file) const fd = fs.openSync(p, 'r') const buffer = Buffer.alloc(6) fs.readSync(fd, buffer, 0, 6, 0) @@ -883,7 +884,7 @@ describe('asar package', function () { }) it('throws ENOENT error when can not find file', function () { - const p = path.join(fixtures, 'asar', 'a.asar', 'not-exist') + const p = path.join(asarDir, 'a.asar', 'not-exist') const throws = function () { fs.openSync(p) } @@ -893,7 +894,7 @@ describe('asar package', function () { describe('fs.open', function () { it('opens a normal file', function (done) { - const p = path.join(fixtures, 'asar', 'a.asar', 'file1') + const p = path.join(asarDir, 'a.asar', 'file1') fs.open(p, 'r', function (err, fd) { assert.strictEqual(err, null) const buffer = Buffer.alloc(6) @@ -906,7 +907,7 @@ describe('asar package', function () { }) it('throws ENOENT error when can not find file', function (done) { - const p = path.join(fixtures, 'asar', 'a.asar', 'not-exist') + const p = path.join(asarDir, 'a.asar', 'not-exist') fs.open(p, 'r', function (err) { assert.strictEqual(err.code, 'ENOENT') done() @@ -916,7 +917,7 @@ describe('asar package', function () { describe('fs.promises.open', function () { it('opens a normal file', async function () { - const p = path.join(fixtures, 'asar', 'a.asar', 'file1') + const p = path.join(asarDir, 'a.asar', 'file1') const fh = await fs.promises.open(p, 'r') const buffer = Buffer.alloc(6) await fh.read(buffer, 0, 6, 0) @@ -925,14 +926,14 @@ describe('asar package', function () { }) it('throws ENOENT error when can not find file', async function () { - const p = path.join(fixtures, 'asar', 'a.asar', 'not-exist') + const p = path.join(asarDir, 'a.asar', 'not-exist') await expectToThrowErrorWithCode(() => fs.promises.open(p, 'r'), 'ENOENT') }) }) describe('fs.mkdir', function () { it('throws error when calling inside asar archive', function (done) { - const p = path.join(fixtures, 'asar', 'a.asar', 'not-exist') + const p = path.join(asarDir, 'a.asar', 'not-exist') fs.mkdir(p, function (err) { assert.strictEqual(err.code, 'ENOTDIR') done() @@ -942,14 +943,14 @@ describe('asar package', function () { describe('fs.promises.mkdir', function () { it('throws error when calling inside asar archive', async function () { - const p = path.join(fixtures, 'asar', 'a.asar', 'not-exist') + const p = path.join(asarDir, 'a.asar', 'not-exist') await expectToThrowErrorWithCode(() => fs.promises.mkdir(p), 'ENOTDIR') }) }) describe('fs.mkdirSync', function () { it('throws error when calling inside asar archive', function () { - const p = path.join(fixtures, 'asar', 'a.asar', 'not-exist') + const p = path.join(asarDir, 'a.asar', 'not-exist') assert.throws(function () { fs.mkdirSync(p) }, new RegExp('ENOTDIR')) @@ -958,7 +959,7 @@ describe('asar package', function () { describe('fs.exists', function () { it('handles an existing file', function (done) { - const p = path.join(fixtures, 'asar', 'a.asar', 'file1') + const p = path.join(asarDir, 'a.asar', 'file1') // eslint-disable-next-line fs.exists(p, function (exists) { assert.strictEqual(exists, true) @@ -967,7 +968,7 @@ describe('asar package', function () { }) it('handles a non-existent file', function (done) { - const p = path.join(fixtures, 'asar', 'a.asar', 'not-exist') + const p = path.join(asarDir, 'a.asar', 'not-exist') // eslint-disable-next-line fs.exists(p, function (exists) { assert.strictEqual(exists, false) @@ -976,7 +977,7 @@ describe('asar package', function () { }) it('promisified version handles an existing file', (done) => { - const p = path.join(fixtures, 'asar', 'a.asar', 'file1') + const p = path.join(asarDir, 'a.asar', 'file1') // eslint-disable-next-line util.promisify(fs.exists)(p).then(exists => { assert.strictEqual(exists, true) @@ -985,7 +986,7 @@ describe('asar package', function () { }) it('promisified version handles a non-existent file', function (done) { - const p = path.join(fixtures, 'asar', 'a.asar', 'not-exist') + const p = path.join(asarDir, 'a.asar', 'not-exist') // eslint-disable-next-line util.promisify(fs.exists)(p).then(exists => { assert.strictEqual(exists, false) @@ -996,14 +997,14 @@ describe('asar package', function () { describe('fs.existsSync', function () { it('handles an existing file', function () { - const p = path.join(fixtures, 'asar', 'a.asar', 'file1') + const p = path.join(asarDir, 'a.asar', 'file1') assert.doesNotThrow(function () { assert.strictEqual(fs.existsSync(p), true) }) }) it('handles a non-existent file', function () { - const p = path.join(fixtures, 'asar', 'a.asar', 'not-exist') + const p = path.join(asarDir, 'a.asar', 'not-exist') assert.doesNotThrow(function () { assert.strictEqual(fs.existsSync(p), false) }) @@ -1012,7 +1013,7 @@ describe('asar package', function () { describe('fs.access', function () { it('accesses a normal file', function (done) { - const p = path.join(fixtures, 'asar', 'a.asar', 'file1') + const p = path.join(asarDir, 'a.asar', 'file1') fs.access(p, function (err) { assert(err == null) done() @@ -1020,7 +1021,7 @@ describe('asar package', function () { }) it('throws an error when called with write mode', function (done) { - const p = path.join(fixtures, 'asar', 'a.asar', 'file1') + const p = path.join(asarDir, 'a.asar', 'file1') fs.access(p, fs.constants.R_OK | fs.constants.W_OK, function (err) { assert.strictEqual(err.code, 'EACCES') done() @@ -1028,7 +1029,7 @@ describe('asar package', function () { }) it('throws an error when called on non-existent file', function (done) { - const p = path.join(fixtures, 'asar', 'a.asar', 'not-exist') + const p = path.join(asarDir, 'a.asar', 'not-exist') fs.access(p, function (err) { assert.strictEqual(err.code, 'ENOENT') done() @@ -1036,7 +1037,7 @@ describe('asar package', function () { }) it('allows write mode for unpacked files', function (done) { - const p = path.join(fixtures, 'asar', 'unpack.asar', 'a.txt') + const p = path.join(asarDir, 'unpack.asar', 'a.txt') fs.access(p, fs.constants.R_OK | fs.constants.W_OK, function (err) { assert(err == null) done() @@ -1046,50 +1047,50 @@ describe('asar package', function () { describe('fs.promises.access', function () { it('accesses a normal file', async function () { - const p = path.join(fixtures, 'asar', 'a.asar', 'file1') + const p = path.join(asarDir, 'a.asar', 'file1') await fs.promises.access(p) }) it('throws an error when called with write mode', async function () { - const p = path.join(fixtures, 'asar', 'a.asar', 'file1') + const p = path.join(asarDir, 'a.asar', 'file1') await expectToThrowErrorWithCode(() => fs.promises.access(p, fs.constants.R_OK | fs.constants.W_OK), 'EACCES') }) it('throws an error when called on non-existent file', async function () { - const p = path.join(fixtures, 'asar', 'a.asar', 'not-exist') + const p = path.join(asarDir, 'a.asar', 'not-exist') await expectToThrowErrorWithCode(() => fs.promises.access(p), 'ENOENT') }) it('allows write mode for unpacked files', async function () { - const p = path.join(fixtures, 'asar', 'unpack.asar', 'a.txt') + const p = path.join(asarDir, 'unpack.asar', 'a.txt') await fs.promises.access(p, fs.constants.R_OK | fs.constants.W_OK) }) }) describe('fs.accessSync', function () { it('accesses a normal file', function () { - const p = path.join(fixtures, 'asar', 'a.asar', 'file1') + const p = path.join(asarDir, 'a.asar', 'file1') assert.doesNotThrow(function () { fs.accessSync(p) }) }) it('throws an error when called with write mode', function () { - const p = path.join(fixtures, 'asar', 'a.asar', 'file1') + const p = path.join(asarDir, 'a.asar', 'file1') assert.throws(function () { fs.accessSync(p, fs.constants.R_OK | fs.constants.W_OK) }, /EACCES/) }) it('throws an error when called on non-existent file', function () { - const p = path.join(fixtures, 'asar', 'a.asar', 'not-exist') + const p = path.join(asarDir, 'a.asar', 'not-exist') assert.throws(function () { fs.accessSync(p) }, /ENOENT/) }) it('allows write mode for unpacked files', function () { - const p = path.join(fixtures, 'asar', 'unpack.asar', 'a.txt') + const p = path.join(asarDir, 'unpack.asar', 'a.txt') assert.doesNotThrow(function () { fs.accessSync(p, fs.constants.R_OK | fs.constants.W_OK) }) @@ -1104,7 +1105,7 @@ describe('asar package', function () { }) it('opens a normal js file', function (done) { - const child = ChildProcess.fork(path.join(fixtures, 'asar', 'a.asar', 'ping.js')) + const child = ChildProcess.fork(path.join(asarDir, 'a.asar', 'ping.js')) child.on('message', function (msg) { assert.strictEqual(msg, 'message') done() @@ -1113,7 +1114,7 @@ describe('asar package', function () { }) it('supports asar in the forked js', function (done) { - const file = path.join(fixtures, 'asar', 'a.asar', 'file1') + const file = path.join(asarDir, 'a.asar', 'file1') const child = ChildProcess.fork(path.join(fixtures, 'module', 'asar.js')) child.on('message', function (content) { assert.strictEqual(content, fs.readFileSync(file).toString()) @@ -1124,7 +1125,7 @@ describe('asar package', function () { }) describe('child_process.exec', function () { - const echo = path.join(fixtures, 'asar', 'echo.asar', 'echo') + const echo = path.join(asarDir, 'echo.asar', 'echo') it('should not try to extract the command if there is a reference to a file inside an .asar', function (done) { ChildProcess.exec('echo ' + echo + ' foo bar', function (error, stdout) { @@ -1142,7 +1143,7 @@ describe('asar package', function () { }) describe('child_process.execSync', function () { - const echo = path.join(fixtures, 'asar', 'echo.asar', 'echo') + const echo = path.join(asarDir, 'echo.asar', 'echo') it('should not try to extract the command if there is a reference to a file inside an .asar', function (done) { const stdout = ChildProcess.execSync('echo ' + echo + ' foo bar') @@ -1154,7 +1155,7 @@ describe('asar package', function () { describe('child_process.execFile', function () { const execFile = ChildProcess.execFile const execFileSync = ChildProcess.execFileSync - const echo = path.join(fixtures, 'asar', 'echo.asar', 'echo') + const echo = path.join(asarDir, 'echo.asar', 'echo') before(function () { if (process.platform !== 'darwin') { @@ -1198,16 +1199,16 @@ describe('asar package', function () { const internalModuleReadJSON = process.binding('fs').internalModuleReadJSON it('read a normal file', function () { - const file1 = path.join(fixtures, 'asar', 'a.asar', 'file1') + const file1 = path.join(asarDir, 'a.asar', 'file1') assert.strictEqual(internalModuleReadJSON(file1).toString().trim(), 'file1') - const file2 = path.join(fixtures, 'asar', 'a.asar', 'file2') + const file2 = path.join(asarDir, 'a.asar', 'file2') assert.strictEqual(internalModuleReadJSON(file2).toString().trim(), 'file2') - const file3 = path.join(fixtures, 'asar', 'a.asar', 'file3') + const file3 = path.join(asarDir, 'a.asar', 'file3') assert.strictEqual(internalModuleReadJSON(file3).toString().trim(), 'file3') }) it('reads a normal file with unpacked files', function () { - const p = path.join(fixtures, 'asar', 'unpack.asar', 'a.txt') + const p = path.join(asarDir, 'unpack.asar', 'a.txt') assert.strictEqual(internalModuleReadJSON(p).toString().trim(), 'a') }) }) @@ -1244,8 +1245,8 @@ describe('asar package', function () { }) it('disables asar support in sync API', function () { - const file = path.join(fixtures, 'asar', 'a.asar', 'file1') - const dir = path.join(fixtures, 'asar', 'a.asar', 'dir1') + const file = path.join(asarDir, 'a.asar', 'file1') + const dir = path.join(asarDir, 'a.asar', 'dir1') assert.throws(function () { fs.readFileSync(file) }, new RegExp(errorName)) @@ -1261,8 +1262,8 @@ describe('asar package', function () { }) it('disables asar support in async API', function (done) { - const file = path.join(fixtures, 'asar', 'a.asar', 'file1') - const dir = path.join(fixtures, 'asar', 'a.asar', 'dir1') + const file = path.join(asarDir, 'a.asar', 'file1') + const dir = path.join(asarDir, 'a.asar', 'dir1') fs.readFile(file, function (error) { assert.strictEqual(error.code, errorName) fs.lstat(file, function (error) { @@ -1280,7 +1281,7 @@ describe('asar package', function () { it('treats *.asar as normal file', function () { const originalFs = require('original-fs') - const asar = path.join(fixtures, 'asar', 'a.asar') + const asar = path.join(asarDir, 'a.asar') const content1 = fs.readFileSync(asar) const content2 = originalFs.readFileSync(asar) assert.strictEqual(content1.compare(content2), 0) @@ -1348,7 +1349,7 @@ describe('asar package', function () { }) it('can request a file in package', function (done) { - const p = path.resolve(fixtures, 'asar', 'a.asar', 'file1') + const p = path.resolve(asarDir, 'a.asar', 'file1') $.get('file://' + p, function (data) { assert.strictEqual(data.trim(), 'file1') done() @@ -1356,7 +1357,7 @@ describe('asar package', function () { }) it('can request a file in package with unpacked files', function (done) { - const p = path.resolve(fixtures, 'asar', 'unpack.asar', 'a.txt') + const p = path.resolve(asarDir, 'unpack.asar', 'a.txt') $.get('file://' + p, function (data) { assert.strictEqual(data.trim(), 'a') done() @@ -1364,7 +1365,7 @@ describe('asar package', function () { }) it('can request a linked file in package', function (done) { - const p = path.resolve(fixtures, 'asar', 'a.asar', 'link2', 'link1') + const p = path.resolve(asarDir, 'a.asar', 'link2', 'link1') $.get('file://' + p, function (data) { assert.strictEqual(data.trim(), 'file1') done() @@ -1372,7 +1373,7 @@ describe('asar package', function () { }) it('can request a file in filesystem', function (done) { - const p = path.resolve(fixtures, 'asar', 'file') + const p = path.resolve(asarDir, 'file') $.get('file://' + p, function (data) { assert.strictEqual(data.trim(), 'file') done() @@ -1380,7 +1381,7 @@ describe('asar package', function () { }) it('gets 404 when file is not found', function (done) { - const p = path.resolve(fixtures, 'asar', 'a.asar', 'no-exist') + const p = path.resolve(asarDir, 'a.asar', 'no-exist') $.ajax({ url: 'file://' + p, error: function (err) { @@ -1403,7 +1404,7 @@ describe('asar package', function () { nodeIntegration: true } }) - const p = path.resolve(fixtures, 'asar', 'web.asar', 'index.html') + const p = path.resolve(asarDir, 'web.asar', 'index.html') ipcMain.once('dirname', function (event, dirname) { assert.strictEqual(dirname, path.dirname(p)) done() @@ -1424,7 +1425,7 @@ describe('asar package', function () { nodeIntegration: true } }) - const p = path.resolve(fixtures, 'asar', 'script.asar', 'index.html') + const p = path.resolve(asarDir, 'script.asar', 'index.html') w.loadFile(p) ipcMain.once('ping', function (event, message) { assert.strictEqual(message, 'pong') @@ -1447,7 +1448,7 @@ describe('asar package', function () { nodeIntegration: true } }) - const p = path.resolve(fixtures, 'asar', 'video.asar', 'index.html') + const p = path.resolve(asarDir, 'video.asar', 'index.html') w.loadFile(p) ipcMain.on('asar-video', function (event, message, error) { if (message === 'ended') { @@ -1464,7 +1465,7 @@ describe('asar package', function () { const originalFs = require('original-fs') it('treats .asar as file', function () { - const file = path.join(fixtures, 'asar', 'a.asar') + const file = path.join(asarDir, 'a.asar') const stats = originalFs.statSync(file) assert(stats.isFile()) }) @@ -1484,7 +1485,7 @@ describe('asar package', function () { }) it('can be used with streams', () => { - originalFs.createReadStream(path.join(fixtures, 'asar', 'a.asar')) + originalFs.createReadStream(path.join(asarDir, 'a.asar')) }) it('has the same APIs as fs', function () { @@ -1497,7 +1498,7 @@ describe('asar package', function () { const gfs = require('graceful-fs') it('recognize asar archvies', function () { - const p = path.join(fixtures, 'asar', 'a.asar', 'link1') + const p = path.join(asarDir, 'a.asar', 'link1') assert.strictEqual(gfs.readFileSync(p).toString().trim(), 'file1') }) it('does not touch global fs object', function () { @@ -1509,7 +1510,7 @@ describe('asar package', function () { const mkdirp = require('mkdirp') it('throws error when calling inside asar archive', function () { - const p = path.join(fixtures, 'asar', 'a.asar', 'not-exist') + const p = path.join(asarDir, 'a.asar', 'not-exist') assert.throws(function () { mkdirp.sync(p) }, new RegExp('ENOTDIR')) @@ -1518,7 +1519,7 @@ describe('asar package', function () { describe('native-image', function () { it('reads image from asar archive', function () { - const p = path.join(fixtures, 'asar', 'logo.asar', 'logo.png') + const p = path.join(asarDir, 'logo.asar', 'logo.png') const logo = nativeImage.createFromPath(p) assert.deepStrictEqual(logo.getSize(), { width: 55, @@ -1527,7 +1528,7 @@ describe('asar package', function () { }) it('reads image from asar archive with unpacked files', function () { - const p = path.join(fixtures, 'asar', 'unpack.asar', 'atom.png') + const p = path.join(asarDir, 'unpack.asar', 'atom.png') const logo = nativeImage.createFromPath(p) assert.deepStrictEqual(logo.getSize(), { width: 1024, diff --git a/spec/fixtures/module/no-asar.js b/spec/fixtures/module/no-asar.js index e574e3c6511b8..400a8525ffa47 100644 --- a/spec/fixtures/module/no-asar.js +++ b/spec/fixtures/module/no-asar.js @@ -1,7 +1,7 @@ const fs = require('fs') const path = require('path') -const stats = fs.statSync(path.join(__dirname, '..', 'asar', 'a.asar')) +const stats = fs.statSync(path.join(__dirname, '..', 'test.asar', 'a.asar')) const details = { isFile: stats.isFile(), diff --git a/spec/fixtures/no-proprietary-codecs.js b/spec/fixtures/no-proprietary-codecs.js index d29342d0ea2ca..741927b44f27b 100644 --- a/spec/fixtures/no-proprietary-codecs.js +++ b/spec/fixtures/no-proprietary-codecs.js @@ -25,7 +25,7 @@ app.once('ready', () => { app.exit(1) }) - window.loadFile(path.resolve(__dirname, 'asar', 'video.asar', 'index.html')) + window.loadFile(path.resolve(__dirname, 'test.asar', 'video.asar', 'index.html')) ipcMain.on('asar-video', (event, message, error) => { if (message === 'ended') { diff --git a/spec/fixtures/asar/a.asar b/spec/fixtures/test.asar/a.asar similarity index 100% rename from spec/fixtures/asar/a.asar rename to spec/fixtures/test.asar/a.asar diff --git a/spec/fixtures/asar/echo.asar b/spec/fixtures/test.asar/echo.asar similarity index 100% rename from spec/fixtures/asar/echo.asar rename to spec/fixtures/test.asar/echo.asar diff --git a/spec/fixtures/asar/empty.asar b/spec/fixtures/test.asar/empty.asar similarity index 100% rename from spec/fixtures/asar/empty.asar rename to spec/fixtures/test.asar/empty.asar diff --git a/spec/fixtures/asar/file b/spec/fixtures/test.asar/file similarity index 100% rename from spec/fixtures/asar/file rename to spec/fixtures/test.asar/file diff --git a/spec/fixtures/asar/logo.asar b/spec/fixtures/test.asar/logo.asar similarity index 100% rename from spec/fixtures/asar/logo.asar rename to spec/fixtures/test.asar/logo.asar diff --git a/spec/fixtures/asar/script.asar b/spec/fixtures/test.asar/script.asar similarity index 100% rename from spec/fixtures/asar/script.asar rename to spec/fixtures/test.asar/script.asar diff --git a/spec/fixtures/asar/unpack.asar b/spec/fixtures/test.asar/unpack.asar similarity index 100% rename from spec/fixtures/asar/unpack.asar rename to spec/fixtures/test.asar/unpack.asar diff --git a/spec/fixtures/asar/unpack.asar.unpacked/a.txt b/spec/fixtures/test.asar/unpack.asar.unpacked/a.txt similarity index 100% rename from spec/fixtures/asar/unpack.asar.unpacked/a.txt rename to spec/fixtures/test.asar/unpack.asar.unpacked/a.txt diff --git a/spec/fixtures/asar/unpack.asar.unpacked/atom.png b/spec/fixtures/test.asar/unpack.asar.unpacked/atom.png similarity index 100% rename from spec/fixtures/asar/unpack.asar.unpacked/atom.png rename to spec/fixtures/test.asar/unpack.asar.unpacked/atom.png diff --git a/spec/fixtures/asar/video.asar b/spec/fixtures/test.asar/video.asar similarity index 100% rename from spec/fixtures/asar/video.asar rename to spec/fixtures/test.asar/video.asar diff --git a/spec/fixtures/asar/web.asar b/spec/fixtures/test.asar/web.asar similarity index 100% rename from spec/fixtures/asar/web.asar rename to spec/fixtures/test.asar/web.asar From 3176e323e41f097fedc2bb7110a10bf48482dbe8 Mon Sep 17 00:00:00 2001 From: "trop[bot]" <37223003+trop[bot]@users.noreply.github.com> Date: Thu, 3 Oct 2019 08:59:09 +0200 Subject: [PATCH 16/28] fix: recentDocuments menu role on macOS (#20409) --- atom/browser/ui/cocoa/atom_menu_controller.mm | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/atom/browser/ui/cocoa/atom_menu_controller.mm b/atom/browser/ui/cocoa/atom_menu_controller.mm index 9d66880c1cab6..32af8b3880266 100644 --- a/atom/browser/ui/cocoa/atom_menu_controller.mm +++ b/atom/browser/ui/cocoa/atom_menu_controller.mm @@ -126,11 +126,13 @@ - (void)populateWithModel:(atom::AtomMenuModel*)model { if (!menu_) return; + // Locate & retain the recent documents menu item if (!recentDocumentsMenuItem_) { - // Locate & retain the recent documents menu item - recentDocumentsMenuItem_.reset( - [[[[[NSApp mainMenu] itemWithTitle:@"Electron"] submenu] - itemWithTitle:@"Open Recent"] retain]); + base::string16 title = base::ASCIIToUTF16("Open Recent"); + NSString* openTitle = l10n_util::FixUpWindowsStyleLabel(title); + + recentDocumentsMenuItem_.reset([[[[[NSApp mainMenu] + itemWithTitle:@"Electron"] submenu] itemWithTitle:openTitle] retain]); } model_ = model; @@ -193,8 +195,17 @@ - (void)moveMenuItems:(NSMenu*)source to:(NSMenu*)destination { // Replaces the item's submenu instance with the singleton recent documents // menu. Previously replaced menu items will be recovered. - (void)replaceSubmenuShowingRecentDocuments:(NSMenuItem*)item { - NSMenu* recentDocumentsMenu = - [[[recentDocumentsMenuItem_ submenu] retain] autorelease]; + NSMenu* recentDocumentsMenu = [recentDocumentsMenuItem_ submenu]; + if (!recentDocumentsMenu) { + base::string16 title = base::ASCIIToUTF16("Clear Menu"); + NSString* clearTitle = l10n_util::FixUpWindowsStyleLabel(title); + recentDocumentsMenu = [[[NSMenu alloc] initWithTitle:@""] autorelease]; + [recentDocumentsMenu + addItem:[[[NSMenuItem alloc] + initWithTitle:clearTitle + action:@selector(clearRecentDocuments:) + keyEquivalent:@""] autorelease]]; + } // Remove menu items in recent documents back to swap menu [self moveMenuItems:recentDocumentsMenu to:recentDocumentsMenuSwap_]; @@ -211,6 +222,9 @@ - (void)replaceSubmenuShowingRecentDocuments:(NSMenuItem*)item { // Replace submenu [item setSubmenu:recentDocumentsMenu]; + DCHECK_EQ([item action], @selector(submenuAction:)); + DCHECK_EQ([item target], recentDocumentsMenu); + // Remember the new menu item that carries the recent documents menu recentDocumentsMenuItem_.reset([item retain]); } From 15e611a0ff49c896cea56dc7872b27d27a5bb7c0 Mon Sep 17 00:00:00 2001 From: Shelley Vohr Date: Mon, 7 Oct 2019 17:15:48 +0200 Subject: [PATCH 17/28] docs: clarify dock.bounce usage (#20458) --- docs/api/app.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/api/app.md b/docs/api/app.md index e1785cf144e79..8cfa6ddefeab0 100644 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -1285,6 +1285,8 @@ you exactly what went wrong * `type` String (optional) - Can be `critical` or `informational`. The default is `informational` +Returns `Integer` an ID representing the request. + When `critical` is passed, the dock icon will bounce until either the application becomes active or the request is canceled. @@ -1292,7 +1294,7 @@ When `informational` is passed, the dock icon will bounce for one second. However, the request remains active until either the application becomes active or the request is canceled. -Returns `Integer` an ID representing the request. +**Nota Bene:** This method can only be used while the app is not focused; when the app is focused it will return -1. ### `app.dock.cancelBounce(id)` _macOS_ From 28eb7b05321436b666cc2588a6f386e9d2246b5d Mon Sep 17 00:00:00 2001 From: Joshua Westerheide Date: Mon, 7 Oct 2019 19:04:00 +0200 Subject: [PATCH 18/28] feat: add env variable to skip binary download on npm install (backport) (#20438) * feat: add env variable to skip binary download on npm install * docs: add "Skip binary download" section to install tutorial --- docs/tutorial/installation.md | 11 +++++++++++ npm/install.js | 4 ++++ 2 files changed, 15 insertions(+) diff --git a/docs/tutorial/installation.md b/docs/tutorial/installation.md index 5eeb89911b727..3aaba70d369a1 100644 --- a/docs/tutorial/installation.md +++ b/docs/tutorial/installation.md @@ -97,6 +97,17 @@ a text file. A typical cache might look like this: ├── SHASUMS256.txt-1.8.2-beta.3 ``` +## Skip binary download +When installing the `electron` NPM package, it automatically downloads the electron binary. + +This can sometimes be unnecessary, e.g. in a CI environment, when testing another component. + +To prevent the binary from being downloaded when you install all npm dependencies you can set the environment variable `ELECTRON_SKIP_BINARY_DOWNLOAD`. +E.g.: +```sh +ELECTRON_SKIP_BINARY_DOWNLOAD=1 npm install +``` + ## Troubleshooting When running `npm install electron`, some users occasionally encounter diff --git a/npm/install.js b/npm/install.js index 3f59ce15d22bc..05bdab0bdab0b 100755 --- a/npm/install.js +++ b/npm/install.js @@ -15,6 +15,10 @@ try { // do nothing } +if (process.env.ELECTRON_SKIP_BINARY_DOWNLOAD) { + process.exit(0) +} + var platformPath = getPlatformPath() var electronPath = process.env.ELECTRON_OVERRIDE_DIST_PATH || path.join(__dirname, 'dist', platformPath) From e501930d38ac8ff7c19417005b06e9a2e9fd1303 Mon Sep 17 00:00:00 2001 From: Robo Date: Mon, 7 Oct 2019 13:05:14 -0700 Subject: [PATCH 19/28] fix: fs.watch() behavior change in node >= 10.16.0 (#20429) This reverts the patch from https://github.com/electron/node/pull/100 which never got merged due to reasons outlined in https://github.com/libuv/libuv/pull/2313 * Adds new patches that backports https://github.com/libuv/libuv/pull/2459 and https://github.com/libuv/libuv/pull/2460 Based on https://github.com/nodejs/node/issues/29460 --- patches/node/.patches | 3 +- .../fsevents-regression-in-watching.patch | 158 +++++++++++++ ...s-stop-using-fsevents-to-watch-files.patch | 120 ++++++++++ .../fsevents_fix_file_event_reporting.patch | 213 ------------------ 4 files changed, 280 insertions(+), 214 deletions(-) create mode 100644 patches/node/fsevents-regression-in-watching.patch create mode 100644 patches/node/fsevents-stop-using-fsevents-to-watch-files.patch delete mode 100644 patches/node/fsevents_fix_file_event_reporting.patch diff --git a/patches/node/.patches b/patches/node/.patches index 4b1b10e03f924..ab79ba34c02ef 100644 --- a/patches/node/.patches +++ b/patches/node/.patches @@ -32,7 +32,6 @@ feat_add_original-fs_module.patch build_allow_embedders_to_override_the_node_module_version_define.patch refactor_allow_embedder_overriding_of_internal_fs_calls.patch chore_add_ability_to_prevent_warn_non_context-aware_native_modules.patch -fsevents_fix_file_event_reporting.patch src_only_run_preloadmodules_if_the_preload_array_is_not_empty.patch src_read_break_node_first_line_from_the_inspect_options.patch chore_allow_the_node_entrypoint_to_be_a_builtin_module.patch @@ -55,3 +54,5 @@ chore_read_nobrowserglobals_from_global_not_process.patch chore_use_v8_inspector_js_protocol_to_find_pdl_file.patch chore_split_createenvironment_into_createenvironment_and.patch fix_set_uptime_offset_in_correct_init_method.patch +fsevents-stop-using-fsevents-to-watch-files.patch +fsevents-regression-in-watching.patch diff --git a/patches/node/fsevents-regression-in-watching.patch b/patches/node/fsevents-regression-in-watching.patch new file mode 100644 index 0000000000000..e808aba80e358 --- /dev/null +++ b/patches/node/fsevents-regression-in-watching.patch @@ -0,0 +1,158 @@ +From ae12376dbb56fa080b699f00840c7b9c5230a85f Mon Sep 17 00:00:00 2001 +From: Jameson Nash +Date: Sat, 7 Sep 2019 20:45:39 -0400 +Subject: [PATCH] fsevents: regression in watching / + +This case got lost by accident in +https://github.com/libuv/libuv/pull/2082, +preventing the realpath `/` from ever matching. + +Fixes: https://github.com/nodejs/node/issues/28917 +PR-URL: https://github.com/libuv/libuv/pull/2460 +Reviewed-By: Ben Noordhuis +Reviewed-By: Saúl Ibarra Corretgé + +diff --git a/deps/uv/src/unix/fsevents.c b/deps/uv/src/unix/fsevents.c +index ddacda31..deeaa63d 100644 +--- a/deps/uv/src/unix/fsevents.c ++++ b/deps/uv/src/unix/fsevents.c +@@ -263,10 +263,12 @@ static void uv__fsevents_event_cb(ConstFSEventStreamRef streamRef, + if (len < handle->realpath_len) + continue; + ++ /* Make sure that realpath actually named a directory, ++ * (unless watching root, which alone keeps a trailing slash on the realpath) ++ * or that we matched the whole string */ + if (handle->realpath_len != len && ++ handle->realpath_len > 1 && + path[handle->realpath_len] != '/') +- /* Make sure that realpath actually named a directory, +- * or that we matched the whole string */ + continue; + + if (memcmp(path, handle->realpath, handle->realpath_len) != 0) +diff --git a/deps/uv/test/test-fs-event.c b/deps/uv/test/test-fs-event.c +index 4b8bb1ef..7725c3af 100644 +--- a/deps/uv/test/test-fs-event.c ++++ b/deps/uv/test/test-fs-event.c +@@ -47,6 +47,7 @@ static const char file_prefix[] = "fsevent-"; + static const int fs_event_file_count = 16; + #if defined(__APPLE__) || defined(_WIN32) + static const char file_prefix_in_subdir[] = "subdir"; ++static int fs_multievent_cb_called; + #endif + static uv_timer_t timer; + static int timer_cb_called; +@@ -280,7 +281,7 @@ static void fs_event_cb_dir_multi_file_in_subdir(uv_fs_event_t* handle, + if (filename && strcmp(filename, file_prefix_in_subdir) == 0) + return; + #endif +- fs_event_cb_called++; ++ fs_multievent_cb_called++; + ASSERT(handle == &fs_event); + ASSERT(status == 0); + ASSERT(events == UV_CHANGE || events == UV_RENAME); +@@ -298,7 +299,7 @@ static void fs_event_cb_dir_multi_file_in_subdir(uv_fs_event_t* handle, + if (fs_event_created + fs_event_removed == fs_event_file_count) { + /* Once we've processed all create events, delete all files */ + ASSERT(0 == uv_timer_start(&timer, fs_event_unlink_files_in_subdir, 1, 0)); +- } else if (fs_event_cb_called == 2 * fs_event_file_count) { ++ } else if (fs_multievent_cb_called == 2 * fs_event_file_count) { + /* Once we've processed all create and delete events, stop watching */ + uv_close((uv_handle_t*) &timer, close_cb); + uv_close((uv_handle_t*) handle, close_cb); +@@ -393,6 +394,21 @@ static void timer_cb_watch_twice(uv_timer_t* handle) { + uv_close((uv_handle_t*) handle, NULL); + } + ++static void fs_event_cb_close(uv_fs_event_t* handle, ++ const char* filename, ++ int events, ++ int status) { ++ ASSERT(status == 0); ++ ++ ASSERT(fs_event_cb_called < 3); ++ ++fs_event_cb_called; ++ ++ if (fs_event_cb_called == 3) { ++ uv_close((uv_handle_t*) handle, close_cb); ++ } ++} ++ ++ + TEST_IMPL(fs_event_watch_dir) { + #if defined(NO_FS_EVENTS) + RETURN_SKIP(NO_FS_EVENTS); +@@ -434,10 +450,12 @@ TEST_IMPL(fs_event_watch_dir) { + return 0; + } + ++ + TEST_IMPL(fs_event_watch_dir_recursive) { + #if defined(__APPLE__) || defined(_WIN32) + uv_loop_t* loop; + int r; ++ uv_fs_event_t fs_event_root; + + /* Setup */ + loop = uv_default_loop(); +@@ -451,17 +469,37 @@ TEST_IMPL(fs_event_watch_dir_recursive) { + + r = uv_fs_event_init(loop, &fs_event); + ASSERT(r == 0); +- r = uv_fs_event_start(&fs_event, fs_event_cb_dir_multi_file_in_subdir, "watch_dir", UV_FS_EVENT_RECURSIVE); ++ r = uv_fs_event_start(&fs_event, ++ fs_event_cb_dir_multi_file_in_subdir, ++ "watch_dir", ++ UV_FS_EVENT_RECURSIVE); + ASSERT(r == 0); + r = uv_timer_init(loop, &timer); + ASSERT(r == 0); + r = uv_timer_start(&timer, fs_event_create_files_in_subdir, 100, 0); + ASSERT(r == 0); + ++#ifndef _WIN32 ++ /* Also try to watch the root directory. ++ * This will be noisier, so we're just checking for any couple events to happen. */ ++ r = uv_fs_event_init(loop, &fs_event_root); ++ ASSERT(r == 0); ++ r = uv_fs_event_start(&fs_event_root, ++ fs_event_cb_close, ++ "/", ++ UV_FS_EVENT_RECURSIVE); ++ ASSERT(r == 0); ++#else ++ fs_event_cb_called += 3; ++ close_cb_called += 1; ++ (void)fs_event_root; ++#endif ++ + uv_run(loop, UV_RUN_DEFAULT); + +- ASSERT(fs_event_cb_called == fs_event_created + fs_event_removed); +- ASSERT(close_cb_called == 2); ++ ASSERT(fs_multievent_cb_called == fs_event_created + fs_event_removed); ++ ASSERT(fs_event_cb_called == 3); ++ ASSERT(close_cb_called == 3); + + /* Cleanup */ + fs_event_unlink_files_in_subdir(NULL); +@@ -870,18 +908,6 @@ TEST_IMPL(fs_event_close_with_pending_event) { + return 0; + } + +-static void fs_event_cb_close(uv_fs_event_t* handle, const char* filename, +- int events, int status) { +- ASSERT(status == 0); +- +- ASSERT(fs_event_cb_called < 3); +- ++fs_event_cb_called; +- +- if (fs_event_cb_called == 3) { +- uv_close((uv_handle_t*) handle, close_cb); +- } +-} +- + TEST_IMPL(fs_event_close_in_callback) { + #if defined(NO_FS_EVENTS) + RETURN_SKIP(NO_FS_EVENTS); diff --git a/patches/node/fsevents-stop-using-fsevents-to-watch-files.patch b/patches/node/fsevents-stop-using-fsevents-to-watch-files.patch new file mode 100644 index 0000000000000..b502c5540d58f --- /dev/null +++ b/patches/node/fsevents-stop-using-fsevents-to-watch-files.patch @@ -0,0 +1,120 @@ +From 97b85e8b75b8f3df774b6e008dbaa143daa412b7 Mon Sep 17 00:00:00 2001 +From: Jameson Nash +Date: Sat, 7 Sep 2019 14:55:40 -0400 +Subject: [PATCH] fsevents: stop using fsevents to watch files + +Goes back to just using it to watch folders, +but keeps the other logic changes around. + +Refs: https://github.com/libuv/libuv/pull/387 +Refs: https://github.com/libuv/libuv/pull/2082 +Refs: https://github.com/libuv/libuv/pull/1572 +Refs: https://github.com/nodejs/node/issues/29460 +Fixes: https://github.com/libuv/libuv/issues/2488 +Closes: https://github.com/libuv/libuv/pull/2452 +PR-URL: https://github.com/libuv/libuv/pull/2459 +Reviewed-By: Ben Noordhuis +Reviewed-By: Saúl Ibarra Corretgé + +diff --git a/deps/uv/src/unix/kqueue.c b/deps/uv/src/unix/kqueue.c +index c04e7a48..ad09f403 100644 +--- a/deps/uv/src/unix/kqueue.c ++++ b/deps/uv/src/unix/kqueue.c +@@ -454,10 +454,26 @@ int uv_fs_event_start(uv_fs_event_t* handle, + const char* path, + unsigned int flags) { + int fd; ++#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 ++ struct stat statbuf; ++#endif + + if (uv__is_active(handle)) + return UV_EINVAL; + ++ handle->cb = cb; ++ handle->path = uv__strdup(path); ++ if (handle->path == NULL) ++ return UV_ENOMEM; ++ ++ /* TODO open asynchronously - but how do we report back errors? */ ++ fd = open(handle->path, O_RDONLY); ++ if (fd == -1) { ++ uv__free(handle->path); ++ handle->path = NULL; ++ return UV__ERR(errno); ++ } ++ + #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 + /* Nullify field to perform checks later */ + handle->cf_cb = NULL; +@@ -465,14 +481,17 @@ int uv_fs_event_start(uv_fs_event_t* handle, + handle->realpath_len = 0; + handle->cf_flags = flags; + ++ if (fstat(fd, &statbuf)) ++ goto fallback; ++ /* FSEvents works only with directories */ ++ if (!(statbuf.st_mode & S_IFDIR)) ++ goto fallback; ++ + if (!uv__has_forked_with_cfrunloop) { + int r; +- /* The fallback fd is not used */ ++ /* The fallback fd is no longer needed */ ++ uv__close_nocheckstdio(fd); + handle->event_watcher.fd = -1; +- handle->path = uv__strdup(path); +- if (handle->path == NULL) +- return UV_ENOMEM; +- handle->cb = cb; + r = uv__fsevents_init(handle); + if (r == 0) { + uv__handle_start(handle); +@@ -482,20 +501,9 @@ int uv_fs_event_start(uv_fs_event_t* handle, + } + return r; + } ++fallback: + #endif /* #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */ + +- /* TODO open asynchronously - but how do we report back errors? */ +- fd = open(path, O_RDONLY); +- if (fd == -1) +- return UV__ERR(errno); +- +- handle->path = uv__strdup(path); +- if (handle->path == NULL) { +- uv__close_nocheckstdio(fd); +- return UV_ENOMEM; +- } +- +- handle->cb = cb; + uv__handle_start(handle); + uv__io_init(&handle->event_watcher, uv__fs_event, fd); + uv__io_start(handle->loop, &handle->event_watcher, POLLIN); +@@ -514,7 +522,7 @@ int uv_fs_event_stop(uv_fs_event_t* handle) { + uv__handle_stop(handle); + + #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 +- if (!uv__has_forked_with_cfrunloop) ++ if (!uv__has_forked_with_cfrunloop && handle->cf_cb != NULL) + r = uv__fsevents_close(handle); + #endif + +diff --git a/deps/uv/test/test-fs-event.c b/deps/uv/test/test-fs-event.c +index ea34bd63..4b8bb1ef 100644 +--- a/deps/uv/test/test-fs-event.c ++++ b/deps/uv/test/test-fs-event.c +@@ -656,6 +656,12 @@ TEST_IMPL(fs_event_watch_file_current_dir) { + /* Setup */ + remove("watch_file"); + create_file("watch_file"); ++#if defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_12) ++ /* Empirically, kevent seems to (sometimes) report the preceeding ++ * create_file events prior to macOS 10.11.6 in the subsequent fs_event_start ++ * So let the system settle before running the test. */ ++ uv_sleep(1100); ++#endif + + r = uv_fs_event_init(loop, &fs_event); + ASSERT(r == 0); diff --git a/patches/node/fsevents_fix_file_event_reporting.patch b/patches/node/fsevents_fix_file_event_reporting.patch deleted file mode 100644 index bc89830651349..0000000000000 --- a/patches/node/fsevents_fix_file_event_reporting.patch +++ /dev/null @@ -1,213 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Ben Noordhuis -Date: Mon, 27 May 2019 14:31:53 +0200 -Subject: fsevents: fix file event reporting - -Commit 2d2af38 ("fsevents: really watch files with fsevents on macos -10.7+") from last November introduced a regression where events that -were previously reported as UV_RENAME were now reported as UV_CHANGE. -This commit rectifies that. - -Fixes: https://github.com/nodejs/node/issues/27869 - -diff --git a/deps/uv/src/unix/fsevents.c b/deps/uv/src/unix/fsevents.c -index ddacda31fef87eee131fc2ee2ff46cc88be429d9..911023a6562319af5e9e3412ddbfd2ca14f77b05 100644 ---- a/deps/uv/src/unix/fsevents.c -+++ b/deps/uv/src/unix/fsevents.c -@@ -49,19 +49,9 @@ void uv__fsevents_loop_delete(uv_loop_t* loop) { - #include - #include - --/* These are macros to avoid "initializer element is not constant" errors -+/* Macro to avoid "initializer element is not constant" errors - * with old versions of gcc. - */ --#define kFSEventsModified (kFSEventStreamEventFlagItemFinderInfoMod | \ -- kFSEventStreamEventFlagItemModified | \ -- kFSEventStreamEventFlagItemInodeMetaMod | \ -- kFSEventStreamEventFlagItemChangeOwner | \ -- kFSEventStreamEventFlagItemXattrMod) -- --#define kFSEventsRenamed (kFSEventStreamEventFlagItemCreated | \ -- kFSEventStreamEventFlagItemRemoved | \ -- kFSEventStreamEventFlagItemRenamed) -- - #define kFSEventsSystem (kFSEventStreamEventFlagUserDropped | \ - kFSEventStreamEventFlagKernelDropped | \ - kFSEventStreamEventFlagEventIdsWrapped | \ -@@ -289,8 +279,6 @@ static void uv__fsevents_event_cb(ConstFSEventStreamRef streamRef, - path--; - len++; - } -- /* Created and Removed seem to be always set, but don't make sense */ -- flags &= ~kFSEventsRenamed; - } else { - /* Skip forward slash */ - path++; -@@ -311,12 +299,12 @@ static void uv__fsevents_event_cb(ConstFSEventStreamRef streamRef, - - memset(event, 0, sizeof(*event)); - memcpy(event->path, path, len + 1); -- event->events = UV_RENAME; -+ event->events = UV_CHANGE; - -- if (0 == (flags & kFSEventsRenamed)) { -- if (0 != (flags & kFSEventsModified) || -- 0 == (flags & kFSEventStreamEventFlagItemIsDir)) -- event->events = UV_CHANGE; -+ if ((flags & kFSEventStreamEventFlagItemIsDir) || -+ (flags & kFSEventStreamEventFlagItemRemoved) || -+ (flags & kFSEventStreamEventFlagItemRenamed)) { -+ event->events = UV_RENAME; - } - - QUEUE_INSERT_TAIL(&head, &event->member); -diff --git a/deps/uv/test/test-fs-event.c b/deps/uv/test/test-fs-event.c -index ea34bd63a70625c3e2c60d5a1bbb087c5f0bbb2e..38d722a27ef1a78717726272d54578c734280242 100644 ---- a/deps/uv/test/test-fs-event.c -+++ b/deps/uv/test/test-fs-event.c -@@ -62,6 +62,15 @@ static char fs_event_filename[1024]; - static int timer_cb_touch_called; - static int timer_cb_exact_called; - -+static void expect_filename(const char* path, const char* expected) { -+#if defined(__APPLE__) || defined(_WIN32) || defined(__linux__) -+ ASSERT(0 == strcmp(path, expected)); -+#else -+ if (path != NULL) -+ ASSERT(0 == strcmp(path, expected)); -+#endif -+} -+ - static void fs_event_fail(uv_fs_event_t* handle, - const char* filename, - int events, -@@ -130,11 +139,7 @@ static void fs_event_cb_dir(uv_fs_event_t* handle, const char* filename, - ASSERT(handle == &fs_event); - ASSERT(status == 0); - ASSERT(events == UV_CHANGE); -- #if defined(__APPLE__) || defined(_WIN32) || defined(__linux__) -- ASSERT(strcmp(filename, "file1") == 0); -- #else -- ASSERT(filename == NULL || strcmp(filename, "file1") == 0); -- #endif -+ expect_filename(filename, "file1"); - ASSERT(0 == uv_fs_event_stop(handle)); - uv_close((uv_handle_t*)handle, close_cb); - } -@@ -312,11 +317,7 @@ static void fs_event_cb_file(uv_fs_event_t* handle, const char* filename, - ASSERT(handle == &fs_event); - ASSERT(status == 0); - ASSERT(events == UV_CHANGE); -- #if defined(__APPLE__) || defined(_WIN32) || defined(__linux__) -- ASSERT(strcmp(filename, "file2") == 0); -- #else -- ASSERT(filename == NULL || strcmp(filename, "file2") == 0); -- #endif -+ expect_filename(filename, "file2"); - ASSERT(0 == uv_fs_event_stop(handle)); - uv_close((uv_handle_t*)handle, close_cb); - } -@@ -339,11 +340,7 @@ static void fs_event_cb_file_current_dir(uv_fs_event_t* handle, - ASSERT(handle == &fs_event); - ASSERT(status == 0); - ASSERT(events == UV_CHANGE); -- #if defined(__APPLE__) || defined(_WIN32) || defined(__linux__) -- ASSERT(strcmp(filename, "watch_file") == 0); -- #else -- ASSERT(filename == NULL || strcmp(filename, "watch_file") == 0); -- #endif -+ expect_filename(filename, "watch_file"); - - /* Regression test for SunOS: touch should generate just one event. */ - { -@@ -619,6 +616,69 @@ TEST_IMPL(fs_event_watch_file_exact_path) { - return 0; - } - -+static void file_remove_cb(uv_fs_event_t* handle, -+ const char* path, -+ int events, -+ int status) { -+ fs_event_cb_called++; -+ -+ expect_filename(path, "file1"); -+ /* TODO(bnoordhuis) Harmonize the behavior across platforms. Right now -+ * this test merely ensures the status quo doesn't regress. -+ */ -+#if defined(_AIX) || defined(__linux__) -+ ASSERT(UV_CHANGE == events); -+#else -+ ASSERT(UV_RENAME == events); -+#endif -+ ASSERT(0 == status); -+ -+ uv_close((uv_handle_t*) handle, NULL); -+} -+ -+static void file_remove_next(uv_timer_t* handle) { -+ uv_close((uv_handle_t*) handle, NULL); -+ remove("watch_dir/file1"); -+} -+ -+static void file_remove_start(uv_timer_t* handle) { -+ uv_fs_event_t* watcher; -+ uv_loop_t* loop; -+ -+ loop = handle->loop; -+ watcher = handle->data; -+ -+ ASSERT(0 == uv_fs_event_init(loop, watcher)); -+ ASSERT(0 == uv_fs_event_start(watcher, file_remove_cb, "watch_dir/file1", 0)); -+ ASSERT(0 == uv_timer_start(handle, file_remove_next, 50, 0)); -+} -+ -+TEST_IMPL(fs_event_watch_file_remove) { -+ uv_fs_event_t watcher; -+ uv_timer_t timer; -+ uv_loop_t* loop; -+ -+#if defined(__MVS__) -+ RETURN_SKIP("test does not work on this OS"); -+#endif -+ -+ remove("watch_dir/file1"); -+ remove("watch_dir/"); -+ create_dir("watch_dir"); -+ create_file("watch_dir/file1"); -+ -+ loop = uv_default_loop(); -+ timer.data = &watcher; -+ -+ ASSERT(0 == uv_timer_init(loop, &timer)); -+ ASSERT(0 == uv_timer_start(&timer, file_remove_start, 500, 0)); -+ ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); -+ ASSERT(1 == fs_event_cb_called); -+ -+ MAKE_VALGRIND_HAPPY(); -+ return 0; -+} -+ - TEST_IMPL(fs_event_watch_file_twice) { - #if defined(NO_FS_EVENTS) - RETURN_SKIP(NO_FS_EVENTS); -diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h -index 8886b07c8a74736208d5614257f832f59d79633a..3e758a1d2cbe104a691d362411770006d1494bae 100644 ---- a/deps/uv/test/test-list.h -+++ b/deps/uv/test/test-list.h -@@ -333,6 +333,7 @@ TEST_DECLARE (fs_event_watch_dir_short_path) - #endif - TEST_DECLARE (fs_event_watch_file) - TEST_DECLARE (fs_event_watch_file_exact_path) -+TEST_DECLARE (fs_event_watch_file_remove) - TEST_DECLARE (fs_event_watch_file_twice) - TEST_DECLARE (fs_event_watch_file_current_dir) - #ifdef _WIN32 -@@ -920,6 +921,7 @@ TASK_LIST_START - #endif - TEST_ENTRY (fs_event_watch_file) - TEST_ENTRY (fs_event_watch_file_exact_path) -+ TEST_ENTRY (fs_event_watch_file_remove) - TEST_ENTRY (fs_event_watch_file_twice) - TEST_ENTRY (fs_event_watch_file_current_dir) - #ifdef _WIN32 From 03d16f37d2dc9e570adecbc87872e78fe4855378 Mon Sep 17 00:00:00 2001 From: Shelley Vohr Date: Tue, 8 Oct 2019 17:59:28 +0200 Subject: [PATCH 20/28] fix: enable worker threads in ELECTRON_RUN_AS_NODE (#20457) --- patches/node/.patches | 1 + patches/node/fix_enable_worker_threads.patch | 29 ++++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 patches/node/fix_enable_worker_threads.patch diff --git a/patches/node/.patches b/patches/node/.patches index ab79ba34c02ef..bf7dc4efef84a 100644 --- a/patches/node/.patches +++ b/patches/node/.patches @@ -54,5 +54,6 @@ chore_read_nobrowserglobals_from_global_not_process.patch chore_use_v8_inspector_js_protocol_to_find_pdl_file.patch chore_split_createenvironment_into_createenvironment_and.patch fix_set_uptime_offset_in_correct_init_method.patch +fix_enable_worker_threads.patch fsevents-stop-using-fsevents-to-watch-files.patch fsevents-regression-in-watching.patch diff --git a/patches/node/fix_enable_worker_threads.patch b/patches/node/fix_enable_worker_threads.patch new file mode 100644 index 0000000000000..586cd0b46a95c --- /dev/null +++ b/patches/node/fix_enable_worker_threads.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Shelley Vohr +Date: Thu, 3 Oct 2019 19:03:30 +0200 +Subject: fix: enable worker_threads + +Electron sets NODE_USE_V8_PLATFORM to false, because Electron +initializes the v8 platform itself and Node.js worker thread +initialization relies on the platform it uses having been set inside +code guarded by NODE_USE_V8_PLATFORM. + +This commit fixes this problem by changing node_worker to use the three-arg +implementation of `NewIsolate` to prevent it trying to use a possibly-null ptr. + +diff --git a/src/node_worker.cc b/src/node_worker.cc +index 8f97f5c351..2bfbb28e61 100644 +--- a/src/node_worker.cc ++++ b/src/node_worker.cc +@@ -112,7 +112,10 @@ class WorkerThreadData { + array_buffer_allocator_(ArrayBufferAllocator::Create()) { + CHECK_EQ(uv_loop_init(&loop_), 0); + +- Isolate* isolate = NewIsolate(array_buffer_allocator_.get(), &loop_); ++ Isolate* isolate = NewIsolate( ++ array_buffer_allocator_.get(), ++ &loop_, ++ w->platform_); + CHECK_NOT_NULL(isolate); + + { From 31ba6c203e754f5bb8a12c223186d9e98caf96fd Mon Sep 17 00:00:00 2001 From: "trop[bot]" <37223003+trop[bot]@users.noreply.github.com> Date: Tue, 8 Oct 2019 15:33:32 -0400 Subject: [PATCH 21/28] fix: properly free IsolateData in node_main (#20475) --- atom/app/node_main.cc | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/atom/app/node_main.cc b/atom/app/node_main.cc index 482b375c106e4..332687302e3e5 100644 --- a/atom/app/node_main.cc +++ b/atom/app/node_main.cc @@ -68,9 +68,14 @@ int NodeMain(int argc, char* argv[]) { // Initialize gin::IsolateHolder. JavascriptEnvironment gin_env(loop); - node::Environment* env = node::CreateEnvironment( - node::CreateIsolateData(gin_env.isolate(), loop, gin_env.platform()), - gin_env.context(), argc, argv, exec_argc, exec_argv, false); + node::IsolateData* isolate_data = + node::CreateIsolateData(gin_env.isolate(), loop, gin_env.platform()); + CHECK_NE(nullptr, isolate_data); + + node::Environment* env = + node::CreateEnvironment(isolate_data, gin_env.context(), argc, argv, + exec_argc, exec_argv, false); + CHECK_NE(nullptr, env); // Enable support for v8 inspector. NodeDebugger node_debugger(env); @@ -118,6 +123,7 @@ int NodeMain(int argc, char* argv[]) { v8::Isolate* isolate = env->isolate(); node::FreeEnvironment(env); + node::FreeIsolateData(isolate_data); gin_env.platform()->DrainTasks(isolate); gin_env.platform()->CancelPendingDelayedTasks(isolate); From 1e50380fab37f407c4d357e1e30ecbc3d5a703b8 Mon Sep 17 00:00:00 2001 From: Electron Bot Date: Tue, 8 Oct 2019 12:43:31 -0700 Subject: [PATCH 22/28] Bump v6.0.12 --- ELECTRON_VERSION | 2 +- atom/browser/resources/mac/Info.plist | 4 ++-- atom/browser/resources/win/atom.rc | 8 ++++---- atom/common/atom_version.h | 2 +- package.json | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ELECTRON_VERSION b/ELECTRON_VERSION index cb372c07bfa82..d089f6d74812e 100644 --- a/ELECTRON_VERSION +++ b/ELECTRON_VERSION @@ -1 +1 @@ -6.0.11 \ No newline at end of file +6.0.12 \ No newline at end of file diff --git a/atom/browser/resources/mac/Info.plist b/atom/browser/resources/mac/Info.plist index d3efa6a713058..59b1a119fa920 100644 --- a/atom/browser/resources/mac/Info.plist +++ b/atom/browser/resources/mac/Info.plist @@ -17,9 +17,9 @@ CFBundleIconFile electron.icns CFBundleVersion - 6.0.11 + 6.0.12 CFBundleShortVersionString - 6.0.11 + 6.0.12 LSApplicationCategoryType public.app-category.developer-tools LSMinimumSystemVersion diff --git a/atom/browser/resources/win/atom.rc b/atom/browser/resources/win/atom.rc index f378c8dc44a2b..ab44121518d97 100644 --- a/atom/browser/resources/win/atom.rc +++ b/atom/browser/resources/win/atom.rc @@ -50,8 +50,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 6,0,11,0 - PRODUCTVERSION 6,0,11,0 + FILEVERSION 6,0,12,0 + PRODUCTVERSION 6,0,12,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -68,12 +68,12 @@ BEGIN BEGIN VALUE "CompanyName", "GitHub, Inc." VALUE "FileDescription", "Electron" - VALUE "FileVersion", "6.0.11" + VALUE "FileVersion", "6.0.12" VALUE "InternalName", "electron.exe" VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved." VALUE "OriginalFilename", "electron.exe" VALUE "ProductName", "Electron" - VALUE "ProductVersion", "6.0.11" + VALUE "ProductVersion", "6.0.12" VALUE "SquirrelAwareVersion", "1" END END diff --git a/atom/common/atom_version.h b/atom/common/atom_version.h index 2929e61ed841d..589e7066cd61d 100644 --- a/atom/common/atom_version.h +++ b/atom/common/atom_version.h @@ -7,7 +7,7 @@ #define ATOM_MAJOR_VERSION 6 #define ATOM_MINOR_VERSION 0 -#define ATOM_PATCH_VERSION 11 +#define ATOM_PATCH_VERSION 12 // clang-format off // #define ATOM_PRE_RELEASE_VERSION // clang-format on diff --git a/package.json b/package.json index f332706dc9e8b..2bdfcf9902a2b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "electron", - "version": "6.0.11", + "version": "6.0.12", "repository": "https://github.com/electron/electron", "description": "Build cross platform desktop apps with JavaScript, HTML, and CSS", "devDependencies": { From fd0b57f219b1275b7133074387625d15094fd3c6 Mon Sep 17 00:00:00 2001 From: Robo Date: Wed, 9 Oct 2019 13:41:06 -0700 Subject: [PATCH 23/28] fix: backport chromium patches to fix touchpad scrolling on windows (#20488) Backports https://chromium-review.googlesource.com/c/chromium/src/+/1689922 and https://chromium-review.googlesource.com/c/chromium/src/+/1753661 --- patches/common/chromium/.patches | 2 + ...andler_when_directmanipulationhelper.patch | 118 +++ ...helper_when_every_lrwhh_updateparent.patch | 975 ++++++++++++++++++ 3 files changed, 1095 insertions(+) create mode 100644 patches/common/chromium/notify_directmanipulationeventhandler_when_directmanipulationhelper.patch create mode 100644 patches/common/chromium/recreate_directmanipulationhelper_when_every_lrwhh_updateparent.patch diff --git a/patches/common/chromium/.patches b/patches/common/chromium/.patches index 06f8cbd21a607..2b0f234f8655b 100644 --- a/patches/common/chromium/.patches +++ b/patches/common/chromium/.patches @@ -84,3 +84,5 @@ fix_use_weakptr_to_detect_deletion.patch fix_disabling_compositor_recycling.patch allow_new_privileges_in_unsandboxed_child_processes.patch fix_add_more_checks_in_mojocdmservice.patch +recreate_directmanipulationhelper_when_every_lrwhh_updateparent.patch +notify_directmanipulationeventhandler_when_directmanipulationhelper.patch diff --git a/patches/common/chromium/notify_directmanipulationeventhandler_when_directmanipulationhelper.patch b/patches/common/chromium/notify_directmanipulationeventhandler_when_directmanipulationhelper.patch new file mode 100644 index 0000000000000..dec26bfb080f4 --- /dev/null +++ b/patches/common/chromium/notify_directmanipulationeventhandler_when_directmanipulationhelper.patch @@ -0,0 +1,118 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Siye Liu +Date: Thu, 15 Aug 2019 02:30:05 +0000 +Subject: Notify DirectManipulationEventHandler when DirectManipulationHelper + is destructed. + +The crash report shows that DirectManipulation may call +|DirectManipulationEventHandler::OnInteraction| after +DirectManipulationHelper is destroyed. Since |OnInteraction| is relying +on DirectManipulationHelper to add/remove animation observer, we should +set the pointer to DirectManipulationHelper to nullptr after it is +destroyed. + +In this CL, we set the pointer to DirectManipulationHelper in separate +function |SetDirectManipulationHelper| instead of passing the pointer +during ctor of DirectManipulationEventHandler. + +Bug: 993260 +Change-Id: Id781af047e72268532d861920a077a0c6b1650bb +Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1753661 +Reviewed-by: Scott Violet +Commit-Queue: Siye Liu +Cr-Commit-Position: refs/heads/master@{#687125} + +diff --git a/content/browser/renderer_host/direct_manipulation_event_handler_win.cc b/content/browser/renderer_host/direct_manipulation_event_handler_win.cc +index 33ce63d8d0f59573cb4764f146b4f88008cca4a8..bae879411fb253a810034eb2cb531a54530a4183 100644 +--- a/content/browser/renderer_host/direct_manipulation_event_handler_win.cc ++++ b/content/browser/renderer_host/direct_manipulation_event_handler_win.cc +@@ -28,9 +28,8 @@ bool FloatEquals(float f1, float f2) { + } // namespace + + DirectManipulationEventHandler::DirectManipulationEventHandler( +- DirectManipulationHelper* helper, + ui::WindowEventTarget* event_target) +- : helper_(helper), event_target_(event_target) {} ++ : event_target_(event_target) {} + + bool DirectManipulationEventHandler::SetViewportSizeInPixels( + const gfx::Size& viewport_size_in_pixels) { +@@ -45,6 +44,11 @@ void DirectManipulationEventHandler::SetDeviceScaleFactor( + device_scale_factor_ = device_scale_factor; + } + ++void DirectManipulationEventHandler::SetDirectManipulationHelper( ++ DirectManipulationHelper* helper) { ++ helper_ = helper; ++} ++ + DirectManipulationEventHandler::~DirectManipulationEventHandler() {} + + void DirectManipulationEventHandler::TransitionToState( +@@ -303,6 +307,9 @@ HRESULT DirectManipulationEventHandler::OnContentUpdated( + HRESULT DirectManipulationEventHandler::OnInteraction( + IDirectManipulationViewport2* viewport, + DIRECTMANIPULATION_INTERACTION_TYPE interaction) { ++ if (!helper_) ++ return S_OK; ++ + if (interaction == DIRECTMANIPULATION_INTERACTION_BEGIN) { + DebugLogging("OnInteraction BEGIN.", S_OK); + helper_->AddAnimationObserver(); +diff --git a/content/browser/renderer_host/direct_manipulation_event_handler_win.h b/content/browser/renderer_host/direct_manipulation_event_handler_win.h +index f1902085032ffc95edb2d8dcd5224f1c5ecda3d2..e654c5f1a45da9e054d2c367df6f5115fa25862c 100644 +--- a/content/browser/renderer_host/direct_manipulation_event_handler_win.h ++++ b/content/browser/renderer_host/direct_manipulation_event_handler_win.h +@@ -38,14 +38,15 @@ class DirectManipulationEventHandler + IDirectManipulationViewportEventHandler, + IDirectManipulationInteractionEventHandler>> { + public: +- DirectManipulationEventHandler(DirectManipulationHelper* helper, +- ui::WindowEventTarget* event_target); ++ DirectManipulationEventHandler(ui::WindowEventTarget* event_target); + + // Return true if viewport_size_in_pixels_ changed. + bool SetViewportSizeInPixels(const gfx::Size& viewport_size_in_pixels); + + void SetDeviceScaleFactor(float device_scale_factor); + ++ void SetDirectManipulationHelper(DirectManipulationHelper* helper); ++ + private: + friend class DirectManipulationBrowserTest; + friend DirectManipulationUnitTest; +diff --git a/content/browser/renderer_host/direct_manipulation_helper_win.cc b/content/browser/renderer_host/direct_manipulation_helper_win.cc +index 9401e7f8fb1fafd0532bb1e86035701c1df2ffda..6ce09b9f7b80e94c2adb582954c90afc95fc20e4 100644 +--- a/content/browser/renderer_host/direct_manipulation_helper_win.cc ++++ b/content/browser/renderer_host/direct_manipulation_helper_win.cc +@@ -78,8 +78,9 @@ DirectManipulationHelper::CreateInstanceForTesting( + base::WrapUnique(new DirectManipulationHelper(0, nullptr)); + + instance->event_handler_ = +- Microsoft::WRL::Make(instance.get(), +- event_target); ++ Microsoft::WRL::Make(event_target); ++ ++ instance->event_handler_->SetDirectManipulationHelper(instance.get()); + + instance->viewport_ = viewport; + +@@ -159,7 +160,9 @@ bool DirectManipulationHelper::Initialize(ui::WindowEventTarget* event_target) { + } + + event_handler_ = +- Microsoft::WRL::Make(this, event_target); ++ Microsoft::WRL::Make(event_target); ++ ++ event_handler_->SetDirectManipulationHelper(this); + + // We got Direct Manipulation transform from + // IDirectManipulationViewportEventHandler. +@@ -265,6 +268,7 @@ void DirectManipulationHelper::Destroy() { + if (has_animation_observer_) + RemoveAnimationObserver(); + compositor_ = nullptr; ++ event_handler_->SetDirectManipulationHelper(nullptr); + + HRESULT hr; + if (viewport_) { diff --git a/patches/common/chromium/recreate_directmanipulationhelper_when_every_lrwhh_updateparent.patch b/patches/common/chromium/recreate_directmanipulationhelper_when_every_lrwhh_updateparent.patch new file mode 100644 index 0000000000000..c1688b62918f1 --- /dev/null +++ b/patches/common/chromium/recreate_directmanipulationhelper_when_every_lrwhh_updateparent.patch @@ -0,0 +1,975 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Siye Liu +Date: Mon, 12 Aug 2019 19:26:49 +0000 +Subject: Recreate DirectManipulationHelper when every LRWHH UpdateParent + +This is a reland of 7da070704275ac67c95a89dd373a1dc0a1ba1256 and +d77c5029a13a83e676833aea61966a003564e57a + +Compositor and window event target is associated with window's parent. +We call LRWHH UpdateParent when window's parent update, includes +window's parent actually update and window initialize. Recreate +DirectManipulationHelper on every window's parent update helps keep +DirectManipulationHelper lifecycle tracking simpler. We also make +CompositorAnimationObserver owned by DirectManipulationHelper. + +With this changes, we start the DirectManipulation event polling when +DirectManipulationHelper created and stop when it destroyed. The issue +should be fix since event polling start no more depends on +DM_POINTERHITTEST. + +This CL also includes 3 refactoring changes: + +1. Move CompositorAnimationObserver into DirectManipulationHelper. +2. Call ZoomToRect to reset viewport of DirectManipulation when + viewport is actually transformed in RUNNING - READAY sequence. +3. Pass the viewport size to DMEventHandler and use it to reset viewport + at gesture end. + +The original changes caused a regression that browser UI composition +keeps ticking begin frames. We register DirectManipulationHelperWin +as an AnimationObserver of ui::Compositor. UI compositor will ask for +begin frames as long as it has an AnimationObserver. We should call +OnCompositorShuttingDown() when the compositor is going Idle. Therefore, +I added a IDirectManipulationInteractionEventHandler that adds the +observer when a manipulation begins, and removes it when manipulation +ends. After my fix, we start the DirectManipulation event polling when +DirectManipulation interaction begin and stop when DirectManipulation +interaction end. + +Bug: 914914 +Change-Id: I9f59381bdcc6e4ed0970003d87b26ac750bfb42d +Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1689922 +Reviewed-by: Scott Violet +Commit-Queue: Siye Liu +Cr-Commit-Position: refs/heads/master@{#686111} + +diff --git a/content/browser/renderer_host/direct_manipulation_event_handler_win.cc b/content/browser/renderer_host/direct_manipulation_event_handler_win.cc +index eec54fcb0187cfd47286d51226057b2fc4b3204a..33ce63d8d0f59573cb4764f146b4f88008cca4a8 100644 +--- a/content/browser/renderer_host/direct_manipulation_event_handler_win.cc ++++ b/content/browser/renderer_host/direct_manipulation_event_handler_win.cc +@@ -28,19 +28,16 @@ bool FloatEquals(float f1, float f2) { + } // namespace + + DirectManipulationEventHandler::DirectManipulationEventHandler( +- DirectManipulationHelper* helper) +- : helper_(helper) {} +- +-void DirectManipulationEventHandler::SetWindowEventTarget( +- ui::WindowEventTarget* event_target) { +- if (!event_target && LoggingEnabled()) { +- DebugLogging("Event target is null.", S_OK); +- if (event_target_) +- DebugLogging("Previous event target is not null", S_OK); +- else +- DebugLogging("Previous event target is null", S_OK); +- } +- event_target_ = event_target; ++ DirectManipulationHelper* helper, ++ ui::WindowEventTarget* event_target) ++ : helper_(helper), event_target_(event_target) {} ++ ++bool DirectManipulationEventHandler::SetViewportSizeInPixels( ++ const gfx::Size& viewport_size_in_pixels) { ++ if (viewport_size_in_pixels_ == viewport_size_in_pixels) ++ return false; ++ viewport_size_in_pixels_ = viewport_size_in_pixels; ++ return true; + } + + void DirectManipulationEventHandler::SetDeviceScaleFactor( +@@ -175,19 +172,28 @@ HRESULT DirectManipulationEventHandler::OnViewportStatusChanged( + if (current != DIRECTMANIPULATION_READY) + return S_OK; + +- // Reset the viewport when we're idle, so the content transforms always start +- // at identity. +- // Every animation will receive 2 ready message, we should stop request +- // compositor animation at the second ready. +- first_ready_ = !first_ready_; +- HRESULT hr = helper_->Reset(first_ready_); ++ // Normally gesture sequence will receive 2 READY message, the first one is ++ // gesture end, the second one is from viewport reset. We don't have content ++ // transform in the second RUNNING -> READY. We should not reset on an empty ++ // RUNNING -> READY sequence. ++ if (last_scale_ != 1.0f || last_x_offset_ != 0 || last_y_offset_ != 0) { ++ HRESULT hr = viewport->ZoomToRect( ++ static_cast(0), static_cast(0), ++ static_cast(viewport_size_in_pixels_.width()), ++ static_cast(viewport_size_in_pixels_.height()), FALSE); ++ if (!SUCCEEDED(hr)) { ++ DebugLogging("Viewport zoom to rect failed.", hr); ++ return hr; ++ } ++ } ++ + last_scale_ = 1.0f; + last_x_offset_ = 0.0f; + last_y_offset_ = 0.0f; + + TransitionToState(GestureState::kNone); + +- return hr; ++ return S_OK; + } + + HRESULT DirectManipulationEventHandler::OnViewportUpdated( +@@ -294,4 +300,18 @@ HRESULT DirectManipulationEventHandler::OnContentUpdated( + return hr; + } + ++HRESULT DirectManipulationEventHandler::OnInteraction( ++ IDirectManipulationViewport2* viewport, ++ DIRECTMANIPULATION_INTERACTION_TYPE interaction) { ++ if (interaction == DIRECTMANIPULATION_INTERACTION_BEGIN) { ++ DebugLogging("OnInteraction BEGIN.", S_OK); ++ helper_->AddAnimationObserver(); ++ } else if (interaction == DIRECTMANIPULATION_INTERACTION_END) { ++ DebugLogging("OnInteraction END.", S_OK); ++ helper_->RemoveAnimationObserver(); ++ } ++ ++ return S_OK; ++} ++ + } // namespace content +diff --git a/content/browser/renderer_host/direct_manipulation_event_handler_win.h b/content/browser/renderer_host/direct_manipulation_event_handler_win.h +index 270e85a09feb0add5b62afe3d9234627070ffe00..f1902085032ffc95edb2d8dcd5224f1c5ecda3d2 100644 +--- a/content/browser/renderer_host/direct_manipulation_event_handler_win.h ++++ b/content/browser/renderer_host/direct_manipulation_event_handler_win.h +@@ -11,6 +11,7 @@ + #include + + #include "base/macros.h" ++#include "ui/gfx/geometry/size.h" + + namespace ui { + +@@ -21,6 +22,7 @@ class WindowEventTarget; + namespace content { + + class DirectManipulationHelper; ++class DirectManipulationBrowserTest; + class DirectManipulationUnitTest; + + // DirectManipulationEventHandler receives status update and gesture events from +@@ -33,17 +35,19 @@ class DirectManipulationEventHandler + Microsoft::WRL::RuntimeClassFlags< + Microsoft::WRL::RuntimeClassType::ClassicCom>, + Microsoft::WRL::FtmBase, +- IDirectManipulationViewportEventHandler>> { ++ IDirectManipulationViewportEventHandler, ++ IDirectManipulationInteractionEventHandler>> { + public: +- explicit DirectManipulationEventHandler(DirectManipulationHelper* helper); ++ DirectManipulationEventHandler(DirectManipulationHelper* helper, ++ ui::WindowEventTarget* event_target); + +- // WindowEventTarget updates for every DM_POINTERHITTEST in case window +- // hierarchy changed. +- void SetWindowEventTarget(ui::WindowEventTarget* event_target); ++ // Return true if viewport_size_in_pixels_ changed. ++ bool SetViewportSizeInPixels(const gfx::Size& viewport_size_in_pixels); + + void SetDeviceScaleFactor(float device_scale_factor); + + private: ++ friend class DirectManipulationBrowserTest; + friend DirectManipulationUnitTest; + + // DirectManipulationEventHandler(); +@@ -65,18 +69,23 @@ class DirectManipulationEventHandler + OnContentUpdated(_In_ IDirectManipulationViewport* viewport, + _In_ IDirectManipulationContent* content) override; + ++ HRESULT STDMETHODCALLTYPE ++ OnInteraction(_In_ IDirectManipulationViewport2* viewport, ++ _In_ DIRECTMANIPULATION_INTERACTION_TYPE interaction) override; ++ + DirectManipulationHelper* helper_ = nullptr; + ui::WindowEventTarget* event_target_ = nullptr; + float device_scale_factor_ = 1.0f; + float last_scale_ = 1.0f; + int last_x_offset_ = 0; + int last_y_offset_ = 0; +- bool first_ready_ = false; + bool should_send_scroll_begin_ = false; + + // Current recognized gesture from Direct Manipulation. + GestureState gesture_state_ = GestureState::kNone; + ++ gfx::Size viewport_size_in_pixels_; ++ + DISALLOW_COPY_AND_ASSIGN(DirectManipulationEventHandler); + }; + +diff --git a/content/browser/renderer_host/direct_manipulation_helper_win.cc b/content/browser/renderer_host/direct_manipulation_helper_win.cc +index cc62fd688711153e2930fe06550c219e4cc01173..9401e7f8fb1fafd0532bb1e86035701c1df2ffda 100644 +--- a/content/browser/renderer_host/direct_manipulation_helper_win.cc ++++ b/content/browser/renderer_host/direct_manipulation_helper_win.cc +@@ -14,6 +14,8 @@ + #include "base/win/windows_version.h" + #include "ui/base/ui_base_features.h" + #include "ui/base/win/window_event_target.h" ++#include "ui/compositor/compositor.h" ++#include "ui/compositor/compositor_animation_observer.h" + #include "ui/display/win/screen_win.h" + #include "ui/gfx/geometry/rect.h" + +@@ -39,8 +41,9 @@ void DebugLogging(const std::string& s, HRESULT hr) { + // static + std::unique_ptr + DirectManipulationHelper::CreateInstance(HWND window, ++ ui::Compositor* compositor, + ui::WindowEventTarget* event_target) { +- if (!::IsWindow(window)) ++ if (!::IsWindow(window) || !compositor || !event_target) + return nullptr; + + if (!base::FeatureList::IsEnabled(features::kPrecisionTouchpad)) +@@ -51,8 +54,7 @@ DirectManipulationHelper::CreateInstance(HWND window, + return nullptr; + + std::unique_ptr instance = +- base::WrapUnique(new DirectManipulationHelper()); +- instance->window_ = window; ++ base::WrapUnique(new DirectManipulationHelper(window, compositor)); + + if (instance->Initialize(event_target)) + return instance; +@@ -73,11 +75,11 @@ DirectManipulationHelper::CreateInstanceForTesting( + return nullptr; + + std::unique_ptr instance = +- base::WrapUnique(new DirectManipulationHelper()); ++ base::WrapUnique(new DirectManipulationHelper(0, nullptr)); + + instance->event_handler_ = +- Microsoft::WRL::Make(instance.get()); +- instance->event_handler_->SetWindowEventTarget(event_target); ++ Microsoft::WRL::Make(instance.get(), ++ event_target); + + instance->viewport_ = viewport; + +@@ -85,11 +87,25 @@ DirectManipulationHelper::CreateInstanceForTesting( + } + + DirectManipulationHelper::~DirectManipulationHelper() { +- if (viewport_) +- viewport_->Abandon(); ++ Destroy(); + } + +-DirectManipulationHelper::DirectManipulationHelper() {} ++DirectManipulationHelper::DirectManipulationHelper(HWND window, ++ ui::Compositor* compositor) ++ : window_(window), compositor_(compositor) {} ++ ++void DirectManipulationHelper::OnAnimationStep(base::TimeTicks timestamp) { ++ // Simulate 1 frame in update_manager_. ++ HRESULT hr = update_manager_->Update(nullptr); ++ if (!SUCCEEDED(hr)) ++ DebugLogging("UpdateManager update failed.", hr); ++} ++ ++void DirectManipulationHelper::OnCompositingShuttingDown( ++ ui::Compositor* compositor) { ++ DCHECK_EQ(compositor, compositor_); ++ Destroy(); ++} + + bool DirectManipulationHelper::Initialize(ui::WindowEventTarget* event_target) { + // IDirectManipulationUpdateManager is the first COM object created by the +@@ -142,8 +158,8 @@ bool DirectManipulationHelper::Initialize(ui::WindowEventTarget* event_target) { + return false; + } + +- event_handler_ = Microsoft::WRL::Make(this); +- event_handler_->SetWindowEventTarget(event_target); ++ event_handler_ = ++ Microsoft::WRL::Make(this, event_target); + + // We got Direct Manipulation transform from + // IDirectManipulationViewportEventHandler. +@@ -155,8 +171,9 @@ bool DirectManipulationHelper::Initialize(ui::WindowEventTarget* event_target) { + } + + // Set default rect for viewport before activate. +- viewport_size_in_pixels_ = {1000, 1000}; +- RECT rect = gfx::Rect(viewport_size_in_pixels_).ToRECT(); ++ gfx::Size viewport_size_in_pixels = {1000, 1000}; ++ event_handler_->SetViewportSizeInPixels(viewport_size_in_pixels); ++ RECT rect = gfx::Rect(viewport_size_in_pixels).ToRECT(); + hr = viewport_->SetViewportRect(&rect); + if (!SUCCEEDED(hr)) { + DebugLogging("Viewport set rect failed.", hr); +@@ -185,33 +202,9 @@ bool DirectManipulationHelper::Initialize(ui::WindowEventTarget* event_target) { + return true; + } + +-void DirectManipulationHelper::Activate() { +- HRESULT hr = viewport_->Stop(); +- if (!SUCCEEDED(hr)) { +- DebugLogging("Viewport stop failed.", hr); +- return; +- } +- +- hr = manager_->Activate(window_); +- if (!SUCCEEDED(hr)) +- DebugLogging("DirectManipulationManager activate failed.", hr); +-} +- +-void DirectManipulationHelper::Deactivate() { +- HRESULT hr = viewport_->Stop(); +- if (!SUCCEEDED(hr)) { +- DebugLogging("Viewport stop failed.", hr); +- return; +- } +- +- hr = manager_->Deactivate(window_); +- if (!SUCCEEDED(hr)) +- DebugLogging("DirectManipulationManager deactivate failed.", hr); +-} +- + void DirectManipulationHelper::SetSizeInPixels( + const gfx::Size& size_in_pixels) { +- if (viewport_size_in_pixels_ == size_in_pixels) ++ if (!event_handler_->SetViewportSizeInPixels(size_in_pixels)) + return; + + HRESULT hr = viewport_->Stop(); +@@ -220,16 +213,13 @@ void DirectManipulationHelper::SetSizeInPixels( + return; + } + +- viewport_size_in_pixels_ = size_in_pixels; +- RECT rect = gfx::Rect(viewport_size_in_pixels_).ToRECT(); ++ RECT rect = gfx::Rect(size_in_pixels).ToRECT(); + hr = viewport_->SetViewportRect(&rect); + if (!SUCCEEDED(hr)) + DebugLogging("Viewport set rect failed.", hr); + } + +-bool DirectManipulationHelper::OnPointerHitTest( +- WPARAM w_param, +- ui::WindowEventTarget* event_target) { ++void DirectManipulationHelper::OnPointerHitTest(WPARAM w_param) { + // Update the device scale factor. + event_handler_->SetDeviceScaleFactor( + display::win::ScreenWin::GetScaleFactorForHWND(window_)); +@@ -240,53 +230,62 @@ bool DirectManipulationHelper::OnPointerHitTest( + // For WM_POINTER, the pointer type will show the event from mouse. + // For WM_POINTERACTIVATE, the pointer id will be different with the following + // message. +- event_handler_->SetWindowEventTarget(event_target); +- + using GetPointerTypeFn = BOOL(WINAPI*)(UINT32, POINTER_INPUT_TYPE*); + UINT32 pointer_id = GET_POINTERID_WPARAM(w_param); + POINTER_INPUT_TYPE pointer_type; + static const auto get_pointer_type = reinterpret_cast( + base::win::GetUser32FunctionPointer("GetPointerType")); + if (get_pointer_type && get_pointer_type(pointer_id, &pointer_type) && +- pointer_type == PT_TOUCHPAD && event_target) { ++ pointer_type == PT_TOUCHPAD) { + HRESULT hr = viewport_->SetContact(pointer_id); +- if (!SUCCEEDED(hr)) { ++ if (!SUCCEEDED(hr)) + DebugLogging("Viewport set contact failed.", hr); +- return false; +- } +- +- // Request begin frame for fake viewport. +- need_poll_events_ = true; + } +- return need_poll_events_; + } + +-HRESULT DirectManipulationHelper::Reset(bool need_poll_events) { +- // By zooming the primary content to a rect that match the viewport rect, we +- // reset the content's transform to identity. +- HRESULT hr = viewport_->ZoomToRect( +- static_cast(0), static_cast(0), +- static_cast(viewport_size_in_pixels_.width()), +- static_cast(viewport_size_in_pixels_.height()), FALSE); +- if (!SUCCEEDED(hr)) { +- DebugLogging("Viewport zoom to rect failed.", hr); +- return hr; +- } +- +- need_poll_events_ = need_poll_events; +- return S_OK; ++void DirectManipulationHelper::AddAnimationObserver() { ++ DCHECK(compositor_); ++ compositor_->AddAnimationObserver(this); ++ has_animation_observer_ = true; + } + +-bool DirectManipulationHelper::PollForNextEvent() { +- // Simulate 1 frame in update_manager_. +- HRESULT hr = update_manager_->Update(nullptr); +- if (!SUCCEEDED(hr)) +- DebugLogging("UpdateManager update failed.", hr); +- return need_poll_events_; ++void DirectManipulationHelper::RemoveAnimationObserver() { ++ DCHECK(compositor_); ++ compositor_->RemoveAnimationObserver(this); ++ has_animation_observer_ = false; + } + + void DirectManipulationHelper::SetDeviceScaleFactorForTesting(float factor) { + event_handler_->SetDeviceScaleFactor(factor); + } + ++void DirectManipulationHelper::Destroy() { ++ if (!compositor_) ++ return; ++ if (has_animation_observer_) ++ RemoveAnimationObserver(); ++ compositor_ = nullptr; ++ ++ HRESULT hr; ++ if (viewport_) { ++ hr = viewport_->Stop(); ++ if (!SUCCEEDED(hr)) ++ DebugLogging("Viewport stop failed.", hr); ++ ++ hr = viewport_->RemoveEventHandler(view_port_handler_cookie_); ++ if (!SUCCEEDED(hr)) ++ DebugLogging("Viewport remove event handler failed.", hr); ++ ++ hr = viewport_->Abandon(); ++ if (!SUCCEEDED(hr)) ++ DebugLogging("Viewport abandon failed.", hr); ++ } ++ ++ if (manager_) { ++ hr = manager_->Deactivate(window_); ++ if (!SUCCEEDED(hr)) ++ DebugLogging("DirectManipulationManager deactivate failed.", hr); ++ } ++} ++ + } // namespace content +diff --git a/content/browser/renderer_host/direct_manipulation_helper_win.h b/content/browser/renderer_host/direct_manipulation_helper_win.h +index 76c889b35508ebd92f803a2dd723cfdc11cef1e1..adf19d6849f69b83c51b123c86600a15679da9c6 100644 +--- a/content/browser/renderer_host/direct_manipulation_helper_win.h ++++ b/content/browser/renderer_host/direct_manipulation_helper_win.h +@@ -16,10 +16,12 @@ + #include "base/macros.h" + #include "content/browser/renderer_host/direct_manipulation_event_handler_win.h" + #include "content/common/content_export.h" ++#include "ui/compositor/compositor_animation_observer.h" + #include "ui/gfx/geometry/size.h" + + namespace ui { + ++class Compositor; + class WindowEventTarget; + + } // namespace ui +@@ -44,13 +46,15 @@ bool LoggingEnabled(); + // when DM_POINTERHITTEST. + // 3. OnViewportStatusChanged will be called when the gesture phase change. + // OnContentUpdated will be called when the gesture update. +-class CONTENT_EXPORT DirectManipulationHelper { ++class CONTENT_EXPORT DirectManipulationHelper ++ : public ui::CompositorAnimationObserver { + public: + // Creates and initializes an instance of this class if Direct Manipulation is + // enabled on the platform. Returns nullptr if it disabled or failed on + // initialization. + static std::unique_ptr CreateInstance( + HWND window, ++ ui::Compositor* compositor, + ui::WindowEventTarget* event_target); + + // Creates and initializes an instance for testing. +@@ -58,49 +62,48 @@ class CONTENT_EXPORT DirectManipulationHelper { + ui::WindowEventTarget* event_target, + Microsoft::WRL::ComPtr viewport); + +- ~DirectManipulationHelper(); ++ ~DirectManipulationHelper() override; + +- // Actives Direct Manipulation, call when window show. +- void Activate(); +- +- // Deactivates Direct Manipulation, call when window show. +- void Deactivate(); ++ // CompositorAnimationObserver implements. ++ // DirectManipulation needs to poll for new events every frame while finger ++ // gesturing on touchpad. ++ void OnAnimationStep(base::TimeTicks timestamp) override; ++ void OnCompositingShuttingDown(ui::Compositor* compositor) override; + + // Updates viewport size. Call it when window bounds updated. + void SetSizeInPixels(const gfx::Size& size_in_pixels); + +- // Reset for gesture end. +- HRESULT Reset(bool need_animtation); ++ // Pass the pointer hit test to Direct Manipulation. ++ void OnPointerHitTest(WPARAM w_param); + +- // Pass the pointer hit test to Direct Manipulation. Return true indicated we +- // need poll for new events every frame from here. +- bool OnPointerHitTest(WPARAM w_param, ui::WindowEventTarget* event_target); ++ // Register this as an AnimationObserver of ui::Compositor. ++ void AddAnimationObserver(); + +- // On each frame poll new Direct Manipulation events. Return true if we still +- // need poll for new events on next frame, otherwise stop request need begin +- // frame. +- bool PollForNextEvent(); ++ // Unregister this as an AnimationObserver of ui::Compositor. ++ void RemoveAnimationObserver(); + + private: + friend class content::DirectManipulationBrowserTest; + friend class DirectManipulationUnitTest; + +- DirectManipulationHelper(); ++ DirectManipulationHelper(HWND window, ui::Compositor* compositor); + + // This function instantiates Direct Manipulation and creates a viewport for +- // the passed in |window|. Return false if initialize failed. ++ // |window_|. Return false if initialize failed. + bool Initialize(ui::WindowEventTarget* event_target); + + void SetDeviceScaleFactorForTesting(float factor); + ++ void Destroy(); ++ + Microsoft::WRL::ComPtr manager_; + Microsoft::WRL::ComPtr update_manager_; + Microsoft::WRL::ComPtr viewport_; + Microsoft::WRL::ComPtr event_handler_; + HWND window_; ++ ui::Compositor* compositor_ = nullptr; + DWORD view_port_handler_cookie_; +- bool need_poll_events_ = false; +- gfx::Size viewport_size_in_pixels_; ++ bool has_animation_observer_ = false; + + DISALLOW_COPY_AND_ASSIGN(DirectManipulationHelper); + }; +diff --git a/content/browser/renderer_host/direct_manipulation_win_browsertest.cc b/content/browser/renderer_host/direct_manipulation_win_browsertest.cc +index 7648cf140d0de6e82ea81c33877495c91e7a57a9..10cf453cda7110b0531854ba63bb908fdd590d50 100644 +--- a/content/browser/renderer_host/direct_manipulation_win_browsertest.cc ++++ b/content/browser/renderer_host/direct_manipulation_win_browsertest.cc +@@ -49,33 +49,23 @@ class DirectManipulationBrowserTest : public ContentBrowserTest, + return rwhva->legacy_render_widget_host_HWND_; + } + +- HWND GetSubWindowHWND() { +- LegacyRenderWidgetHostHWND* lrwhh = GetLegacyRenderWidgetHostHWND(); +- +- return lrwhh->hwnd(); +- } +- + ui::WindowEventTarget* GetWindowEventTarget() { + LegacyRenderWidgetHostHWND* lrwhh = GetLegacyRenderWidgetHostHWND(); + + return lrwhh->GetWindowEventTarget(lrwhh->GetParent()); + } + +- void SimulatePointerHitTest() { +- LegacyRenderWidgetHostHWND* lrwhh = GetLegacyRenderWidgetHostHWND(); +- +- lrwhh->direct_manipulation_helper_->need_poll_events_ = true; +- lrwhh->CreateAnimationObserver(); +- } +- +- void UpdateParent(HWND hwnd) { ++ void SetDirectManipulationInteraction( ++ DIRECTMANIPULATION_INTERACTION_TYPE type) { + LegacyRenderWidgetHostHWND* lrwhh = GetLegacyRenderWidgetHostHWND(); + +- lrwhh->UpdateParent(hwnd); ++ lrwhh->direct_manipulation_helper_->event_handler_->OnInteraction(nullptr, ++ type); + } + +- bool HasCompositorAnimationObserver(LegacyRenderWidgetHostHWND* lrwhh) { +- return lrwhh->compositor_animation_observer_ != nullptr; ++ bool HasAnimationObserver(LegacyRenderWidgetHostHWND* lrwhh) { ++ return lrwhh->direct_manipulation_helper_->compositor_ ++ ->HasAnimationObserver(lrwhh->direct_manipulation_helper_.get()); + } + + private: +@@ -88,8 +78,10 @@ INSTANTIATE_TEST_SUITE_P(WithScrollEventPhase, + DirectManipulationBrowserTest, + testing::Bool()); + +-// Ensure the AnimationObserver destroy when hwnd reparent to other hwnd. +-IN_PROC_BROWSER_TEST_P(DirectManipulationBrowserTest, HWNDReparent) { ++// Ensure the AnimationObserver is only created after direct manipulation ++// interaction begin and destroyed after direct manipulation interaction end. ++IN_PROC_BROWSER_TEST_P(DirectManipulationBrowserTest, ++ ObserverDuringInteraction) { + if (base::win::GetVersion() < base::win::Version::WIN10) + return; + +@@ -98,25 +90,20 @@ IN_PROC_BROWSER_TEST_P(DirectManipulationBrowserTest, HWNDReparent) { + LegacyRenderWidgetHostHWND* lrwhh = GetLegacyRenderWidgetHostHWND(); + ASSERT_TRUE(lrwhh); + +- // The observer should not create before it needed. +- ASSERT_TRUE(!HasCompositorAnimationObserver(lrwhh)); ++ // The observer should not be created before it is needed. ++ EXPECT_FALSE(HasAnimationObserver(lrwhh)); + +- // Add AnimationObserver to tab to simulate direct manipulation start. +- SimulatePointerHitTest(); +- ASSERT_TRUE(HasCompositorAnimationObserver(lrwhh)); ++ // Begin direct manipulation interaction. ++ SetDirectManipulationInteraction(DIRECTMANIPULATION_INTERACTION_BEGIN); ++ // AnimationObserver should be added after direct manipulation interaction ++ // begin. ++ EXPECT_TRUE(HasAnimationObserver(lrwhh)); + +- // Create another browser. +- Shell* shell2 = CreateBrowser(); +- NavigateToURL(shell2, GURL(url::kAboutBlankURL)); +- +- // Move to the tab to browser2. +- UpdateParent( +- shell2->window()->GetRootWindow()->GetHost()->GetAcceleratedWidget()); ++ // End direct manipulation interaction. ++ SetDirectManipulationInteraction(DIRECTMANIPULATION_INTERACTION_END); + + // The animation observer should be removed. +- EXPECT_FALSE(HasCompositorAnimationObserver(lrwhh)); +- +- shell2->Close(); ++ EXPECT_FALSE(HasAnimationObserver(lrwhh)); + } + + // EventLogger is to observe the events sent from WindowEventTarget (the root +diff --git a/content/browser/renderer_host/direct_manipulation_win_unittest.cc b/content/browser/renderer_host/direct_manipulation_win_unittest.cc +index 3bf1b55555d0485c25575264045d415cf534323c..ccfa4d90b4e5c546c78afdac7c6b7b36f6096514 100644 +--- a/content/browser/renderer_host/direct_manipulation_win_unittest.cc ++++ b/content/browser/renderer_host/direct_manipulation_win_unittest.cc +@@ -31,6 +31,12 @@ class MockDirectManipulationViewport + + ~MockDirectManipulationViewport() override {} + ++ bool WasZoomToRectCalled() { ++ bool called = zoom_to_rect_called_; ++ zoom_to_rect_called_ = false; ++ return called; ++ } ++ + HRESULT STDMETHODCALLTYPE Enable() override { return S_OK; } + + HRESULT STDMETHODCALLTYPE Disable() override { return S_OK; } +@@ -75,6 +81,7 @@ class MockDirectManipulationViewport + _In_ const float right, + _In_ const float bottom, + _In_ BOOL animate) override { ++ zoom_to_rect_called_ = true; + return S_OK; + } + +@@ -161,6 +168,8 @@ class MockDirectManipulationViewport + HRESULT STDMETHODCALLTYPE Abandon() override { return S_OK; } + + private: ++ bool zoom_to_rect_called_ = false; ++ + DISALLOW_COPY_AND_ASSIGN(MockDirectManipulationViewport); + }; + +@@ -397,13 +406,7 @@ class DirectManipulationUnitTest : public testing::Test { + viewport_.Get(), content_.Get()); + } + +- void SetNeedAnimation(bool need_poll_events) { +- direct_manipulation_helper_->need_poll_events_ = need_poll_events; +- } +- +- bool NeedAnimation() { +- return direct_manipulation_helper_->need_poll_events_; +- } ++ bool WasZoomToRectCalled() { return viewport_->WasZoomToRectCalled(); } + + void SetDeviceScaleFactor(float factor) { + direct_manipulation_helper_->SetDeviceScaleFactorForTesting(factor); +@@ -721,21 +724,19 @@ TEST_F(DirectManipulationUnitTest, + } + + TEST_F(DirectManipulationUnitTest, +- NeedAnimtationShouldBeFalseAfterSecondReset) { ++ ZoomToRectShouldNotBeCalledInEmptyRunningReadySequence) { + if (!GetDirectManipulationHelper()) + return; + +- // Direct Manipulation will set need_poll_events_ true when DM_POINTERTEST +- // from touchpad. +- SetNeedAnimation(true); ++ ContentUpdated(1.0f, 5, 0); + + // Receive first ready when gesture end. + ViewportStatusChanged(DIRECTMANIPULATION_READY, DIRECTMANIPULATION_RUNNING); +- EXPECT_TRUE(NeedAnimation()); ++ EXPECT_TRUE(WasZoomToRectCalled()); + + // Receive second ready from ZoomToRect. + ViewportStatusChanged(DIRECTMANIPULATION_READY, DIRECTMANIPULATION_RUNNING); +- EXPECT_FALSE(NeedAnimation()); ++ EXPECT_FALSE(WasZoomToRectCalled()); + } + + TEST_F(DirectManipulationUnitTest, HiDPIScroll) { +diff --git a/content/browser/renderer_host/legacy_render_widget_host_win.cc b/content/browser/renderer_host/legacy_render_widget_host_win.cc +index b78186969fc928468c67f0bfcc853f5d7418df95..d2dd02a743a9bc908b6f8438ccac9dd85aa0a281 100644 +--- a/content/browser/renderer_host/legacy_render_widget_host_win.cc ++++ b/content/browser/renderer_host/legacy_render_widget_host_win.cc +@@ -27,7 +27,6 @@ + #include "ui/base/view_prop.h" + #include "ui/base/win/internal_constants.h" + #include "ui/base/win/window_event_target.h" +-#include "ui/compositor/compositor.h" + #include "ui/display/win/screen_win.h" + #include "ui/gfx/geometry/rect.h" + +@@ -38,47 +37,6 @@ namespace content { + // accessibility support. + const int kIdScreenReaderHoneyPot = 1; + +-// DirectManipulation needs to poll for new events every frame while finger +-// gesturing on touchpad. +-class CompositorAnimationObserverForDirectManipulation +- : public ui::CompositorAnimationObserver { +- public: +- CompositorAnimationObserverForDirectManipulation( +- LegacyRenderWidgetHostHWND* render_widget_host_hwnd, +- ui::Compositor* compositor) +- : render_widget_host_hwnd_(render_widget_host_hwnd), +- compositor_(compositor) { +- DCHECK(compositor_); +- compositor_->AddAnimationObserver(this); +- DebugLogging("Add AnimationObserverForDirectManipulation."); +- } +- +- ~CompositorAnimationObserverForDirectManipulation() override { +- if (compositor_) { +- compositor_->RemoveAnimationObserver(this); +- DebugLogging("Remove AnimationObserverForDirectManipulation."); +- } +- } +- +- // ui::CompositorAnimationObserver +- void OnAnimationStep(base::TimeTicks timestamp) override { +- render_widget_host_hwnd_->PollForNextEvent(); +- } +- +- // ui::CompositorAnimationObserver +- void OnCompositingShuttingDown(ui::Compositor* compositor) override { +- DebugLogging("OnCompositingShuttingDown."); +- compositor->RemoveAnimationObserver(this); +- compositor_ = nullptr; +- } +- +- private: +- LegacyRenderWidgetHostHWND* render_widget_host_hwnd_; +- ui::Compositor* compositor_; +- +- DISALLOW_COPY_AND_ASSIGN(CompositorAnimationObserverForDirectManipulation); +-}; +- + // static + LegacyRenderWidgetHostHWND* LegacyRenderWidgetHostHWND::Create( + HWND parent) { +@@ -103,8 +61,9 @@ LegacyRenderWidgetHostHWND* LegacyRenderWidgetHostHWND::Create( + } + + void LegacyRenderWidgetHostHWND::Destroy() { +- // Stop the AnimationObserver when window close. +- DestroyAnimationObserver(); ++ // Delete DirectManipulationHelper before the window is destroyed. ++ if (direct_manipulation_helper_) ++ direct_manipulation_helper_.reset(); + host_ = nullptr; + if (::IsWindow(hwnd())) + ::DestroyWindow(hwnd()); +@@ -113,10 +72,16 @@ void LegacyRenderWidgetHostHWND::Destroy() { + void LegacyRenderWidgetHostHWND::UpdateParent(HWND parent) { + if (GetWindowEventTarget(GetParent())) + GetWindowEventTarget(GetParent())->HandleParentChanged(); +- // Stop the AnimationObserver when window hide. eg. tab switch, move tab to +- // another window. +- DestroyAnimationObserver(); ++ + ::SetParent(hwnd(), parent); ++ ++ // Direct Manipulation is enabled on Windows 10+. The CreateInstance function ++ // returns NULL if Direct Manipulation is not available. Recreate ++ // |direct_manipulation_helper_| when parent changed (compositor and window ++ // event target updated). ++ direct_manipulation_helper_ = DirectManipulationHelper::CreateInstance( ++ hwnd(), host_->GetNativeView()->GetHost()->compositor(), ++ GetWindowEventTarget(GetParent())); + } + + HWND LegacyRenderWidgetHostHWND::GetParent() { +@@ -125,14 +90,10 @@ HWND LegacyRenderWidgetHostHWND::GetParent() { + + void LegacyRenderWidgetHostHWND::Show() { + ::ShowWindow(hwnd(), SW_SHOW); +- if (direct_manipulation_helper_) +- direct_manipulation_helper_->Activate(); + } + + void LegacyRenderWidgetHostHWND::Hide() { + ::ShowWindow(hwnd(), SW_HIDE); +- if (direct_manipulation_helper_) +- direct_manipulation_helper_->Deactivate(); + } + + void LegacyRenderWidgetHostHWND::SetBounds(const gfx::Rect& bounds) { +@@ -191,11 +152,6 @@ bool LegacyRenderWidgetHostHWND::Init() { + CHILDID_SELF); + } + +- // Direct Manipulation is enabled on Windows 10+. The CreateInstance function +- // returns NULL if Direct Manipulation is not available. +- direct_manipulation_helper_ = DirectManipulationHelper::CreateInstance( +- hwnd(), GetWindowEventTarget(GetParent())); +- + // Disable pen flicks (http://crbug.com/506977) + base::win::DisableFlicks(hwnd()); + +@@ -501,21 +457,6 @@ LRESULT LegacyRenderWidgetHostHWND::OnSize(UINT message, + return 0; + } + +-LRESULT LegacyRenderWidgetHostHWND::OnWindowPosChanged(UINT message, +- WPARAM w_param, +- LPARAM l_param) { +- WINDOWPOS* window_pos = reinterpret_cast(l_param); +- if (direct_manipulation_helper_) { +- if (window_pos->flags & SWP_SHOWWINDOW) { +- direct_manipulation_helper_->Activate(); +- } else if (window_pos->flags & SWP_HIDEWINDOW) { +- direct_manipulation_helper_->Deactivate(); +- } +- } +- SetMsgHandled(FALSE); +- return 0; +-} +- + LRESULT LegacyRenderWidgetHostHWND::OnDestroy(UINT message, + WPARAM w_param, + LPARAM l_param) { +@@ -534,30 +475,12 @@ LRESULT LegacyRenderWidgetHostHWND::OnPointerHitTest(UINT message, + return 0; + + DebugLogging("Receive DM_POINTERHITTEST."); +- // Update window event target for each DM_POINTERHITTEST. +- if (direct_manipulation_helper_->OnPointerHitTest( +- w_param, GetWindowEventTarget(GetParent()))) { +- if (compositor_animation_observer_) { +- // This is reach if Windows send a DM_POINTERHITTEST before the last +- // DM_POINTERHITTEST receive READY status. We never see this but still +- // worth to handle it. +- DebugLogging("AnimationObserverForDirectManipulation exists."); +- return 0; +- } + +- CreateAnimationObserver(); +- } ++ direct_manipulation_helper_->OnPointerHitTest(w_param); + + return 0; + } + +-void LegacyRenderWidgetHostHWND::PollForNextEvent() { +- DCHECK(direct_manipulation_helper_); +- +- if (!direct_manipulation_helper_->PollForNextEvent()) +- DestroyAnimationObserver(); +-} +- + gfx::NativeViewAccessible + LegacyRenderWidgetHostHWND::GetOrCreateWindowRootAccessible() { + if (!host_) +@@ -589,20 +512,4 @@ LegacyRenderWidgetHostHWND::GetOrCreateWindowRootAccessible() { + return root->GetNativeViewAccessible(); + } + +-void LegacyRenderWidgetHostHWND::CreateAnimationObserver() { +- DCHECK(!compositor_animation_observer_); +- DCHECK(host_); +- DCHECK(host_->GetNativeView()->GetHost()); +- DCHECK(host_->GetNativeView()->GetHost()->compositor()); +- +- compositor_animation_observer_ = +- std::make_unique( +- this, host_->GetNativeView()->GetHost()->compositor()); +-} +- +-void LegacyRenderWidgetHostHWND::DestroyAnimationObserver() { +- DebugLogging("DestroyAnimationObserver."); +- compositor_animation_observer_.reset(); +-} +- + } // namespace content +diff --git a/content/browser/renderer_host/legacy_render_widget_host_win.h b/content/browser/renderer_host/legacy_render_widget_host_win.h +index 4f12296e3185caac685c8326192d88d32037a9d9..be0ea7bdbf460f414c94b0f2275a00424ec3198a 100644 +--- a/content/browser/renderer_host/legacy_render_widget_host_win.h ++++ b/content/browser/renderer_host/legacy_render_widget_host_win.h +@@ -17,7 +17,6 @@ + + #include "base/macros.h" + #include "content/common/content_export.h" +-#include "ui/compositor/compositor_animation_observer.h" + #include "ui/gfx/geometry/rect.h" + #include "ui/gfx/native_widget_types.h" + +@@ -99,7 +98,6 @@ class CONTENT_EXPORT LegacyRenderWidgetHostHWND + OnMouseRange) + MESSAGE_HANDLER_EX(WM_NCCALCSIZE, OnNCCalcSize) + MESSAGE_HANDLER_EX(WM_SIZE, OnSize) +- MESSAGE_HANDLER_EX(WM_WINDOWPOSCHANGED, OnWindowPosChanged) + MESSAGE_HANDLER_EX(WM_DESTROY, OnDestroy) + MESSAGE_HANDLER_EX(DM_POINTERHITTEST, OnPointerHitTest) + END_MSG_MAP() +@@ -126,10 +124,6 @@ class CONTENT_EXPORT LegacyRenderWidgetHostHWND + host_ = host; + } + +- // DirectManipulation needs to poll for new events every frame while finger +- // gesturing on touchpad. +- void PollForNextEvent(); +- + // Return the root accessible object for either MSAA or UI Automation. + gfx::NativeViewAccessible GetOrCreateWindowRootAccessible(); + +@@ -166,15 +160,10 @@ class CONTENT_EXPORT LegacyRenderWidgetHostHWND + LRESULT OnSetCursor(UINT message, WPARAM w_param, LPARAM l_param); + LRESULT OnNCCalcSize(UINT message, WPARAM w_param, LPARAM l_param); + LRESULT OnSize(UINT message, WPARAM w_param, LPARAM l_param); +- LRESULT OnWindowPosChanged(UINT message, WPARAM w_param, LPARAM l_param); + LRESULT OnDestroy(UINT message, WPARAM w_param, LPARAM l_param); + + LRESULT OnPointerHitTest(UINT message, WPARAM w_param, LPARAM l_param); + +- void CreateAnimationObserver(); +- +- void DestroyAnimationObserver(); +- + Microsoft::WRL::ComPtr window_accessible_; + + // Set to true if we turned on mouse tracking. +@@ -193,9 +182,6 @@ class CONTENT_EXPORT LegacyRenderWidgetHostHWND + // in Chrome on Windows 10. + std::unique_ptr direct_manipulation_helper_; + +- std::unique_ptr +- compositor_animation_observer_; +- + DISALLOW_COPY_AND_ASSIGN(LegacyRenderWidgetHostHWND); + }; + From ffb96acab04012e4bfe8a9a5038bba6ddcebd478 Mon Sep 17 00:00:00 2001 From: Milan Burda Date: Thu, 10 Oct 2019 14:12:28 +0200 Subject: [PATCH 24/28] fix: when building with enable_plugins=false (#20354) (#20508) --- atom/app/atom_content_client.cc | 12 ++- atom/browser/api/atom_api_web_contents.cc | 3 + patches/common/chromium/.patches | 1 + ...n_building_with_enable_plugins_false.patch | 74 +++++++++++++++++++ 4 files changed, 88 insertions(+), 2 deletions(-) create mode 100644 patches/common/chromium/build_fix_when_building_with_enable_plugins_false.patch diff --git a/atom/app/atom_content_client.cc b/atom/app/atom_content_client.cc index f17184a8114a7..014c614a77eb1 100644 --- a/atom/app/atom_content_client.cc +++ b/atom/app/atom_content_client.cc @@ -15,9 +15,8 @@ #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "content/public/common/content_constants.h" -#include "content/public/common/pepper_plugin_info.h" #include "electron/buildflags/buildflags.h" -#include "ppapi/shared_impl/ppapi_permissions.h" +#include "ppapi/buildflags/buildflags.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" #include "url/url_constants.h" @@ -35,6 +34,11 @@ #include "pdf/pdf.h" #endif // BUILDFLAG(ENABLE_PDF_VIEWER) +#if BUILDFLAG(ENABLE_PLUGINS) +#include "content/public/common/pepper_plugin_info.h" +#include "ppapi/shared_impl/ppapi_permissions.h" +#endif // BUILDFLAG(ENABLE_PLUGINS) + namespace atom { namespace { @@ -141,6 +145,7 @@ void AddPepperFlashFromCommandLine( } #endif // BUILDFLAG(ENABLE_PEPPER_FLASH) +#if BUILDFLAG(ENABLE_PLUGINS) void ComputeBuiltInPlugins(std::vector* plugins) { #if BUILDFLAG(ENABLE_PDF_VIEWER) content::PepperPluginInfo pdf_info; @@ -161,6 +166,7 @@ void ComputeBuiltInPlugins(std::vector* plugins) { plugins->push_back(pdf_info); #endif // BUILDFLAG(ENABLE_PDF_VIEWER) } +#endif // BUILDFLAG(ENABLE_PLUGINS) void AppendDelimitedSwitchToVector(const base::StringPiece cmd_switch, std::vector* append_me) { @@ -227,7 +233,9 @@ void AtomContentClient::AddPepperPlugins( base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); AddPepperFlashFromCommandLine(command_line, plugins); #endif // BUILDFLAG(ENABLE_PEPPER_FLASH) +#if BUILDFLAG(ENABLE_PLUGINS) ComputeBuiltInPlugins(plugins); +#endif // BUILDFLAG(ENABLE_PLUGINS) } void AtomContentClient::AddContentDecryptionModules( diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index c7b6793db3684..ddd4939f54805 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -85,6 +85,7 @@ #include "native_mate/dictionary.h" #include "native_mate/object_template_builder.h" #include "net/url_request/url_request_context.h" +#include "ppapi/buildflags/buildflags.h" #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" #include "third_party/blink/public/mojom/frame/find_in_page.mojom.h" #include "third_party/blink/public/platform/web_cursor_info.h" @@ -833,10 +834,12 @@ void WebContents::RenderProcessGone(base::TerminationStatus status) { void WebContents::PluginCrashed(const base::FilePath& plugin_path, base::ProcessId plugin_pid) { +#if BUILDFLAG(ENABLE_PLUGINS) content::WebPluginInfo info; auto* plugin_service = content::PluginService::GetInstance(); plugin_service->GetPluginInfoByPath(plugin_path, &info); Emit("plugin-crashed", info.name, info.version); +#endif // BUILDFLAG(ENABLE_PLUIGNS) } void WebContents::MediaStartedPlaying(const MediaPlayerInfo& video_type, diff --git a/patches/common/chromium/.patches b/patches/common/chromium/.patches index 2b0f234f8655b..9f6d231173f28 100644 --- a/patches/common/chromium/.patches +++ b/patches/common/chromium/.patches @@ -86,3 +86,4 @@ allow_new_privileges_in_unsandboxed_child_processes.patch fix_add_more_checks_in_mojocdmservice.patch recreate_directmanipulationhelper_when_every_lrwhh_updateparent.patch notify_directmanipulationeventhandler_when_directmanipulationhelper.patch +build_fix_when_building_with_enable_plugins_false.patch diff --git a/patches/common/chromium/build_fix_when_building_with_enable_plugins_false.patch b/patches/common/chromium/build_fix_when_building_with_enable_plugins_false.patch new file mode 100644 index 0000000000000..54809da2b4bf3 --- /dev/null +++ b/patches/common/chromium/build_fix_when_building_with_enable_plugins_false.patch @@ -0,0 +1,74 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: deepak1556 +Date: Tue, 8 Oct 2019 15:40:50 +0000 +Subject: build: fix when building with enable_plugins=false + +Bug: none +Change-Id: If878b3a7f5bb051c6e99c617418475c12754ae90 +Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1845624 +Reviewed-by: Robert Sesek +Commit-Queue: Robert Sesek +Cr-Commit-Position: refs/heads/master@{#703739} + +diff --git a/AUTHORS b/AUTHORS +index 32fc92e6113c6324cc0b09b7a7ff309e2c89ddda..ae51b1d483564c96cb98b603280ac510f90c36c1 100644 +--- a/AUTHORS ++++ b/AUTHORS +@@ -219,6 +219,7 @@ Debashish Samantaray + Debug Wang + Deepak Dilip Borade + Deepak Mittal ++Deepak Mohan + Deepak Sharma + Deepak Singla + Deokjin Kim +diff --git a/content/browser/sandbox_parameters_mac.mm b/content/browser/sandbox_parameters_mac.mm +index b4d539bab49d468e0d2bdade76aad3dba0facfc4..73905a6eac811f9bff04e1b0ceb47b3ea326ee62 100644 +--- a/content/browser/sandbox_parameters_mac.mm ++++ b/content/browser/sandbox_parameters_mac.mm +@@ -21,12 +21,16 @@ + #include "content/public/browser/plugin_service.h" + #include "content/public/common/content_client.h" + #include "content/public/common/content_switches.h" +-#include "content/public/common/pepper_plugin_info.h" ++#include "ppapi/buildflags/buildflags.h" + #include "sandbox/mac/seatbelt_exec.h" + #include "services/service_manager/sandbox/mac/sandbox_mac.h" + #include "services/service_manager/sandbox/sandbox_type.h" + #include "services/service_manager/sandbox/switches.h" + ++#if BUILDFLAG(ENABLE_PLUGINS) ++#include "content/public/common/pepper_plugin_info.h" ++#endif ++ + namespace content { + + namespace { +@@ -125,6 +129,7 @@ void SetupNetworkSandboxParameters(sandbox::SeatbeltExecClient* client) { + } + } + ++#if BUILDFLAG(ENABLE_PLUGINS) + void SetupPPAPISandboxParameters(sandbox::SeatbeltExecClient* client) { + SetupCommonSandboxParameters(client); + +@@ -149,6 +154,7 @@ void SetupPPAPISandboxParameters(sandbox::SeatbeltExecClient* client) { + // to n+1 more than the plugins added. + CHECK(index <= 5); + } ++#endif + + void SetupCDMSandboxParameters(sandbox::SeatbeltExecClient* client) { + SetupCommonSandboxParameters(client); +@@ -186,9 +192,11 @@ void SetupSandboxParameters(service_manager::SandboxType sandbox_type, + case service_manager::SANDBOX_TYPE_NETWORK: + SetupNetworkSandboxParameters(client); + break; ++#if BUILDFLAG(ENABLE_PLUGINS) + case service_manager::SANDBOX_TYPE_PPAPI: + SetupPPAPISandboxParameters(client); + break; ++#endif + case service_manager::SANDBOX_TYPE_PROFILING: + case service_manager::SANDBOX_TYPE_UTILITY: + SetupUtilitySandboxParameters(client, command_line); From e257981a6dc8755b0435cbdbebb59340020fc2ef Mon Sep 17 00:00:00 2001 From: "trop[bot]" <37223003+trop[bot]@users.noreply.github.com> Date: Mon, 14 Oct 2019 12:38:01 -0700 Subject: [PATCH 25/28] spec: allow "Yu Gothic" as a Japanese sans-serif font on Windows (#20569) --- spec/chromium-spec.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/chromium-spec.js b/spec/chromium-spec.js index aecc974fc1b94..a06f429113283 100644 --- a/spec/chromium-spec.js +++ b/spec/chromium-spec.js @@ -1568,9 +1568,9 @@ describe('font fallback', () => { const fonts = await getRenderedFonts(html) expect(fonts).to.be.an('array') expect(fonts).to.have.length(1) - expect(fonts[0].familyName).to.equal({ - 'win32': 'Meiryo', - 'darwin': 'Hiragino Kaku Gothic ProN' + expect(fonts[0].familyName).to.be.oneOf({ + 'win32': ['Meiryo', 'Yu Gothic'], + 'darwin': ['Hiragino Kaku Gothic ProN'] }[process.platform]) }) }) From a12de693b08e1103aed6786e7468667acfe56f71 Mon Sep 17 00:00:00 2001 From: "trop[bot]" <37223003+trop[bot]@users.noreply.github.com> Date: Tue, 15 Oct 2019 09:14:25 -0700 Subject: [PATCH 26/28] ci: add macOS debug builds (#20572) * ci: add macOS debug builds * Fix mac debug builds * Remove ninja status as it is not available in 6-0-x --- .circleci/config.yml | 29 +++++++++++++++++++++++++++++ BUILD.gn | 4 +--- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 84c4f6ab3d67b..c2e835a0efadf 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -640,9 +640,11 @@ steps-electron-build-for-tests: &steps-electron-build-for-tests - *step-depot-tools-add-to-path - *step-setup-env-for-build - *step-restore-brew-cache + - *step-get-more-space-on-mac - *step-install-npm-deps-on-mac - *step-fix-sync-on-mac - *step-gn-gen-default + - *step-delete-git-directories # Electron app - *step-electron-build @@ -1099,6 +1101,14 @@ jobs: <<: *env-enable-sccache <<: *steps-electron-build-for-tests + osx-debug: + <<: *machine-mac-large + environment: + <<: *env-mac-large + <<: *env-debug-build + <<: *env-enable-sccache + <<: *steps-electron-build-for-tests + osx-debug-gn-check: <<: *machine-mac environment: @@ -1147,6 +1157,15 @@ jobs: <<: *env-enable-sccache <<: *steps-electron-build-for-tests + mas-debug: + <<: *machine-mac-large + environment: + <<: *env-mac-large + <<: *env-mas + <<: *env-debug-build + <<: *env-enable-sccache + <<: *steps-electron-build-for-tests + mas-debug-gn-check: <<: *machine-mac environment: @@ -1470,9 +1489,14 @@ workflows: requires: - mac-checkout + - osx-debug: + requires: + - mac-checkout + - osx-debug-gn-check: requires: - mac-checkout + - osx-testing-gn-check: requires: - mac-checkout @@ -1485,9 +1509,14 @@ workflows: requires: - mac-checkout + - mas-debug: + requires: + - mac-checkout + - mas-debug-gn-check: requires: - mac-checkout + - mas-testing-gn-check: requires: - mac-checkout diff --git a/BUILD.gn b/BUILD.gn index a7c471f611fac..de94f837acc9e 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -657,9 +657,7 @@ static_library("electron_lib") { } if (enable_desktop_capturer) { - if (is_component_build && is_win) { - # On windows the implementation relies on unexported - # DxgiDuplicatorController class. + if (is_component_build && !is_linux) { deps += [ "//third_party/webrtc/modules/desktop_capture" ] } sources += [ From d5b088bc26682d74e3f707f94ea95f71a2e57931 Mon Sep 17 00:00:00 2001 From: Robo Date: Fri, 18 Oct 2019 09:57:08 -0700 Subject: [PATCH 27/28] fix: add patch to node for native module size issue on windows (#20614) (#20627) --- patches/node/.patches | 1 + ...ng_back_node_with_ltcg_configuration.patch | 42 +++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 patches/node/build_bring_back_node_with_ltcg_configuration.patch diff --git a/patches/node/.patches b/patches/node/.patches index bf7dc4efef84a..7fa240e76a173 100644 --- a/patches/node/.patches +++ b/patches/node/.patches @@ -57,3 +57,4 @@ fix_set_uptime_offset_in_correct_init_method.patch fix_enable_worker_threads.patch fsevents-stop-using-fsevents-to-watch-files.patch fsevents-regression-in-watching.patch +build_bring_back_node_with_ltcg_configuration.patch diff --git a/patches/node/build_bring_back_node_with_ltcg_configuration.patch b/patches/node/build_bring_back_node_with_ltcg_configuration.patch new file mode 100644 index 0000000000000..24fb0cd6e28d0 --- /dev/null +++ b/patches/node/build_bring_back_node_with_ltcg_configuration.patch @@ -0,0 +1,42 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Deepak Mohan +Date: Wed, 16 Oct 2019 13:41:12 -0700 +Subject: build: bring back node_with_ltcg configuration + +This was moved to code node.gyp as part of https://github.com/nodejs/node/pull/25931 +which caused native modules size increase which were depending on +this configuration transitively https://github.com/nodejs/node/issues/29501. +THe fix for this should land in node-gyp as discussed in above issue, +landing this as temporary patch. + +diff --git a/common.gypi b/common.gypi +index f07e65f719a1a5939997dfcae7bc787ee6391f4d..69b5439a5c19230e5568450c3aca9ce27661d77c 100644 +--- a/common.gypi ++++ b/common.gypi +@@ -180,6 +180,26 @@ + 'cflags': [ '-fPIE' ], + 'ldflags': [ '-fPIE', '-pie' ] + }], ++ ['node_with_ltcg=="true"', { ++ 'msvs_settings': { ++ 'VCCLCompilerTool': { ++ 'WholeProgramOptimization': 'true' # /GL, whole program optimization, needed for LTCG ++ }, ++ 'VCLibrarianTool': { ++ 'AdditionalOptions': [ ++ '/LTCG:INCREMENTAL', # incremental link-time code generation ++ ] ++ }, ++ 'VCLinkerTool': { ++ 'OptimizeReferences': 2, # /OPT:REF ++ 'EnableCOMDATFolding': 2, # /OPT:ICF ++ 'LinkIncremental': 1, # disable incremental linking ++ 'AdditionalOptions': [ ++ '/LTCG:INCREMENTAL', # incremental link-time code generation ++ ] ++ } ++ } ++ }] + ], + 'msvs_settings': { + 'VCCLCompilerTool': { From 9901700a91bfc9a03a2d8f0c73f02129664f62cf Mon Sep 17 00:00:00 2001 From: Milan Burda Date: Mon, 21 Oct 2019 21:40:21 +0200 Subject: [PATCH 28/28] test: skip desktopCapturer / remote module tests when the features are disabled (#20566) (#20577) --- spec-main/api-app-spec.ts | 159 ++++++++++++++++++++------------------ spec-main/spec-helpers.ts | 4 + 2 files changed, 87 insertions(+), 76 deletions(-) create mode 100644 spec-main/spec-helpers.ts diff --git a/spec-main/api-app-spec.ts b/spec-main/api-app-spec.ts index 710607a97c4ca..cf57a25e3d23d 100644 --- a/spec-main/api-app-spec.ts +++ b/spec-main/api-app-spec.ts @@ -9,6 +9,9 @@ import split = require('split') import { app, BrowserWindow, Menu } from 'electron' import { emittedOnce } from './events-helpers'; import { closeWindow } from './window-helpers'; +import { ifdescribe } from './spec-helpers'; + +const features = process.electronBinding('features') const { expect } = chai @@ -405,103 +408,107 @@ describe('app module', () => { expect(webContents).to.equal(w.webContents) }) - it('should emit desktop-capturer-get-sources event when desktopCapturer.getSources() is invoked', async () => { - w = new BrowserWindow({ - show: false, - webPreferences: { - nodeIntegration: true - } - }) - await w.loadURL('about:blank') - - const promise = emittedOnce(app, 'desktop-capturer-get-sources') - w.webContents.executeJavaScript(`require('electron').desktopCapturer.getSources({ types: ['screen'] }, () => {})`) + ifdescribe(features.isDesktopCapturerEnabled())('desktopCapturer module filtering', () => { + it('should emit desktop-capturer-get-sources event when desktopCapturer.getSources() is invoked', async () => { + w = new BrowserWindow({ + show: false, + webPreferences: { + nodeIntegration: true + } + }) + await w.loadURL('about:blank') - const [, webContents] = await promise - expect(webContents).to.equal(w.webContents) - }) + const promise = emittedOnce(app, 'desktop-capturer-get-sources') + w.webContents.executeJavaScript(`require('electron').desktopCapturer.getSources({ types: ['screen'] }, () => {})`) - it('should emit remote-require event when remote.require() is invoked', async () => { - w = new BrowserWindow({ - show: false, - webPreferences: { - nodeIntegration: true - } + const [, webContents] = await promise + expect(webContents).to.equal(w.webContents) }) - await w.loadURL('about:blank') + }) - const promise = emittedOnce(app, 'remote-require') - w.webContents.executeJavaScript(`require('electron').remote.require('test')`) + describe('remote module filtering', () => { + it('should emit remote-require event when remote.require() is invoked', async () => { + w = new BrowserWindow({ + show: false, + webPreferences: { + nodeIntegration: true + } + }) + await w.loadURL('about:blank') - const [, webContents, moduleName] = await promise - expect(webContents).to.equal(w.webContents) - expect(moduleName).to.equal('test') - }) + const promise = emittedOnce(app, 'remote-require') + w.webContents.executeJavaScript(`require('electron').remote.require('test')`) - it('should emit remote-get-global event when remote.getGlobal() is invoked', async () => { - w = new BrowserWindow({ - show: false, - webPreferences: { - nodeIntegration: true - } + const [, webContents, moduleName] = await promise + expect(webContents).to.equal(w.webContents) + expect(moduleName).to.equal('test') }) - await w.loadURL('about:blank') - const promise = emittedOnce(app, 'remote-get-global') - w.webContents.executeJavaScript(`require('electron').remote.getGlobal('test')`) + it('should emit remote-get-global event when remote.getGlobal() is invoked', async () => { + w = new BrowserWindow({ + show: false, + webPreferences: { + nodeIntegration: true + } + }) + await w.loadURL('about:blank') - const [, webContents, globalName] = await promise - expect(webContents).to.equal(w.webContents) - expect(globalName).to.equal('test') - }) + const promise = emittedOnce(app, 'remote-get-global') + w.webContents.executeJavaScript(`require('electron').remote.getGlobal('test')`) - it('should emit remote-get-builtin event when remote.getBuiltin() is invoked', async () => { - w = new BrowserWindow({ - show: false, - webPreferences: { - nodeIntegration: true - } + const [, webContents, globalName] = await promise + expect(webContents).to.equal(w.webContents) + expect(globalName).to.equal('test') }) - await w.loadURL('about:blank') - const promise = emittedOnce(app, 'remote-get-builtin') - w.webContents.executeJavaScript(`require('electron').remote.app`) + it('should emit remote-get-builtin event when remote.getBuiltin() is invoked', async () => { + w = new BrowserWindow({ + show: false, + webPreferences: { + nodeIntegration: true + } + }) + await w.loadURL('about:blank') - const [, webContents, moduleName] = await promise - expect(webContents).to.equal(w.webContents) - expect(moduleName).to.equal('app') - }) + const promise = emittedOnce(app, 'remote-get-builtin') + w.webContents.executeJavaScript(`require('electron').remote.app`) - it('should emit remote-get-current-window event when remote.getCurrentWindow() is invoked', async () => { - w = new BrowserWindow({ - show: false, - webPreferences: { - nodeIntegration: true - } + const [, webContents, moduleName] = await promise + expect(webContents).to.equal(w.webContents) + expect(moduleName).to.equal('app') }) - await w.loadURL('about:blank') - const promise = emittedOnce(app, 'remote-get-current-window') - w.webContents.executeJavaScript(`require('electron').remote.getCurrentWindow()`) + it('should emit remote-get-current-window event when remote.getCurrentWindow() is invoked', async () => { + w = new BrowserWindow({ + show: false, + webPreferences: { + nodeIntegration: true + } + }) + await w.loadURL('about:blank') - const [, webContents] = await promise - expect(webContents).to.equal(w.webContents) - }) + const promise = emittedOnce(app, 'remote-get-current-window') + w.webContents.executeJavaScript(`require('electron').remote.getCurrentWindow()`) - it('should emit remote-get-current-web-contents event when remote.getCurrentWebContents() is invoked', async () => { - w = new BrowserWindow({ - show: false, - webPreferences: { - nodeIntegration: true - } + const [, webContents] = await promise + expect(webContents).to.equal(w.webContents) }) - await w.loadURL('about:blank') - const promise = emittedOnce(app, 'remote-get-current-web-contents') - w.webContents.executeJavaScript(`require('electron').remote.getCurrentWebContents()`) + it('should emit remote-get-current-web-contents event when remote.getCurrentWebContents() is invoked', async () => { + w = new BrowserWindow({ + show: false, + webPreferences: { + nodeIntegration: true + } + }) + await w.loadURL('about:blank') + + const promise = emittedOnce(app, 'remote-get-current-web-contents') + w.webContents.executeJavaScript(`require('electron').remote.getCurrentWebContents()`) - const [, webContents] = await promise - expect(webContents).to.equal(w.webContents) + const [, webContents] = await promise + expect(webContents).to.equal(w.webContents) + }) }) }) diff --git a/spec-main/spec-helpers.ts b/spec-main/spec-helpers.ts new file mode 100644 index 0000000000000..89953c17aae4c --- /dev/null +++ b/spec-main/spec-helpers.ts @@ -0,0 +1,4 @@ +export const ifit = (condition: boolean) => (condition ? it : it.skip) +export const ifdescribe = (condition: boolean) => (condition ? describe : describe.skip) + +export const delay = (time: number) => new Promise(r => setTimeout(r, time))