From 3bc3896ee75df30883be05e064d6cbd7d74dd609 Mon Sep 17 00:00:00 2001 From: Kevin Ushey Date: Tue, 8 Mar 2022 11:15:05 -0800 Subject: [PATCH 01/38] docs: fix documented return value for getFocusedWebContents (#33170) --- docs/api/web-contents.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index d4a1233c5976a..64af596682384 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -35,7 +35,7 @@ for all windows, webviews, opened devtools, and devtools extension background pa ### `webContents.getFocusedWebContents()` -Returns `WebContents` - The web contents that is focused in this application, otherwise +Returns `WebContents` | null - The web contents that is focused in this application, otherwise returns `null`. ### `webContents.fromId(id)` From b96f15bfc262edd88d5df8c3684484c894d08ce5 Mon Sep 17 00:00:00 2001 From: Milan Burda Date: Tue, 8 Mar 2022 20:38:15 +0100 Subject: [PATCH 02/38] fix: patches to use BUILDFLAG(IS_WIN) / BUILDFLAG(IS_MAC) checks (#33160) --- ...ransfer_to_requestsingleinstancelock.patch | 6 +++--- ...screen_rendering_with_viz_compositor.patch | 20 ++++++++++--------- ...media_key_usage_with_globalshortcuts.patch | 6 +++--- patches/chromium/process_singleton.patch | 10 +++++----- 4 files changed, 22 insertions(+), 20 deletions(-) diff --git a/patches/chromium/feat_add_data_transfer_to_requestsingleinstancelock.patch b/patches/chromium/feat_add_data_transfer_to_requestsingleinstancelock.patch index fd11a39b225c8..a609f4e83a6de 100644 --- a/patches/chromium/feat_add_data_transfer_to_requestsingleinstancelock.patch +++ b/patches/chromium/feat_add_data_transfer_to_requestsingleinstancelock.patch @@ -19,7 +19,7 @@ instance, but also so the second instance can send back additional data to the first instance if needed. diff --git a/chrome/browser/process_singleton.h b/chrome/browser/process_singleton.h -index 8f94cc300b58e8a94b6ca155aa3cf370bcb948d8..4340376f323d24e5e2c5897a81c6a9ebf13adab4 100644 +index 5a64220aaf1309832dc0ad543e353de67fe0a779..a568dd10d1ef8679d66f4cdc6a471c251cbcd4eb 100644 --- a/chrome/browser/process_singleton.h +++ b/chrome/browser/process_singleton.h @@ -18,6 +18,7 @@ @@ -49,7 +49,7 @@ index 8f94cc300b58e8a94b6ca155aa3cf370bcb948d8..4340376f323d24e5e2c5897a81c6a9eb + const std::vector additional_data, + const NotificationAckCallback& ack_callback)>; - #if defined(OS_WIN) + #if BUILDFLAG(IS_WIN) ProcessSingleton(const std::string& program_name, const base::FilePath& user_data_dir, + const base::span additional_data, @@ -96,7 +96,7 @@ index 8f94cc300b58e8a94b6ca155aa3cf370bcb948d8..4340376f323d24e5e2c5897a81c6a9eb // Return true if the given pid is one of our child processes. // Assumes that the current pid is the root of all pids of the current diff --git a/chrome/browser/process_singleton_posix.cc b/chrome/browser/process_singleton_posix.cc -index 47e60bfd8239d4a2e292b835c49132bdbb751555..9861a884a15e79b36833e6df58897141acdc6718 100644 +index 7d3a441bdb64268ed5fbfa7bf589fb35a2fd1b75..b23c16fde275fdba559abb1f30e42f65ddbfc332 100644 --- a/chrome/browser/process_singleton_posix.cc +++ b/chrome/browser/process_singleton_posix.cc @@ -148,7 +148,7 @@ const char kACKToken[] = "ACK"; diff --git a/patches/chromium/feat_enable_offscreen_rendering_with_viz_compositor.patch b/patches/chromium/feat_enable_offscreen_rendering_with_viz_compositor.patch index d2675bfa80b29..231ad6fe4f48e 100644 --- a/patches/chromium/feat_enable_offscreen_rendering_with_viz_compositor.patch +++ b/patches/chromium/feat_enable_offscreen_rendering_with_viz_compositor.patch @@ -226,10 +226,10 @@ index a480befb5d8db36e7e281d5033aeef0bea83d220..4e54acc897d08c87bccc3b44f68634e2 diff --git a/components/viz/service/display_embedder/software_output_device_proxy.cc b/components/viz/service/display_embedder/software_output_device_proxy.cc new file mode 100644 -index 0000000000000000000000000000000000000000..4efea02f80f8b6818291321a7c63f0f4815a5b98 +index 0000000000000000000000000000000000000000..88aba74877a6490e08e357266b1ce8461b5b6dff --- /dev/null +++ b/components/viz/service/display_embedder/software_output_device_proxy.cc -@@ -0,0 +1,157 @@ +@@ -0,0 +1,158 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. @@ -239,6 +239,7 @@ index 0000000000000000000000000000000000000000..4efea02f80f8b6818291321a7c63f0f4 +#include "base/memory/unsafe_shared_memory_region.h" +#include "base/threading/thread_checker.h" +#include "base/trace_event/trace_event.h" ++#include "build/build_config.h" +#include "components/viz/common/resources/resource_sizes.h" +#include "components/viz/service/display_embedder/output_device_backing.h" +#include "mojo/public/cpp/system/platform_handle.h" @@ -247,7 +248,7 @@ index 0000000000000000000000000000000000000000..4efea02f80f8b6818291321a7c63f0f4 +#include "third_party/skia/include/core/SkCanvas.h" +#include "ui/gfx/skia_util.h" + -+#if defined(OS_WIN) ++#if BUILDFLAG(IS_WIN) +#include "skia/ext/skia_utils_win.h" +#include "ui/gfx/gdi_util.h" +#include "ui/gfx/win/hwnd_util.h" @@ -389,10 +390,10 @@ index 0000000000000000000000000000000000000000..4efea02f80f8b6818291321a7c63f0f4 +} // namespace viz diff --git a/components/viz/service/display_embedder/software_output_device_proxy.h b/components/viz/service/display_embedder/software_output_device_proxy.h new file mode 100644 -index 0000000000000000000000000000000000000000..fbc517e164d9bf33256c1ecbe86e31744375097e +index 0000000000000000000000000000000000000000..a80258d6165e45a3c3d2b551158ff7d2a5778a7c --- /dev/null +++ b/components/viz/service/display_embedder/software_output_device_proxy.h -@@ -0,0 +1,92 @@ +@@ -0,0 +1,93 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. @@ -400,20 +401,21 @@ index 0000000000000000000000000000000000000000..fbc517e164d9bf33256c1ecbe86e3174 +#ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SOFTWARE_OUTPUT_DEVICE_PROXY_H_ +#define COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SOFTWARE_OUTPUT_DEVICE_PROXY_H_ + -+#if defined(OS_WIN) -+#include -+#endif -+ +#include + +#include "base/memory/shared_memory_mapping.h" +#include "base/threading/thread_checker.h" ++#include "build/build_config.h" +#include "components/viz/host/host_display_client.h" +#include "components/viz/service/display/software_output_device.h" +#include "components/viz/service/viz_service_export.h" +#include "services/viz/privileged/mojom/compositing/display_private.mojom.h" +#include "services/viz/privileged/mojom/compositing/layered_window_updater.mojom.h" + ++#if BUILDFLAG(IS_WIN) ++#include ++#endif ++ +namespace viz { + +// Shared base class for SoftwareOutputDevice implementations. diff --git a/patches/chromium/fix_media_key_usage_with_globalshortcuts.patch b/patches/chromium/fix_media_key_usage_with_globalshortcuts.patch index 2986f58de269f..7460a09ea3beb 100644 --- a/patches/chromium/fix_media_key_usage_with_globalshortcuts.patch +++ b/patches/chromium/fix_media_key_usage_with_globalshortcuts.patch @@ -59,7 +59,7 @@ index ad366d0fd4c3a637d75a102ab56984f0d01bfc04..d63eb133fd4bab1ea309bb8c742acf88 // true if register successfully, or false if 1) the specificied |accelerator| // has been registered by another caller or other native applications, or diff --git a/content/browser/media/media_keys_listener_manager_impl.cc b/content/browser/media/media_keys_listener_manager_impl.cc -index ac923f436cbdd6ded0629da4e4c659d94258e55b..7e603dd5bad2a60b1bd7d9df569a10e838d797bc 100644 +index ac923f436cbdd6ded0629da4e4c659d94258e55b..43f9531075bcef87de8e60f24071f49fe4cd0891 100644 --- a/content/browser/media/media_keys_listener_manager_impl.cc +++ b/content/browser/media/media_keys_listener_manager_impl.cc @@ -55,7 +55,12 @@ bool MediaKeysListenerManagerImpl::StartWatchingMediaKey( @@ -68,9 +68,9 @@ index ac923f436cbdd6ded0629da4e4c659d94258e55b..7e603dd5bad2a60b1bd7d9df569a10e8 // Tell the underlying MediaKeysListener to listen for the key. - if (should_start_watching && media_keys_listener_ && + if ( -+#if defined(OS_MAC) ++#if BUILDFLAG(IS_MAC) + !media_key_handling_enabled_ && -+#endif // defined(OS_MAC) ++#endif // BUILDFLAG(IS_MAC) + should_start_watching && + media_keys_listener_ && !media_keys_listener_->StartWatchingMediaKey(key_code)) { diff --git a/patches/chromium/process_singleton.patch b/patches/chromium/process_singleton.patch index 58d5bc201d4af..565c00742ba81 100644 --- a/patches/chromium/process_singleton.patch +++ b/patches/chromium/process_singleton.patch @@ -24,14 +24,14 @@ This patch adds a few changes to the Chromium code: before the browser thread is ready. diff --git a/chrome/browser/process_singleton.h b/chrome/browser/process_singleton.h -index 16bb3aa15a5378e8319f75f4b6b72b39177828f4..8f94cc300b58e8a94b6ca155aa3cf370bcb948d8 100644 +index 16bb3aa15a5378e8319f75f4b6b72b39177828f4..5a64220aaf1309832dc0ad543e353de67fe0a779 100644 --- a/chrome/browser/process_singleton.h +++ b/chrome/browser/process_singleton.h @@ -102,12 +102,19 @@ class ProcessSingleton { base::RepeatingCallback; -+#if defined(OS_WIN) ++#if BUILDFLAG(IS_WIN) + ProcessSingleton(const std::string& program_name, + const base::FilePath& user_data_dir, + bool is_sandboxed, @@ -75,7 +75,7 @@ index 16bb3aa15a5378e8319f75f4b6b72b39177828f4..8f94cc300b58e8a94b6ca155aa3cf370 #if BUILDFLAG(IS_MAC) diff --git a/chrome/browser/process_singleton_posix.cc b/chrome/browser/process_singleton_posix.cc -index c9f26ea2d2ea16484d416fdce095ec1b8b885991..47e60bfd8239d4a2e292b835c49132bdbb751555 100644 +index c9f26ea2d2ea16484d416fdce095ec1b8b885991..7d3a441bdb64268ed5fbfa7bf589fb35a2fd1b75 100644 --- a/chrome/browser/process_singleton_posix.cc +++ b/chrome/browser/process_singleton_posix.cc @@ -53,6 +53,7 @@ @@ -129,7 +129,7 @@ index c9f26ea2d2ea16484d416fdce095ec1b8b885991..47e60bfd8239d4a2e292b835c49132bd } +bool IsAppSandboxed() { -+#if defined(OS_MAC) ++#if BUILDFLAG(IS_MAC) + // NB: There is no sane API for this, we have to just guess by + // reading tea leaves + base::FilePath home_dir; @@ -140,7 +140,7 @@ index c9f26ea2d2ea16484d416fdce095ec1b8b885991..47e60bfd8239d4a2e292b835c49132bd + return home_dir.value().find("Library/Containers") != std::string::npos; +#else + return false; -+#endif // defined(OS_MAC) ++#endif // BUILDFLAG(IS_MAC) +} + bool ConnectSocket(ScopedSocket* socket, From 076bc58b2a15ff18ab07d67e23864aa7b4a4a9eb Mon Sep 17 00:00:00 2001 From: Shelley Vohr Date: Tue, 8 Mar 2022 11:40:25 -0800 Subject: [PATCH 03/38] fix: crash when showin item in folder on DevTools (#33024) --- shell/browser/ui/inspectable_web_contents.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/shell/browser/ui/inspectable_web_contents.cc b/shell/browser/ui/inspectable_web_contents.cc index b7e939c35d45f..150b2fcba242c 100644 --- a/shell/browser/ui/inspectable_web_contents.cc +++ b/shell/browser/ui/inspectable_web_contents.cc @@ -175,6 +175,10 @@ GURL GetDevToolsURL(bool can_dock) { return GURL(url_string); } +void OnOpenItemComplete(const base::FilePath& path, const std::string& result) { + platform_util::ShowItemInFolder(path); +} + constexpr base::TimeDelta kInitialBackoffDelay = base::Milliseconds(250); constexpr base::TimeDelta kMaxBackoffDelay = base::Seconds(10); @@ -737,9 +741,8 @@ void InspectableWebContents::ShowItemInFolder( return; base::FilePath path = base::FilePath::FromUTF8Unsafe(file_system_path); - - // Pass empty callback here; we can ignore errors - platform_util::OpenPath(path, platform_util::OpenCallback()); + platform_util::OpenPath(path.DirName(), + base::BindOnce(&OnOpenItemComplete, path)); } void InspectableWebContents::SaveToFile(const std::string& url, From e41c3e960dd3a53c1f423c746b7079abb4359841 Mon Sep 17 00:00:00 2001 From: Calvin Date: Tue, 8 Mar 2022 14:06:20 -0700 Subject: [PATCH 04/38] fix: non-client mouse events on WCO-enabled windows (#32871) --- patches/chromium/.patches | 1 + ...king_and_message_bubbling_on_windows.patch | 61 +++++++++++++++++++ .../electron_desktop_window_tree_host_win.cc | 17 ------ .../electron_desktop_window_tree_host_win.h | 1 - 4 files changed, 62 insertions(+), 18 deletions(-) create mode 100644 patches/chromium/fix_non-client_mouse_tracking_and_message_bubbling_on_windows.patch diff --git a/patches/chromium/.patches b/patches/chromium/.patches index 995bb12ffa7c7..545165e4e06ad 100644 --- a/patches/chromium/.patches +++ b/patches/chromium/.patches @@ -113,3 +113,4 @@ fix_crash_when_saving_edited_pdf_files.patch port_autofill_colors_to_the_color_pipeline.patch build_disable_partition_alloc_on_mac.patch build_disable_thin_lto_on_mac.patch +fix_non-client_mouse_tracking_and_message_bubbling_on_windows.patch diff --git a/patches/chromium/fix_non-client_mouse_tracking_and_message_bubbling_on_windows.patch b/patches/chromium/fix_non-client_mouse_tracking_and_message_bubbling_on_windows.patch new file mode 100644 index 0000000000000..86a3c0fbc97be --- /dev/null +++ b/patches/chromium/fix_non-client_mouse_tracking_and_message_bubbling_on_windows.patch @@ -0,0 +1,61 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: clavin +Date: Fri, 11 Feb 2022 15:05:42 -0700 +Subject: fix: non-client mouse tracking and message bubbling on windows + +It is not known why, but for some reason calling |DefWindowProc| on the parent +window handle causes a WM_NCMOUSELEAVE (non-client mouse exit) message to be +sent to the parent window, even though |TrackMouseEvent| is never called on it. + +This patch also adds some boilerplate for properly tracking non-client mouse +messages in the legacy window handle layer. + +These conditions are regularly hit with WCO-enabled windows on Windows. + +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 4a894ef70eeb1d8489049aef552c9bae4f24ae62..f5049d730a850f2947023f976b25fb772e42107a 100644 +--- a/content/browser/renderer_host/legacy_render_widget_host_win.cc ++++ b/content/browser/renderer_host/legacy_render_widget_host_win.cc +@@ -288,12 +288,12 @@ LRESULT LegacyRenderWidgetHostHWND::OnMouseRange(UINT message, + WPARAM w_param, + LPARAM l_param, + BOOL& handled) { +- if (message == WM_MOUSEMOVE) { ++ if (message == WM_MOUSEMOVE || message == WM_NCMOUSEMOVE) { + if (!mouse_tracking_enabled_) { + mouse_tracking_enabled_ = true; + TRACKMOUSEEVENT tme; + tme.cbSize = sizeof(tme); +- tme.dwFlags = TME_LEAVE; ++ tme.dwFlags = message == WM_NCMOUSEMOVE ? TME_NONCLIENT | TME_LEAVE : TME_LEAVE; + tme.hwndTrack = hwnd(); + tme.dwHoverTime = 0; + TrackMouseEvent(&tme); +@@ -319,12 +319,11 @@ LRESULT LegacyRenderWidgetHostHWND::OnMouseRange(UINT message, + message, w_param, l_param, &msg_handled); + handled = msg_handled; + // If the parent did not handle non client mouse messages, we call +- // DefWindowProc on the message with the parent window handle. This +- // ensures that WM_SYSCOMMAND is generated for the parent and we are +- // out of the picture. ++ // DefWindowProc on the message. This ensures that WM_SYSCOMMAND is ++ // generated. + if (!handled && + (message >= WM_NCMOUSEMOVE && message <= WM_NCXBUTTONDBLCLK)) { +- ret = ::DefWindowProc(GetParent(), message, w_param, l_param); ++ ret = ::DefWindowProc(hwnd(), message, w_param, l_param); + handled = TRUE; + } + } +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 79dffd981f4d461f30bd3796cfba1457eda3a89d..ae378ce95f90989fd0e74c38b57f5f7dc0a1ee29 100644 +--- a/content/browser/renderer_host/legacy_render_widget_host_win.h ++++ b/content/browser/renderer_host/legacy_render_widget_host_win.h +@@ -105,6 +105,7 @@ class CONTENT_EXPORT LegacyRenderWidgetHostHWND + MESSAGE_HANDLER_EX(WM_NCHITTEST, OnNCHitTest) + MESSAGE_RANGE_HANDLER(WM_NCMOUSEMOVE, WM_NCXBUTTONDBLCLK, + OnMouseRange) ++ MESSAGE_HANDLER_EX(WM_NCMOUSELEAVE, OnMouseLeave) + MESSAGE_HANDLER_EX(WM_NCCALCSIZE, OnNCCalcSize) + MESSAGE_HANDLER_EX(WM_SIZE, OnSize) + MESSAGE_HANDLER_EX(WM_DESTROY, OnDestroy) diff --git a/shell/browser/ui/win/electron_desktop_window_tree_host_win.cc b/shell/browser/ui/win/electron_desktop_window_tree_host_win.cc index 3600e273ea73b..2e4e5bc9502e4 100644 --- a/shell/browser/ui/win/electron_desktop_window_tree_host_win.cc +++ b/shell/browser/ui/win/electron_desktop_window_tree_host_win.cc @@ -99,21 +99,4 @@ bool ElectronDesktopWindowTreeHostWin::GetClientAreaInsets( return false; } -bool ElectronDesktopWindowTreeHostWin::HandleMouseEvent(ui::MouseEvent* event) { - // Call the default implementation of this method to get the event to its - // proper handler. - bool handled = views::DesktopWindowTreeHostWin::HandleMouseEvent(event); - - // On WCO-enabled windows, we need to mark non-client mouse moved events as - // handled so they don't incorrectly propogate back to the OS. - if (native_window_view_->IsWindowControlsOverlayEnabled() && - event->type() == ui::ET_MOUSE_MOVED && - (event->flags() & ui::EF_IS_NON_CLIENT) != 0) { - event->SetHandled(); - handled = true; - } - - return handled; -} - } // namespace electron diff --git a/shell/browser/ui/win/electron_desktop_window_tree_host_win.h b/shell/browser/ui/win/electron_desktop_window_tree_host_win.h index 8c7be1175a193..3fd831aae1ed0 100644 --- a/shell/browser/ui/win/electron_desktop_window_tree_host_win.h +++ b/shell/browser/ui/win/electron_desktop_window_tree_host_win.h @@ -36,7 +36,6 @@ class ElectronDesktopWindowTreeHostWin bool GetDwmFrameInsetsInPixels(gfx::Insets* insets) const override; bool GetClientAreaInsets(gfx::Insets* insets, HMONITOR monitor) const override; - bool HandleMouseEvent(ui::MouseEvent* event) override; private: NativeWindowViews* native_window_view_; // weak ref From 27527fe5ca790dc7061c6e816cc8b6ff72fe56d0 Mon Sep 17 00:00:00 2001 From: Jeremy Rose Date: Tue, 8 Mar 2022 15:39:53 -0800 Subject: [PATCH 05/38] feat: warn that preloads will be sandboxed by default in v20 (#32868) --- docs/breaking-changes.md | 19 +++++++++++++++++++ lib/browser/api/web-contents.ts | 6 +++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/docs/breaking-changes.md b/docs/breaking-changes.md index e603146d0372e..6d561f87bd75e 100644 --- a/docs/breaking-changes.md +++ b/docs/breaking-changes.md @@ -12,6 +12,25 @@ This document uses the following convention to categorize breaking changes: * **Deprecated:** An API was marked as deprecated. The API will continue to function, but will emit a deprecation warning, and will be removed in a future release. * **Removed:** An API or feature was removed, and is no longer supported by Electron. +## Planned Breaking API Changes (20.0) + +### Default Changed: renderers without `nodeIntegration: true` are sandboxed by default + +Previously, renderers that specified a preload script defaulted to being +unsandboxed. This meant that by default, preload scripts had access to Node.js. +In Electron 20, this default has changed. Beginning in Electron 20, renderers +will be sandboxed by default, unless `nodeIntegration: true` or `sandbox: false` +is specified. + +If your preload scripts do not depend on Node, no action is needed. If your +preload scripts _do_ depend on Node, either refactor them to remove Node usage +from the renderer, or explicitly specify `sandbox: false` for the relevant +renderers. + +## Planned Breaking API Changes (19.0) + +*None (yet)* + ## Planned Breaking API Changes (18.0) ### Removed: `nativeWindowOpen` diff --git a/lib/browser/api/web-contents.ts b/lib/browser/api/web-contents.ts index 4e2cd4acbda74..cafe85cae4364 100644 --- a/lib/browser/api/web-contents.ts +++ b/lib/browser/api/web-contents.ts @@ -1,4 +1,4 @@ -import { app, ipcMain, session, webFrameMain } from 'electron/main'; +import { app, ipcMain, session, webFrameMain, deprecate } from 'electron/main'; import type { BrowserWindowConstructorOptions, LoadURLOptions } from 'electron/main'; import * as url from 'url'; @@ -570,6 +570,10 @@ const loggingEnabled = () => { // Add JavaScript wrappers for WebContents class. WebContents.prototype._init = function () { + const prefs = this.getLastWebPreferences() || {}; + if (!prefs.nodeIntegration && (prefs.preload != null || prefs.preloadURL != null) && prefs.sandbox == null) { + deprecate.log('The default sandbox option for windows without nodeIntegration is changing. Presently, by default, when a window has a preload script, it defaults to being unsandboxed. In Electron 20, this default will be changing, and all windows that have nodeIntegration: false (which is the default) will be sandboxed by default. If your preload script doesn\'t use Node, no action is needed. If your preload script does use Node, either refactor it to move Node usage to the main process, or specify sandbox: false in your WebPreferences.'); + } // Read off the ID at construction time, so that it's accessible even after // the underlying C++ WebContents is destroyed. const id = this.id; From 373a9053199f8881cdec7d44b8f3524d68ae8223 Mon Sep 17 00:00:00 2001 From: Shelley Vohr Date: Tue, 8 Mar 2022 17:17:43 -0800 Subject: [PATCH 06/38] fix: settings not persisting across devtools loads (#33120) * fix: settings not persisting across devtools loads * chore: remove redundant RegisterPreference impl --- shell/browser/ui/inspectable_web_contents.cc | 119 +------------------ shell/browser/ui/inspectable_web_contents.h | 5 +- 2 files changed, 5 insertions(+), 119 deletions(-) diff --git a/shell/browser/ui/inspectable_web_contents.cc b/shell/browser/ui/inspectable_web_contents.cc index 150b2fcba242c..4779ee6c77f1e 100644 --- a/shell/browser/ui/inspectable_web_contents.cc +++ b/shell/browser/ui/inspectable_web_contents.cc @@ -86,13 +86,6 @@ const char kChromeUIDevToolsRemoteFrontendPath[] = "serve_file"; const char kDevToolsBoundsPref[] = "electron.devtools.bounds"; const char kDevToolsZoomPref[] = "electron.devtools.zoom"; const char kDevToolsPreferences[] = "electron.devtools.preferences"; -const char kDevToolsSyncPreferences[] = "electron.devtools.sync_preferences"; -const char kDevToolsSyncedPreferencesSyncEnabled[] = - "electron.devtools.synced_preferences_sync_enabled"; -const char kDevToolsSyncedPreferencesSyncDisabled[] = - "electron.devtools.synced_preferences_sync_disabled"; -const char kSyncDevToolsPreferencesFrontendName[] = "electron.sync_preferences"; -const bool kSyncDevToolsPreferencesDefault = false; const char kFrontendHostId[] = "id"; const char kFrontendHostMethod[] = "method"; @@ -346,10 +339,6 @@ void InspectableWebContents::RegisterPrefs(PrefRegistrySimple* registry) { RectToDictionary(gfx::Rect(0, 0, 800, 600))); registry->RegisterDoublePref(kDevToolsZoomPref, 0.); registry->RegisterDictionaryPref(kDevToolsPreferences); - registry->RegisterDictionaryPref(kDevToolsSyncedPreferencesSyncEnabled); - registry->RegisterDictionaryPref(kDevToolsSyncedPreferencesSyncDisabled); - registry->RegisterBooleanPref(kDevToolsSyncPreferences, - kSyncDevToolsPreferencesDefault); } InspectableWebContents::InspectableWebContents( @@ -867,85 +856,19 @@ void InspectableWebContents::SendJsonRequest(DispatchCallback callback, std::move(callback).Run(nullptr); } -void InspectableWebContents::RegisterPreference( - const std::string& name, - const RegisterOptions& options) { - // kSyncDevToolsPreferenceFrontendName is not stored in any of the relevant - // dictionaries. Skip registration. - if (name == kSyncDevToolsPreferencesFrontendName) - return; - - if (options.sync_mode == RegisterOptions::SyncMode::kSync) { - synced_setting_names_.insert(name); - } - - // Setting might have had a different sync status in the past. Move the - // setting to the correct dictionary. - const char* dictionary_to_remove_from = - options.sync_mode == RegisterOptions::SyncMode::kSync - ? kDevToolsPreferences - : GetDictionaryNameForSyncedPrefs(); - const std::string* settings_value = - pref_service_->GetDictionary(dictionary_to_remove_from) - ->FindStringKey(name); - if (!settings_value) { - return; - } - - const char* dictionary_to_insert_into = - GetDictionaryNameForSettingsName(name); - // Settings already moved to the synced dictionary on a different device have - // precedence. - const std::string* already_synced_value = - pref_service_->GetDictionary(dictionary_to_insert_into) - ->FindStringKey(name); - if (dictionary_to_insert_into == kDevToolsPreferences || - !already_synced_value) { - DictionaryPrefUpdate insert_update(pref_service_, - dictionary_to_insert_into); - insert_update.Get()->SetKey(name, base::Value(*settings_value)); - } - - DictionaryPrefUpdate remove_update(pref_service_, dictionary_to_remove_from); - remove_update.Get()->RemoveKey(name); -} - void InspectableWebContents::GetPreferences(DispatchCallback callback) { - base::Value settings(base::Value::Type::DICTIONARY); - settings.SetBoolKey(kSyncDevToolsPreferencesFrontendName, - pref_service_->GetBoolean(kDevToolsSyncPreferences)); - settings.MergeDictionary(pref_service_->GetDictionary(kDevToolsPreferences)); - settings.MergeDictionary( - pref_service_->GetDictionary(GetDictionaryNameForSyncedPrefs())); - - std::move(callback).Run(&settings); + const base::Value* prefs = pref_service_->GetDictionary(kDevToolsPreferences); + std::move(callback).Run(prefs); } void InspectableWebContents::GetPreference(DispatchCallback callback, const std::string& name) { - // Handle kSyncDevToolsPreferencesFrontendName - if (name == kSyncDevToolsPreferencesFrontendName) { - base::Value pref = - base::Value(pref_service_->GetBoolean(kDevToolsSyncPreferences)); - std::move(callback).Run(&pref); - return; - } - - // Check dev tools prefs if (auto* pref = pref_service_->GetDictionary(kDevToolsPreferences)->FindKey(name)) { std::move(callback).Run(pref); return; } - // Check synced prefs - if (auto* pref = - pref_service_->GetDictionary(GetDictionaryNameForSyncedPrefs()) - ->FindKey(name)) { - std::move(callback).Run(pref); - return; - } - // Pref wasn't found, return an empty value base::Value no_pref; std::move(callback).Run(&no_pref); @@ -953,41 +876,21 @@ void InspectableWebContents::GetPreference(DispatchCallback callback, void InspectableWebContents::SetPreference(const std::string& name, const std::string& value) { - if (name == kSyncDevToolsPreferencesFrontendName) { - pref_service_->SetBoolean(kDevToolsSyncPreferences, value == "true"); - return; - } - DictionaryPrefUpdate update(pref_service_, - GetDictionaryNameForSettingsName(name)); + DictionaryPrefUpdate update(pref_service_, kDevToolsPreferences); update.Get()->SetKey(name, base::Value(value)); } void InspectableWebContents::RemovePreference(const std::string& name) { - if (name == kSyncDevToolsPreferencesFrontendName) { - pref_service_->SetBoolean(kDevToolsSyncPreferences, - kSyncDevToolsPreferencesDefault); - return; - } - DictionaryPrefUpdate update(pref_service_, - GetDictionaryNameForSettingsName(name)); + DictionaryPrefUpdate update(pref_service_, kDevToolsPreferences); update.Get()->RemoveKey(name); } void InspectableWebContents::ClearPreferences() { - pref_service_->SetBoolean(kDevToolsSyncPreferences, - kSyncDevToolsPreferencesDefault); DictionaryPrefUpdate unsynced_update(pref_service_, kDevToolsPreferences); unsynced_update.Get()->DictClear(); - DictionaryPrefUpdate sync_enabled_update( - pref_service_, kDevToolsSyncedPreferencesSyncEnabled); - sync_enabled_update.Get()->DictClear(); - DictionaryPrefUpdate sync_disabled_update( - pref_service_, kDevToolsSyncedPreferencesSyncDisabled); - sync_disabled_update.Get()->DictClear(); } void InspectableWebContents::GetSyncInformation(DispatchCallback callback) { - // TODO(anyone): do we want devtool syncing in Electron? base::Value result(base::Value::Type::DICTIONARY); result.SetBoolKey("isSyncActive", false); std::move(callback).Run(&result); @@ -1172,18 +1075,4 @@ void InspectableWebContents::SendMessageAck(int request_id, CallClientFunction("DevToolsAPI.embedderMessageAck", &id_value, arg, nullptr); } -const char* InspectableWebContents::GetDictionaryNameForSettingsName( - const std::string& name) const { - return synced_setting_names_.contains(name) - ? kDevToolsSyncedPreferencesSyncEnabled - : kDevToolsPreferences; -} - -const char* InspectableWebContents::GetDictionaryNameForSyncedPrefs() const { - const bool isDevToolsSyncEnabled = - pref_service_->GetBoolean(kDevToolsSyncPreferences); - return isDevToolsSyncEnabled ? kDevToolsSyncedPreferencesSyncEnabled - : kDevToolsSyncedPreferencesSyncDisabled; -} - } // namespace electron diff --git a/shell/browser/ui/inspectable_web_contents.h b/shell/browser/ui/inspectable_web_contents.h index ba50d83b8aef4..bfc6cbae896d5 100644 --- a/shell/browser/ui/inspectable_web_contents.h +++ b/shell/browser/ui/inspectable_web_contents.h @@ -140,7 +140,7 @@ class InspectableWebContents const std::string& browser_id, const std::string& url) override; void RegisterPreference(const std::string& name, - const RegisterOptions& options) override; + const RegisterOptions& options) override {} void GetPreferences(DispatchCallback callback) override; void GetPreference(DispatchCallback callback, const std::string& name) override; @@ -198,9 +198,6 @@ class InspectableWebContents void SendMessageAck(int request_id, const base::Value* arg1); - const char* GetDictionaryNameForSettingsName(const std::string& name) const; - const char* GetDictionaryNameForSyncedPrefs() const; - #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS) void AddDevToolsExtensionsToClient(); #endif From 865a29ed17d498335790c2c6998578e1e76c5513 Mon Sep 17 00:00:00 2001 From: Sudowoodo Release Bot <88427002+sudowoodo-release-bot[bot]@users.noreply.github.com> Date: Wed, 9 Mar 2022 05:00:38 -0800 Subject: [PATCH 07/38] Bump v19.0.0-nightly.20220309 --- ELECTRON_VERSION | 2 +- package.json | 2 +- shell/browser/resources/win/electron.rc | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ELECTRON_VERSION b/ELECTRON_VERSION index 49ae2ccc9e679..22d94b6c5b151 100644 --- a/ELECTRON_VERSION +++ b/ELECTRON_VERSION @@ -1 +1 @@ -19.0.0-nightly.20220308 \ No newline at end of file +19.0.0-nightly.20220309 \ No newline at end of file diff --git a/package.json b/package.json index 7012c583db14e..1e1905a55217f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "electron", - "version": "19.0.0-nightly.20220308", + "version": "19.0.0-nightly.20220309", "repository": "https://github.com/electron/electron", "description": "Build cross platform desktop apps with JavaScript, HTML, and CSS", "devDependencies": { diff --git a/shell/browser/resources/win/electron.rc b/shell/browser/resources/win/electron.rc index 8d84f50990408..771f39264ebaf 100644 --- a/shell/browser/resources/win/electron.rc +++ b/shell/browser/resources/win/electron.rc @@ -50,8 +50,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 19,0,0,20220308 - PRODUCTVERSION 19,0,0,20220308 + FILEVERSION 19,0,0,20220309 + PRODUCTVERSION 19,0,0,20220309 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L From ebfcf89a0b554804fc8707215752a1130dc10182 Mon Sep 17 00:00:00 2001 From: Jeremy Rose Date: Wed, 9 Mar 2022 07:15:50 -0800 Subject: [PATCH 08/38] fix: propagate unsafely-treat-insecure-origin-as-secure to renderer children (#33189) * fix: propagate unsafely-treat-insecure-origin-as-secure to renderer children * fix build --- shell/browser/electron_browser_client.cc | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/shell/browser/electron_browser_client.cc b/shell/browser/electron_browser_client.cc index 096dcabb56c4f..04e31a63b754d 100644 --- a/shell/browser/electron_browser_client.cc +++ b/shell/browser/electron_browser_client.cc @@ -21,6 +21,7 @@ #include "base/no_destructor.h" #include "base/path_service.h" #include "base/stl_util.h" +#include "base/strings/strcat.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" @@ -63,6 +64,8 @@ #include "printing/buildflags/buildflags.h" #include "services/device/public/cpp/geolocation/location_provider.h" #include "services/network/public/cpp/features.h" +#include "services/network/public/cpp/is_potentially_trustworthy.h" +#include "services/network/public/cpp/network_switches.h" #include "services/network/public/cpp/resource_request_body.h" #include "services/network/public/cpp/self_deleting_url_loader_factory.h" #include "shell/app/electron_crash_reporter_client.h" @@ -361,6 +364,21 @@ int GetCrashSignalFD(const base::CommandLine& command_line) { } #endif // BUILDFLAG(IS_LINUX) +void MaybeAppendSecureOriginsAllowlistSwitch(base::CommandLine* cmdline) { + // |allowlist| combines pref/policy + cmdline switch in the browser process. + // For renderer and utility (e.g. NetworkService) processes the switch is the + // only available source, so below the combined (pref/policy + cmdline) + // allowlist of secure origins is injected into |cmdline| for these other + // processes. + std::vector allowlist = + network::SecureOriginAllowlist::GetInstance().GetCurrentAllowlist(); + if (!allowlist.empty()) { + cmdline->AppendSwitchASCII( + network::switches::kUnsafelyTreatInsecureOriginAsSecure, + base::JoinString(allowlist, ",")); + } +} + } // namespace // static @@ -602,6 +620,10 @@ void ElectronBrowserClient::AppendExtraCommandLineSwitches( command_line->CopySwitchesFrom(*base::CommandLine::ForCurrentProcess(), kCommonSwitchNames, base::size(kCommonSwitchNames)); + if (process_type == ::switches::kUtilityProcess || + content::RenderProcessHost::FromID(process_id)) { + MaybeAppendSecureOriginsAllowlistSwitch(command_line); + } } if (process_type == ::switches::kRendererProcess) { From 86e746c36b20c54c8e77d3d65bc9470b247b232c Mon Sep 17 00:00:00 2001 From: Harry Hopkinson <63599884+Harry-Hopkinson@users.noreply.github.com> Date: Wed, 9 Mar 2022 21:28:54 +0000 Subject: [PATCH 09/38] Formatted C++ Files According to the clang-format file. (#33158) --- spec-main/fixtures/native-addon/uv-dlopen/foo.cpp | 3 +-- spec-main/fixtures/native-addon/uv-dlopen/main.cpp | 12 ++++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/spec-main/fixtures/native-addon/uv-dlopen/foo.cpp b/spec-main/fixtures/native-addon/uv-dlopen/foo.cpp index 00beb974c1a72..7e2438f5006d2 100644 --- a/spec-main/fixtures/native-addon/uv-dlopen/foo.cpp +++ b/spec-main/fixtures/native-addon/uv-dlopen/foo.cpp @@ -1,2 +1 @@ -extern "C" -void foo() { } \ No newline at end of file +extern "C" void foo() {} \ No newline at end of file diff --git a/spec-main/fixtures/native-addon/uv-dlopen/main.cpp b/spec-main/fixtures/native-addon/uv-dlopen/main.cpp index 4d34850a6254c..5edef8a0ea627 100644 --- a/spec-main/fixtures/native-addon/uv-dlopen/main.cpp +++ b/spec-main/fixtures/native-addon/uv-dlopen/main.cpp @@ -8,22 +8,26 @@ napi_value TestLoadLibrary(napi_env env, napi_callback_info info) { napi_value argv; napi_status status; status = napi_get_cb_info(env, info, &argc, &argv, NULL, NULL); - if (status != napi_ok) napi_fatal_error(NULL, 0, NULL, 0); + if (status != napi_ok) + napi_fatal_error(NULL, 0, NULL, 0); char lib_path[256]; status = napi_get_value_string_utf8(env, argv, lib_path, 256, NULL); - if (status != napi_ok) napi_fatal_error(NULL, 0, NULL, 0); + if (status != napi_ok) + napi_fatal_error(NULL, 0, NULL, 0); uv_lib_t lib; auto uv_status = uv_dlopen(lib_path, &lib); if (uv_status == 0) { napi_value result; status = napi_get_boolean(env, true, &result); - if (status != napi_ok) napi_fatal_error(NULL, 0, NULL, 0); + if (status != napi_ok) + napi_fatal_error(NULL, 0, NULL, 0); return result; } else { status = napi_throw_error(env, NULL, uv_dlerror(&lib)); - if (status != napi_ok) napi_fatal_error(NULL, 0, NULL, 0); + if (status != napi_ok) + napi_fatal_error(NULL, 0, NULL, 0); } } From e589e9b259ecad5a2f2f47f0b8d40618d1c54601 Mon Sep 17 00:00:00 2001 From: David Sanders Date: Wed, 9 Mar 2022 14:30:42 -0800 Subject: [PATCH 10/38] fix: fire show event when BrowserWindow shown via maximize() (#32979) --- shell/browser/native_window_views.cc | 6 ++++-- shell/browser/native_window_views_win.cc | 7 ++++--- spec-main/api-browser-window-spec.ts | 23 +++++++++++++++++++++++ 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/shell/browser/native_window_views.cc b/shell/browser/native_window_views.cc index 2d3d866fa71dc..a5c58964016c3 100644 --- a/shell/browser/native_window_views.cc +++ b/shell/browser/native_window_views.cc @@ -580,11 +580,13 @@ void NativeWindowViews::SetEnabledInternal(bool enable) { #if BUILDFLAG(IS_LINUX) void NativeWindowViews::Maximize() { - if (IsVisible()) + if (IsVisible()) { widget()->Maximize(); - else + } else { widget()->native_widget_private()->Show(ui::SHOW_STATE_MAXIMIZED, gfx::Rect()); + NotifyWindowShow(); + } } #endif diff --git a/shell/browser/native_window_views_win.cc b/shell/browser/native_window_views_win.cc index ab336f2e29866..01d88048af794 100644 --- a/shell/browser/native_window_views_win.cc +++ b/shell/browser/native_window_views_win.cc @@ -178,12 +178,13 @@ HHOOK NativeWindowViews::mouse_hook_ = NULL; void NativeWindowViews::Maximize() { // Only use Maximize() when window is NOT transparent style if (!transparent()) { - if (IsVisible()) + if (IsVisible()) { widget()->Maximize(); - else + } else { widget()->native_widget_private()->Show(ui::SHOW_STATE_MAXIMIZED, gfx::Rect()); - return; + NotifyWindowShow(); + } } else { restore_bounds_ = GetBounds(); auto display = display::Screen::GetScreen()->GetDisplayNearestWindow( diff --git a/spec-main/api-browser-window-spec.ts b/spec-main/api-browser-window-spec.ts index 1e9405e0aa3c8..1ed8734711f33 100644 --- a/spec-main/api-browser-window-spec.ts +++ b/spec-main/api-browser-window-spec.ts @@ -3526,6 +3526,29 @@ describe('BrowserWindow module', () => { }); }); + // TODO(dsanders11): Enable once maximize event works on Linux again on CI + ifdescribe(process.platform !== 'linux')('BrowserWindow.maximize()', () => { + afterEach(closeAllWindows); + // TODO(dsanders11): Disabled on macOS, see https://github.com/electron/electron/issues/32947 + ifit(process.platform !== 'darwin')('should show the window if it is not currently shown', async () => { + const w = new BrowserWindow({ show: false }); + const hidden = emittedOnce(w, 'hide'); + const shown = emittedOnce(w, 'show'); + const maximize = emittedOnce(w, 'maximize'); + expect(w.isVisible()).to.be.false('visible'); + w.maximize(); + await maximize; + expect(w.isVisible()).to.be.true('visible'); + // Even if the window is already maximized + w.hide(); + await hidden; + expect(w.isVisible()).to.be.false('visible'); + w.maximize(); + await shown; // Ensure a 'show' event happens when it becomes visible + expect(w.isVisible()).to.be.true('visible'); + }); + }); + describe('BrowserWindow.unmaximize()', () => { afterEach(closeAllWindows); it('should restore the previous window position', () => { From b888d9cd17d41a7b7a2e2bf61429fc1f5d3c94e4 Mon Sep 17 00:00:00 2001 From: Sudowoodo Release Bot <88427002+sudowoodo-release-bot[bot]@users.noreply.github.com> Date: Thu, 10 Mar 2022 05:01:04 -0800 Subject: [PATCH 11/38] Bump v19.0.0-nightly.20220310 --- ELECTRON_VERSION | 2 +- package.json | 2 +- shell/browser/resources/win/electron.rc | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ELECTRON_VERSION b/ELECTRON_VERSION index 22d94b6c5b151..89c7c89ddc4e6 100644 --- a/ELECTRON_VERSION +++ b/ELECTRON_VERSION @@ -1 +1 @@ -19.0.0-nightly.20220309 \ No newline at end of file +19.0.0-nightly.20220310 \ No newline at end of file diff --git a/package.json b/package.json index 1e1905a55217f..c77e759c18349 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "electron", - "version": "19.0.0-nightly.20220309", + "version": "19.0.0-nightly.20220310", "repository": "https://github.com/electron/electron", "description": "Build cross platform desktop apps with JavaScript, HTML, and CSS", "devDependencies": { diff --git a/shell/browser/resources/win/electron.rc b/shell/browser/resources/win/electron.rc index 771f39264ebaf..383de0f2e49e2 100644 --- a/shell/browser/resources/win/electron.rc +++ b/shell/browser/resources/win/electron.rc @@ -50,8 +50,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 19,0,0,20220309 - PRODUCTVERSION 19,0,0,20220309 + FILEVERSION 19,0,0,20220310 + PRODUCTVERSION 19,0,0,20220310 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L From dc63b8e7f478ad87bcde0406508c1fbbcf4b872c Mon Sep 17 00:00:00 2001 From: Sudowoodo Release Bot <88427002+sudowoodo-release-bot[bot]@users.noreply.github.com> Date: Fri, 11 Mar 2022 05:01:42 -0800 Subject: [PATCH 12/38] Bump v19.0.0-nightly.20220311 --- ELECTRON_VERSION | 2 +- package.json | 2 +- shell/browser/resources/win/electron.rc | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ELECTRON_VERSION b/ELECTRON_VERSION index 89c7c89ddc4e6..ade03cdbecc4b 100644 --- a/ELECTRON_VERSION +++ b/ELECTRON_VERSION @@ -1 +1 @@ -19.0.0-nightly.20220310 \ No newline at end of file +19.0.0-nightly.20220311 \ No newline at end of file diff --git a/package.json b/package.json index c77e759c18349..728b3d3653861 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "electron", - "version": "19.0.0-nightly.20220310", + "version": "19.0.0-nightly.20220311", "repository": "https://github.com/electron/electron", "description": "Build cross platform desktop apps with JavaScript, HTML, and CSS", "devDependencies": { diff --git a/shell/browser/resources/win/electron.rc b/shell/browser/resources/win/electron.rc index 383de0f2e49e2..696f4f46d9069 100644 --- a/shell/browser/resources/win/electron.rc +++ b/shell/browser/resources/win/electron.rc @@ -50,8 +50,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 19,0,0,20220310 - PRODUCTVERSION 19,0,0,20220310 + FILEVERSION 19,0,0,20220311 + PRODUCTVERSION 19,0,0,20220311 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L From bbb79880f7016c156c8fad3c08b59caa0eedd8a7 Mon Sep 17 00:00:00 2001 From: Darshan Sen Date: Fri, 11 Mar 2022 22:49:51 +0530 Subject: [PATCH 13/38] chore: cherry-pick 2ed58f4 from chromium (#33109) Refs: https://chromium-review.googlesource.com/c/chromium/src/+/3492658 Fixes: https://github.com/electron/electron/issues/33049 Signed-off-by: Darshan Sen Co-authored-by: Charles Kerr --- patches/chromium/.patches | 1 + ...e_incorrect_width_height_adjustments.patch | 39 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 patches/chromium/remove_incorrect_width_height_adjustments.patch diff --git a/patches/chromium/.patches b/patches/chromium/.patches index 545165e4e06ad..c470189487c06 100644 --- a/patches/chromium/.patches +++ b/patches/chromium/.patches @@ -114,3 +114,4 @@ port_autofill_colors_to_the_color_pipeline.patch build_disable_partition_alloc_on_mac.patch build_disable_thin_lto_on_mac.patch fix_non-client_mouse_tracking_and_message_bubbling_on_windows.patch +remove_incorrect_width_height_adjustments.patch diff --git a/patches/chromium/remove_incorrect_width_height_adjustments.patch b/patches/chromium/remove_incorrect_width_height_adjustments.patch new file mode 100644 index 0000000000000..4fce52ba6e282 --- /dev/null +++ b/patches/chromium/remove_incorrect_width_height_adjustments.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Bruce Dawson +Date: Mon, 28 Feb 2022 19:07:41 +0000 +Subject: Remove incorrect width/height adjustments + +In late 2016 a change which fixed some problems around window sizing +when attaching or detaching additional displays was landed, which fixed +some genuine bugs. Unfortunately it included a subtraction of 1 from the +width and height of the Chrome window. I couldn't find any discussion of +this size adjustment and I think that it was just a misunderstanding of +how window rectangles work (inclusive versus exclusive extents). + +This size adjustment causes non-maximized Chrome windows to shrink every +time a monitor is added or removed. The problematic commit was found +by the bug-filer through a bisect of more than four years of Chrome +history - I'm just landing the fix that they suggested. + +Bug: 1300415 +Change-Id: Ief124f584a91aa9cc3f10704b0cc1e83356dea5b +Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3492658 +Reviewed-by: Allen Bauer +Commit-Queue: Bruce Dawson +Cr-Commit-Position: refs/heads/main@{#975872} + +diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc +index 264a9109e42c23e9be6bf7269b3cfee2634b61e4..86f06d2a2c9588a2210a9f78f47e73f1b7c5e329 100644 +--- a/ui/views/win/hwnd_message_handler.cc ++++ b/ui/views/win/hwnd_message_handler.cc +@@ -2834,8 +2834,8 @@ void HWNDMessageHandler::OnWindowPosChanging(WINDOWPOS* window_pos) { + // (Win+Shift+Arrows). See crbug.com/656001. + window_rect.left = window_pos->x; + window_rect.top = window_pos->y; +- window_rect.right = window_pos->x + window_pos->cx - 1; +- window_rect.bottom = window_pos->y + window_pos->cy - 1; ++ window_rect.right = window_pos->x + window_pos->cx; ++ window_rect.bottom = window_pos->y + window_pos->cy; + } + + HMONITOR monitor; From cdc27a3793958de4a2c06e7fce16244b6f0cb354 Mon Sep 17 00:00:00 2001 From: Jeremy Rose Date: Fri, 11 Mar 2022 11:35:48 -0800 Subject: [PATCH 14/38] fix: prevent UAF crash in setCertificateVerifyProc (#33204) --- ...xpose_setuseragent_on_networkcontext.patch | 4 +- ...emote_certificate_verification_logic.patch | 80 +++++++++++-------- 2 files changed, 48 insertions(+), 36 deletions(-) diff --git a/patches/chromium/expose_setuseragent_on_networkcontext.patch b/patches/chromium/expose_setuseragent_on_networkcontext.patch index 429dd72387ef7..b30988fba7e9c 100644 --- a/patches/chromium/expose_setuseragent_on_networkcontext.patch +++ b/patches/chromium/expose_setuseragent_on_networkcontext.patch @@ -33,10 +33,10 @@ index 14c71cc69388da46f62d9835e2a06fef0870da02..9481ea08401ae29ae9c1d960491b05b3 } // namespace net diff --git a/services/network/network_context.cc b/services/network/network_context.cc -index ca62a13420aa9c114c00054bbe1215f96285a4e9..01be46b1eaed2aadfd24eac9d102da99521b175c 100644 +index 20373c0e86852446569c401c4a993512cb388fc7..9b6dbdad1a17148303ddecaada17a57d4ea22bb2 100644 --- a/services/network/network_context.cc +++ b/services/network/network_context.cc -@@ -1331,6 +1331,13 @@ void NetworkContext::SetNetworkConditions( +@@ -1343,6 +1343,13 @@ void NetworkContext::SetNetworkConditions( std::move(network_conditions)); } diff --git a/patches/chromium/network_service_allow_remote_certificate_verification_logic.patch b/patches/chromium/network_service_allow_remote_certificate_verification_logic.patch index d4aaf27702eea..d524259dd9428 100644 --- a/patches/chromium/network_service_allow_remote_certificate_verification_logic.patch +++ b/patches/chromium/network_service_allow_remote_certificate_verification_logic.patch @@ -7,7 +7,7 @@ This adds a callback from the network service that's used to implement session.setCertificateVerifyCallback. diff --git a/services/network/network_context.cc b/services/network/network_context.cc -index 8ff62f92ed6efdbfc18db53db3c5bb59c1acfe34..ca62a13420aa9c114c00054bbe1215f96285a4e9 100644 +index 8ff62f92ed6efdbfc18db53db3c5bb59c1acfe34..20373c0e86852446569c401c4a993512cb388fc7 100644 --- a/services/network/network_context.cc +++ b/services/network/network_context.cc @@ -126,6 +126,11 @@ @@ -22,12 +22,38 @@ index 8ff62f92ed6efdbfc18db53db3c5bb59c1acfe34..ca62a13420aa9c114c00054bbe1215f9 #if BUILDFLAG(IS_CT_SUPPORTED) #include "components/certificate_transparency/chrome_ct_policy_enforcer.h" #include "components/certificate_transparency/chrome_require_ct_delegate.h" -@@ -433,6 +438,79 @@ bool GetFullDataFilePath( +@@ -433,6 +438,91 @@ bool GetFullDataFilePath( } // namespace +class RemoteCertVerifier : public net::CertVerifier { + public: ++ class Request : public net::CertVerifier::Request { ++ public: ++ Request() {} ++ ~Request() override = default; ++ void OnRemoteResponse( ++ const RequestParams& params, ++ net::CertVerifyResult* verify_result, ++ int error_from_upstream, ++ net::CompletionOnceCallback callback, ++ int error_from_client, ++ const net::CertVerifyResult& verify_result_from_client) { ++ if (error_from_client == net::ERR_ABORTED) { ++ // use the default ++ std::move(callback).Run(error_from_upstream); ++ } else { ++ // use the override ++ verify_result->Reset(); ++ verify_result->verified_cert = verify_result_from_client.verified_cert; ++ std::move(callback).Run(error_from_client); ++ } ++ } ++ base::WeakPtr GetWeakPtr() { return weak_factory_.GetWeakPtr(); } ++ private: ++ base::WeakPtrFactory weak_factory_{this}; ++ }; ++ + RemoteCertVerifier(std::unique_ptr upstream): upstream_(std::move(upstream)) { + } + ~RemoteCertVerifier() override = default; @@ -44,20 +70,14 @@ index 8ff62f92ed6efdbfc18db53db3c5bb59c1acfe34..ca62a13420aa9c114c00054bbe1215f9 + int Verify(const RequestParams& params, + net::CertVerifyResult* verify_result, + net::CompletionOnceCallback callback, -+ std::unique_ptr* out_req, ++ std::unique_ptr* out_req, + const net::NetLogWithSource& net_log) override { + out_req->reset(); + + net::CompletionOnceCallback callback2 = base::BindOnce( + &RemoteCertVerifier::OnRequestFinished, base::Unretained(this), -+ params, std::move(callback), verify_result); -+ int result = upstream_->Verify(params, verify_result, -+ std::move(callback2), out_req, net_log); -+ if (result != net::ERR_IO_PENDING) { -+ // Synchronous completion -+ } -+ -+ return result; ++ params, std::move(callback), verify_result, out_req); ++ return upstream_->Verify(params, verify_result, std::move(callback2), out_req, net_log); + } + + @@ -65,35 +85,27 @@ index 8ff62f92ed6efdbfc18db53db3c5bb59c1acfe34..ca62a13420aa9c114c00054bbe1215f9 + upstream_->SetConfig(config); + } + -+ void OnRequestFinished(const RequestParams& params, net::CompletionOnceCallback callback, net::CertVerifyResult* verify_result, int error) { ++ void OnRequestFinished(const RequestParams& params, ++ net::CompletionOnceCallback callback, ++ net::CertVerifyResult* verify_result, ++ std::unique_ptr* out_req, ++ int error) { + if (client_.is_bound()) { ++ // We take a weak pointer to the request because deletion of the request ++ // is what signals cancellation. Thus if the request is cancelled, the ++ // callback won't be called, thus avoiding UAF, because |verify_result| ++ // is freed when the request is cancelled. ++ *out_req = std::make_unique(); ++ base::WeakPtr weak_req = static_cast(out_req->get())->GetWeakPtr(); + client_->Verify(error, *verify_result, params.certificate(), + params.hostname(), params.flags(), params.ocsp_response(), -+ base::BindOnce(&RemoteCertVerifier::OnRemoteResponse, -+ base::Unretained(this), params, verify_result, error, -+ std::move(callback))); ++ base::BindOnce(&Request::OnRemoteResponse, ++ weak_req, params, verify_result, error, std::move(callback))); + } else { + std::move(callback).Run(error); + } + } + -+ void OnRemoteResponse( -+ const RequestParams& params, -+ net::CertVerifyResult* verify_result, -+ int error, -+ net::CompletionOnceCallback callback, -+ int error2, -+ const net::CertVerifyResult& verify_result2) { -+ if (error2 == net::ERR_ABORTED) { -+ // use the default -+ std::move(callback).Run(error); -+ } else { -+ // use the override -+ verify_result->Reset(); -+ verify_result->verified_cert = verify_result2.verified_cert; -+ std::move(callback).Run(error2); -+ } -+ } + private: + std::unique_ptr upstream_; + mojo::Remote client_; @@ -102,7 +114,7 @@ index 8ff62f92ed6efdbfc18db53db3c5bb59c1acfe34..ca62a13420aa9c114c00054bbe1215f9 constexpr uint32_t NetworkContext::kMaxOutstandingRequestsPerProcess; NetworkContext::PendingCertVerify::PendingCertVerify() = default; -@@ -671,6 +749,13 @@ void NetworkContext::SetClient( +@@ -671,6 +761,13 @@ void NetworkContext::SetClient( client_.Bind(std::move(client)); } @@ -116,7 +128,7 @@ index 8ff62f92ed6efdbfc18db53db3c5bb59c1acfe34..ca62a13420aa9c114c00054bbe1215f9 void NetworkContext::CreateURLLoaderFactory( mojo::PendingReceiver receiver, mojom::URLLoaderFactoryParamsPtr params) { -@@ -2226,6 +2311,9 @@ URLRequestContextOwner NetworkContext::MakeURLRequestContext( +@@ -2226,6 +2323,9 @@ URLRequestContextOwner NetworkContext::MakeURLRequestContext( std::move(cert_verifier)); cert_verifier = base::WrapUnique(cert_verifier_with_trust_anchors_); #endif // BUILDFLAG(IS_CHROMEOS) From f37295325668e50c80fbc00b406f0b4660cc93cd Mon Sep 17 00:00:00 2001 From: Jeremy Rose Date: Sat, 12 Mar 2022 15:28:10 -0800 Subject: [PATCH 15/38] fix: cppgc/node collisions in renderer process (#33252) * fix: cppgc/node collisions in renderer process * Update be_compatible_with_cppgc.patch --- patches/node/.patches | 1 + patches/node/be_compatible_with_cppgc.patch | 97 +++++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 patches/node/be_compatible_with_cppgc.patch diff --git a/patches/node/.patches b/patches/node/.patches index 0346bf4bde829..7a36ac8cbf7a6 100644 --- a/patches/node/.patches +++ b/patches/node/.patches @@ -32,3 +32,4 @@ darwin_remove_eprototype_error_workaround_3405.patch darwin_translate_eprototype_to_econnreset_3413.patch darwin_bump_minimum_supported_version_to_10_15_3406.patch fix_failing_node_js_test_on_outdated.patch +be_compatible_with_cppgc.patch diff --git a/patches/node/be_compatible_with_cppgc.patch b/patches/node/be_compatible_with_cppgc.patch new file mode 100644 index 0000000000000..3bbc3ce0bde16 --- /dev/null +++ b/patches/node/be_compatible_with_cppgc.patch @@ -0,0 +1,97 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jeremy Rose +Date: Fri, 11 Mar 2022 11:17:29 -0800 +Subject: be compatible with cppgc + +This fixes a crash that happens sporadically when Node is used in the same V8 +Isolate as Blink. For example: + +# +# Fatal error in ../../v8/src/objects/js-objects-inl.h, line 306 +# Debug check failed: static_cast(index) < static_cast(GetEmbedderFieldCount()) (1 vs. 1). +# +# +# +#FailureMessage Object: 0x7ffee46fd1c0 +0 Electron Framework 0x00000001181c78d9 base::debug::CollectStackTrace(void**, unsigned long) + 9 +1 Electron Framework 0x00000001180ea633 base::debug::StackTrace::StackTrace() + 19 +2 Electron Framework 0x000000011a04decd gin::(anonymous namespace)::PrintStackTrace() + 45 +3 Electron Framework 0x0000000119a9b416 V8_Fatal(char const*, int, char const*, ...) + 326 +4 Electron Framework 0x0000000119a9aeb5 v8::base::(anonymous namespace)::DefaultDcheckHandler(char const*, int, char const*) + 21 +5 Electron Framework 0x000000011530763f v8::internal::JSObject::GetEmbedderFieldOffset(int) + 207 +6 Electron Framework 0x00000001155f68e6 v8::internal::LocalEmbedderHeapTracer::EmbedderWriteBarrier(v8::internal::Heap*, v8::internal::JSObject) + 150 +7 Electron Framework 0x00000001152cd34f v8::Object::SetAlignedPointerInInternalField(int, void*) + 639 +8 Electron Framework 0x000000011d18df35 node::BaseObject::BaseObject(node::Environment*, v8::Local) + 101 +9 Electron Framework 0x000000011d347b6e node::crypto::DiffieHellman::DiffieHellman(node::Environment*, v8::Local) + 14 +10 Electron Framework 0x000000011d348413 node::crypto::DiffieHellman::New(v8::FunctionCallbackInfo const&) + 147 +[...] + +This crash happens because this V8 isolate has cppgc enabled. When cppgc is +enabled, V8 assumes that the first embedder field is a "type" pointer, the +first 16 bits of which are the embedder ID. Node did not adhere to this +requirement. Sometimes--mostly, even--this worked _by accident_. If the first +field in the BaseObject was a pointer to a bit of memory that happened to +contain the two-byte little-endian value 0x0001, however, V8 would take that to +mean that the object was a Blink object[1], and attempt to read the pointer in +the second embedder slot, which would result in a CHECK. + +This change adds an "embedder id" pointer as the first embedder field in all +Node-managed objects. This ensures that cppgc will always skip over Node +objects. + +This patch should be upstreamed to Node. + +[1]: https://source.chromium.org/chromium/chromium/src/+/main:gin/public/gin_embedders.h;l=20;drc=5a758a97032f0b656c3c36a3497560762495501a + +See also: https://source.chromium.org/chromium/chromium/src/+/main:v8/include/v8-cppgc.h;l=70-76;drc=5a758a97032f0b656c3c36a3497560762495501a + +diff --git a/src/base_object-inl.h b/src/base_object-inl.h +index bb1e8d4b46bce3bf08f730ac5d43f7113d17ae39..6da0669943fc6465ffc47a1c8c3dadfea6beb1c9 100644 +--- a/src/base_object-inl.h ++++ b/src/base_object-inl.h +@@ -32,10 +32,21 @@ + + namespace node { + ++namespace { ++// This just has to be different from the Chromium ones: ++// https://source.chromium.org/chromium/chromium/src/+/main:gin/public/gin_embedders.h;l=18-23;drc=5a758a97032f0b656c3c36a3497560762495501a ++// Otherwise, when Node is loaded in an isolate which uses cppgc, cppgc will ++// misinterpret the data stored in the embedder fields and try to garbage ++// collect them. ++static uint16_t kNodeEmbedderId = 0x90de; ++} ++ + BaseObject::BaseObject(Environment* env, v8::Local object) + : persistent_handle_(env->isolate(), object), env_(env) { + CHECK_EQ(false, object.IsEmpty()); +- CHECK_GT(object->InternalFieldCount(), 0); ++ CHECK_GT(object->InternalFieldCount(), BaseObject::kSlot); ++ object->SetAlignedPointerInInternalField(BaseObject::kWrapperType, ++ &kNodeEmbedderId); + object->SetAlignedPointerInInternalField( + BaseObject::kSlot, + static_cast(this)); +@@ -151,7 +162,8 @@ bool BaseObject::IsWeakOrDetached() const { + void BaseObject::LazilyInitializedJSTemplateConstructor( + const v8::FunctionCallbackInfo& args) { + DCHECK(args.IsConstructCall()); +- DCHECK_GT(args.This()->InternalFieldCount(), 0); ++ DCHECK_GT(args.This()->InternalFieldCount(), BaseObject::kSlot); ++ args.This()->SetAlignedPointerInInternalField(BaseObject::kWrapperType, &kNodeEmbedderId); + args.This()->SetAlignedPointerInInternalField(BaseObject::kSlot, nullptr); + } + +diff --git a/src/base_object.h b/src/base_object.h +index d46a0f216009c63f45c440fc352b54d1ac4a08d8..81913c0d7762bf499ee19aaa3b63b986ca370bb4 100644 +--- a/src/base_object.h ++++ b/src/base_object.h +@@ -40,7 +40,7 @@ class TransferData; + + class BaseObject : public MemoryRetainer { + public: +- enum InternalFields { kSlot, kInternalFieldCount }; ++ enum InternalFields { kWrapperType, kSlot, kInternalFieldCount }; + + // Associates this object with `object`. It uses the 0th internal field for + // that, and in particular aborts if there is no such field. From 039c061d07821b2d77781320a0bdf60d2e1b938a Mon Sep 17 00:00:00 2001 From: Milan Burda Date: Mon, 14 Mar 2022 10:19:15 +0100 Subject: [PATCH 16/38] fix: add missing [[maybe_unused]] to IsEnvSet (#33224) --- shell/app/electron_main_mac.cc | 2 +- shell/app/electron_main_win.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/shell/app/electron_main_mac.cc b/shell/app/electron_main_mac.cc index 6180a4d80bb22..c0f9576fff7fe 100644 --- a/shell/app/electron_main_mac.cc +++ b/shell/app/electron_main_mac.cc @@ -20,7 +20,7 @@ namespace { -bool IsEnvSet(const char* name) { +[[maybe_unused]] bool IsEnvSet(const char* name) { char* indicator = getenv(name); return indicator && indicator[0] != '\0'; } diff --git a/shell/app/electron_main_win.cc b/shell/app/electron_main_win.cc index 38f654e5f047f..2be51c27b2478 100644 --- a/shell/app/electron_main_win.cc +++ b/shell/app/electron_main_win.cc @@ -44,7 +44,7 @@ namespace { const char kUserDataDir[] = "user-data-dir"; const char kProcessType[] = "type"; -bool IsEnvSet(const char* name) { +[[maybe_unused]] bool IsEnvSet(const char* name) { size_t required_size; getenv_s(&required_size, nullptr, 0, name); return required_size != 0; From 4bdb50eeee95bd1853123e974b369c5fd1303843 Mon Sep 17 00:00:00 2001 From: Sudowoodo Release Bot <88427002+sudowoodo-release-bot[bot]@users.noreply.github.com> Date: Mon, 14 Mar 2022 06:02:37 -0700 Subject: [PATCH 17/38] Bump v19.0.0-nightly.20220314 --- ELECTRON_VERSION | 2 +- package.json | 2 +- shell/browser/resources/win/electron.rc | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ELECTRON_VERSION b/ELECTRON_VERSION index ade03cdbecc4b..bc4cd4e3cdf14 100644 --- a/ELECTRON_VERSION +++ b/ELECTRON_VERSION @@ -1 +1 @@ -19.0.0-nightly.20220311 \ No newline at end of file +19.0.0-nightly.20220314 \ No newline at end of file diff --git a/package.json b/package.json index 728b3d3653861..3e50d9ef1202f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "electron", - "version": "19.0.0-nightly.20220311", + "version": "19.0.0-nightly.20220314", "repository": "https://github.com/electron/electron", "description": "Build cross platform desktop apps with JavaScript, HTML, and CSS", "devDependencies": { diff --git a/shell/browser/resources/win/electron.rc b/shell/browser/resources/win/electron.rc index 696f4f46d9069..1bd4cadec9b11 100644 --- a/shell/browser/resources/win/electron.rc +++ b/shell/browser/resources/win/electron.rc @@ -50,8 +50,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 19,0,0,20220311 - PRODUCTVERSION 19,0,0,20220311 + FILEVERSION 19,0,0,20220314 + PRODUCTVERSION 19,0,0,20220314 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L From 75339dccb39381c4692b53d5e3a0655ff0f9ec43 Mon Sep 17 00:00:00 2001 From: Sudowoodo Release Bot <88427002+sudowoodo-release-bot[bot]@users.noreply.github.com> Date: Tue, 15 Mar 2022 06:01:15 -0700 Subject: [PATCH 18/38] Bump v19.0.0-nightly.20220315 --- ELECTRON_VERSION | 2 +- package.json | 2 +- shell/browser/resources/win/electron.rc | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ELECTRON_VERSION b/ELECTRON_VERSION index bc4cd4e3cdf14..16a9535edbe36 100644 --- a/ELECTRON_VERSION +++ b/ELECTRON_VERSION @@ -1 +1 @@ -19.0.0-nightly.20220314 \ No newline at end of file +19.0.0-nightly.20220315 \ No newline at end of file diff --git a/package.json b/package.json index 3e50d9ef1202f..5097dcc2d0927 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "electron", - "version": "19.0.0-nightly.20220314", + "version": "19.0.0-nightly.20220315", "repository": "https://github.com/electron/electron", "description": "Build cross platform desktop apps with JavaScript, HTML, and CSS", "devDependencies": { diff --git a/shell/browser/resources/win/electron.rc b/shell/browser/resources/win/electron.rc index 1bd4cadec9b11..d4ee0781fa344 100644 --- a/shell/browser/resources/win/electron.rc +++ b/shell/browser/resources/win/electron.rc @@ -50,8 +50,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 19,0,0,20220314 - PRODUCTVERSION 19,0,0,20220314 + FILEVERSION 19,0,0,20220315 + PRODUCTVERSION 19,0,0,20220315 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L From 73828910152cb67c849635ccf513dbe107b63ca3 Mon Sep 17 00:00:00 2001 From: Aryan Shridhar <53977614+aryanshridhar@users.noreply.github.com> Date: Tue, 15 Mar 2022 22:41:40 +0530 Subject: [PATCH 19/38] docs: reword sentence for better understanding (#33265) --- docs/tutorial/process-model.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/process-model.md b/docs/tutorial/process-model.md index 6b7737ec50b84..bfbb941486f55 100644 --- a/docs/tutorial/process-model.md +++ b/docs/tutorial/process-model.md @@ -40,7 +40,7 @@ to `require` modules and use all of Node.js APIs. ### Window management -The main process' primary purpose is to create and manage application windows with the +The primary purpose of the main process is to create and manage application windows with the [`BrowserWindow`][browser-window] module. Each instance of the `BrowserWindow` class creates an application window that loads From c8a3a00017d5eaca4e017a22d63acaebeb1e24d4 Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Tue, 15 Mar 2022 10:45:56 -0700 Subject: [PATCH 20/38] fix: race condition where webContents can be nullptr during re-focus and a multi-window close sequence (#33063) * fix: race condition where webContents can be nullptr during re-focus and a multi-window close sequence * chore: update electron_inspectable_web_contents_view.mm --- .../browser/ui/cocoa/electron_inspectable_web_contents_view.mm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/shell/browser/ui/cocoa/electron_inspectable_web_contents_view.mm b/shell/browser/ui/cocoa/electron_inspectable_web_contents_view.mm index e4b797a001a1e..3f86dca5158e5 100644 --- a/shell/browser/ui/cocoa/electron_inspectable_web_contents_view.mm +++ b/shell/browser/ui/cocoa/electron_inspectable_web_contents_view.mm @@ -266,6 +266,8 @@ - (void)viewDidBecomeFirstResponder:(NSNotification*)notification { inspectableWebContentsView_->inspectable_web_contents(); DCHECK(inspectable_web_contents); auto* webContents = inspectable_web_contents->GetWebContents(); + if (!webContents) + return; auto* webContentsView = webContents->GetNativeView().GetNativeNSView(); NSView* view = [notification object]; From 37a904c299c4d7bde4b2b5007a52043bca383868 Mon Sep 17 00:00:00 2001 From: CanadaHonk <19228318+CanadaHonk@users.noreply.github.com> Date: Tue, 15 Mar 2022 17:48:25 +0000 Subject: [PATCH 21/38] docs: specify default for BrowserWindow's center option (#33264) --- docs/api/browser-window.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index bc407ede48021..768d27284104e 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -146,7 +146,7 @@ It creates a new `BrowserWindow` with native properties as set by the `options`. * `useContentSize` boolean (optional) - The `width` and `height` would be used as web page's size, which means the actual window's size will include window frame's size and be slightly larger. Default is `false`. - * `center` boolean (optional) - Show window in the center of the screen. + * `center` boolean (optional) - Show window in the center of the screen. Default is `false`. * `minWidth` Integer (optional) - Window's minimum width. Default is `0`. * `minHeight` Integer (optional) - Window's minimum height. Default is `0`. * `maxWidth` Integer (optional) - Window's maximum width. Default is no limit. From 2657383ea7c21c3229cba7924d9b3ef5904453b7 Mon Sep 17 00:00:00 2001 From: Milan Burda Date: Tue, 15 Mar 2022 21:34:53 +0100 Subject: [PATCH 22/38] feat: allow setting code cache directory (#31154) * feat: allow setting code cache directory * chore: address review feedback * chore: update docs Co-authored-by: Charles Kerr * chore: rewrite with base::Contains Co-authored-by: Charles Kerr Co-authored-by: deepak1556 Co-authored-by: Charles Kerr --- docs/api/session.md | 14 ++++++++ shell/browser/api/electron_api_session.cc | 42 +++++++++++++++++++++++ shell/browser/api/electron_api_session.h | 2 ++ spec-main/api-session-spec.ts | 14 ++++++++ 4 files changed, 72 insertions(+) diff --git a/docs/api/session.md b/docs/api/session.md index 2517fd178d2e0..8bb1ad5ab3c5c 100644 --- a/docs/api/session.md +++ b/docs/api/session.md @@ -868,6 +868,20 @@ this session just before normal `preload` scripts run. Returns `string[]` an array of paths to preload scripts that have been registered. +#### `ses.setCodeCachePath(path)` + +* `path` String - Absolute path to store the v8 generated JS code cache from the renderer. + +Sets the directory to store the generated JS [code cache](https://v8.dev/blog/code-caching-for-devs) for this session. The directory is not required to be created by the user before this call, the runtime will create if it does not exist otherwise will use the existing directory. If directory cannot be created, then code cache will not be used and all operations related to code cache will fail silently inside the runtime. By default, the directory will be `Code Cache` under the +respective user data folder. + +#### `ses.clearCodeCaches(options)` + +* `options` Object + * `urls` String[] (optional) - An array of url corresponding to the resource whose generated code cache needs to be removed. If the list is empty then all entries in the cache directory will be removed. + +Returns `Promise` - resolves when the code cache clear operation is complete. + #### `ses.setSpellCheckerEnabled(enable)` * `enable` boolean diff --git a/shell/browser/api/electron_api_session.cc b/shell/browser/api/electron_api_session.cc index d0a0d4c408e92..ac6b38cdb58f4 100644 --- a/shell/browser/api/electron_api_session.cc +++ b/shell/browser/api/electron_api_session.cc @@ -28,6 +28,7 @@ #include "components/proxy_config/proxy_config_dictionary.h" #include "components/proxy_config/proxy_config_pref_names.h" #include "components/proxy_config/proxy_prefs.h" +#include "content/browser/code_cache/generated_code_cache_context.h" // nogncheck #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/download_item_utils.h" @@ -976,6 +977,45 @@ v8::Local Session::GetPath(v8::Isolate* isolate) { return gin::ConvertToV8(isolate, browser_context_->GetPath()); } +void Session::SetCodeCachePath(gin::Arguments* args) { + base::FilePath code_cache_path; + auto* storage_partition = browser_context_->GetDefaultStoragePartition(); + auto* code_cache_context = storage_partition->GetGeneratedCodeCacheContext(); + if (code_cache_context) { + if (!args->GetNext(&code_cache_path) || !code_cache_path.IsAbsolute()) { + args->ThrowTypeError( + "Absolute path must be provided to store code cache."); + return; + } + code_cache_context->Initialize( + code_cache_path, 0 /* allows disk_cache to choose the size */); + } +} + +v8::Local Session::ClearCodeCaches( + const gin_helper::Dictionary& options) { + auto* isolate = JavascriptEnvironment::GetIsolate(); + gin_helper::Promise promise(isolate); + v8::Local handle = promise.GetHandle(); + + std::set url_list; + base::RepeatingCallback url_matcher = base::NullCallback(); + if (options.Get("urls", &url_list) && !url_list.empty()) { + url_matcher = base::BindRepeating( + [](const std::set& url_list, const GURL& url) { + return base::Contains(url_list, url); + }, + url_list); + } + + browser_context_->GetDefaultStoragePartition()->ClearCodeCaches( + base::Time(), base::Time::Max(), url_matcher, + base::BindOnce(gin_helper::Promise::ResolvePromise, + std::move(promise))); + + return handle; +} + #if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER) base::Value Session::GetSpellCheckerLanguages() { return browser_context_->prefs() @@ -1203,6 +1243,8 @@ gin::ObjectTemplateBuilder Session::GetObjectTemplateBuilder( .SetMethod("preconnect", &Session::Preconnect) .SetMethod("closeAllConnections", &Session::CloseAllConnections) .SetMethod("getStoragePath", &Session::GetPath) + .SetMethod("setCodeCachePath", &Session::SetCodeCachePath) + .SetMethod("clearCodeCaches", &Session::ClearCodeCaches) .SetProperty("cookies", &Session::Cookies) .SetProperty("netLog", &Session::NetLog) .SetProperty("protocol", &Session::Protocol) diff --git a/shell/browser/api/electron_api_session.h b/shell/browser/api/electron_api_session.h index aedf234d38a58..e9b69380dfaf9 100644 --- a/shell/browser/api/electron_api_session.h +++ b/shell/browser/api/electron_api_session.h @@ -127,6 +127,8 @@ class Session : public gin::Wrappable, void Preconnect(const gin_helper::Dictionary& options, gin::Arguments* args); v8::Local CloseAllConnections(); v8::Local GetPath(v8::Isolate* isolate); + void SetCodeCachePath(gin::Arguments* args); + v8::Local ClearCodeCaches(const gin_helper::Dictionary& options); #if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER) base::Value GetSpellCheckerLanguages(); void SetSpellCheckerLanguages(gin_helper::ErrorThrower thrower, diff --git a/spec-main/api-session-spec.ts b/spec-main/api-session-spec.ts index 223d826d7eb84..f504d0db6d464 100644 --- a/spec-main/api-session-spec.ts +++ b/spec-main/api-session-spec.ts @@ -1121,6 +1121,20 @@ describe('session module', () => { }); }); + describe('session.setCodeCachePath()', () => { + it('throws when relative or empty path is provided', () => { + expect(() => { + session.defaultSession.setCodeCachePath('../fixtures'); + }).to.throw('Absolute path must be provided to store code cache.'); + expect(() => { + session.defaultSession.setCodeCachePath(''); + }).to.throw('Absolute path must be provided to store code cache.'); + expect(() => { + session.defaultSession.setCodeCachePath(path.join(app.getPath('userData'), 'test-code-cache')); + }).to.not.throw(); + }); + }); + describe('ses.setSSLConfig()', () => { it('can disable cipher suites', async () => { const ses = session.fromPartition('' + Math.random()); From fc7f38c7ce3e78f84d931d353de3329695887577 Mon Sep 17 00:00:00 2001 From: David Sanders Date: Wed, 16 Mar 2022 03:51:56 -0700 Subject: [PATCH 23/38] docs: remove "marked" from process.getBlinkMemoryInfo() (#33263) --- docs/api/process.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/api/process.md b/docs/api/process.md index 194619e01c0ab..4573899912997 100644 --- a/docs/api/process.md +++ b/docs/api/process.md @@ -178,7 +178,6 @@ Returns an object with V8 heap statistics. Note that all statistics are reported Returns `Object`: * `allocated` Integer - Size of all allocated objects in Kilobytes. -* `marked` Integer - Size of all marked objects in Kilobytes. * `total` Integer - Total allocated space in Kilobytes. Returns an object with Blink memory information. From a5382b7780e8966e144b026cda23ab9677ccc429 Mon Sep 17 00:00:00 2001 From: Sudowoodo Release Bot <88427002+sudowoodo-release-bot[bot]@users.noreply.github.com> Date: Wed, 16 Mar 2022 06:02:33 -0700 Subject: [PATCH 24/38] Bump v19.0.0-nightly.20220316 --- ELECTRON_VERSION | 2 +- package.json | 2 +- shell/browser/resources/win/electron.rc | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ELECTRON_VERSION b/ELECTRON_VERSION index 16a9535edbe36..a3fb7e2f9cea8 100644 --- a/ELECTRON_VERSION +++ b/ELECTRON_VERSION @@ -1 +1 @@ -19.0.0-nightly.20220315 \ No newline at end of file +19.0.0-nightly.20220316 \ No newline at end of file diff --git a/package.json b/package.json index 5097dcc2d0927..b2b2ab389a8c3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "electron", - "version": "19.0.0-nightly.20220315", + "version": "19.0.0-nightly.20220316", "repository": "https://github.com/electron/electron", "description": "Build cross platform desktop apps with JavaScript, HTML, and CSS", "devDependencies": { diff --git a/shell/browser/resources/win/electron.rc b/shell/browser/resources/win/electron.rc index d4ee0781fa344..d462bc89974f0 100644 --- a/shell/browser/resources/win/electron.rc +++ b/shell/browser/resources/win/electron.rc @@ -50,8 +50,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 19,0,0,20220315 - PRODUCTVERSION 19,0,0,20220315 + FILEVERSION 19,0,0,20220316 + PRODUCTVERSION 19,0,0,20220316 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L From 02fe2455216578815d6300ba2a44d462a840142d Mon Sep 17 00:00:00 2001 From: Jeremy Rose Date: Wed, 16 Mar 2022 07:56:20 -0700 Subject: [PATCH 25/38] docs: webFrame.insertCSS should mention options arg (#33274) --- docs/api/web-frame.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/api/web-frame.md b/docs/api/web-frame.md index 9384fe2c98613..b59d98c54cb60 100644 --- a/docs/api/web-frame.md +++ b/docs/api/web-frame.md @@ -110,9 +110,11 @@ webFrame.setSpellCheckProvider('en-US', { }) ``` -### `webFrame.insertCSS(css)` +#### `webFrame.insertCSS(css[, options])` -* `css` string - CSS source code. +* `css` string +* `options` Object (optional) + * `cssOrigin` string (optional) - Can be either 'user' or 'author'. Sets the [cascade origin](https://www.w3.org/TR/css3-cascade/#cascade-origin) of the inserted stylesheet. Default is 'author'. Returns `string` - A key for the inserted CSS that can later be used to remove the CSS via `webFrame.removeInsertedCSS(key)`. From b27401172033e7c8fac38d3b2d784fe8f9a481b2 Mon Sep 17 00:00:00 2001 From: Abhay Gupta <51379307+akgupta0777@users.noreply.github.com> Date: Wed, 16 Mar 2022 08:01:29 -0700 Subject: [PATCH 26/38] fix: fiddle ipc code pattern 3 (#33262) --- docs/fiddles/ipc/pattern-3/renderer.js | 2 +- docs/tutorial/ipc.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/fiddles/ipc/pattern-3/renderer.js b/docs/fiddles/ipc/pattern-3/renderer.js index 3b184add08ba2..04fd4bca890a3 100644 --- a/docs/fiddles/ipc/pattern-3/renderer.js +++ b/docs/fiddles/ipc/pattern-3/renderer.js @@ -4,5 +4,5 @@ window.electronAPI.handleCounter((event, value) => { const oldValue = Number(counter.innerText) const newValue = oldValue + value counter.innerText = newValue - event.reply('counter-value', newValue) + event.sender.send('counter-value', newValue) }) diff --git a/docs/tutorial/ipc.md b/docs/tutorial/ipc.md index 0189e0db7e806..5d3fc2ffec29b 100644 --- a/docs/tutorial/ipc.md +++ b/docs/tutorial/ipc.md @@ -379,7 +379,7 @@ module that uses the `webContents.send` API to send an IPC message from the main target renderer. ```javascript {11-26} title='main.js (Main Process)' -const {app, BrowserWindow, Menu} = require('electron') +const {app, BrowserWindow, Menu, ipcMain} = require('electron') const path = require('path') function createWindow () { @@ -519,7 +519,7 @@ window.electronAPI.onUpdateCounter((event, value) => { const oldValue = Number(counter.innerText) const newValue = oldValue + value counter.innerText = newValue - event.reply('counter-value', newValue) + event.sender.send('counter-value', newValue) }) ``` From cf3ee7be56dad64858a243581eac0644d4653488 Mon Sep 17 00:00:00 2001 From: David Sanders Date: Wed, 16 Mar 2022 10:40:47 -0700 Subject: [PATCH 27/38] build: drop pywin32 usage (#26186) * build: drop pywin32 usage * chore: ignore extra output on AppVeyor --- build/profile_toolchain.py | 87 ++++++++++++++++++++++++-------------- 1 file changed, 55 insertions(+), 32 deletions(-) diff --git a/build/profile_toolchain.py b/build/profile_toolchain.py index d8874dded572b..4251315e0a16a 100755 --- a/build/profile_toolchain.py +++ b/build/profile_toolchain.py @@ -1,9 +1,12 @@ -from __future__ import with_statement +from __future__ import unicode_literals + import contextlib import sys import os import optparse import json +import re +import subprocess sys.path.append("%s/../../build" % os.path.dirname(os.path.realpath(__file__))) @@ -33,36 +36,56 @@ def calculate_hash(root): return CalculateHash('.', None) def windows_installed_software(): - import win32com.client - strComputer = "." - objWMIService = win32com.client.Dispatch("WbemScripting.SWbemLocator") - objSWbemServices = objWMIService.ConnectServer(strComputer, "root\cimv2") - colItems = objSWbemServices.ExecQuery("Select * from Win32_Product") - items = [] - - for objItem in colItems: - item = {} - if objItem.Caption: - item['caption'] = objItem.Caption - if objItem.Caption: - item['description'] = objItem.Description - if objItem.InstallDate: - item['install_date'] = objItem.InstallDate - if objItem.InstallDate2: - item['install_date_2'] = objItem.InstallDate2 - if objItem.InstallLocation: - item['install_location'] = objItem.InstallLocation - if objItem.Name: - item['name'] = objItem.Name - if objItem.SKUNumber: - item['sku_number'] = objItem.SKUNumber - if objItem.Vendor: - item['vendor'] = objItem.Vendor - if objItem.Version: - item['version'] = objItem.Version - items.append(item) - - return items + powershell_command = [ + "Get-CimInstance", + "-Namespace", + "root\cimv2", + "-Class", + "Win32_product", + "|", + "Select", + "vendor,", + "description,", + "@{l='install_location';e='InstallLocation'},", + "@{l='install_date';e='InstallDate'},", + "@{l='install_date_2';e='InstallDate2'},", + "caption,", + "version,", + "name,", + "@{l='sku_number';e='SKUNumber'}", + "|", + "ConvertTo-Json", + ] + + proc = subprocess.Popen( + ["powershell.exe", "-Command", "-"], + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + ) + + stdout, _ = proc.communicate(" ".join(powershell_command).encode("utf-8")) + + if proc.returncode != 0: + raise RuntimeError("Failed to get list of installed software") + + # On AppVeyor there's other output related to PSReadline, + # so grab only the JSON output and ignore everything else + json_match = re.match( + r".*(\[.*{.*}.*\]).*", stdout.decode("utf-8"), re.DOTALL + ) + + if not json_match: + raise RuntimeError( + "Couldn't find JSON output for list of installed software" + ) + + # Filter out missing keys + return list( + map( + lambda info: {k: info[k] for k in info if info[k]}, + json.loads(json_match.group(1)), + ) + ) def windows_profile(): @@ -89,7 +112,7 @@ def windows_profile(): def main(options): if sys.platform == 'win32': - with open(options.output_json, 'wb') as f: + with open(options.output_json, 'w') as f: json.dump(windows_profile(), f) else: raise OSError("Unsupported OS") From 652680e8012983b1d8b9118b48297df4c1d9a939 Mon Sep 17 00:00:00 2001 From: David Sanders Date: Wed, 16 Mar 2022 10:54:30 -0700 Subject: [PATCH 28/38] fix: ensure external memory adjustments are balanced (#33266) --- shell/common/api/electron_api_native_image.cc | 17 +++++++++++------ shell/common/api/electron_api_native_image.h | 3 ++- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/shell/common/api/electron_api_native_image.cc b/shell/common/api/electron_api_native_image.cc index 3543a13585509..0dbda357a755c 100644 --- a/shell/common/api/electron_api_native_image.cc +++ b/shell/common/api/electron_api_native_image.cc @@ -109,7 +109,7 @@ base::win::ScopedHICON ReadICOFromPath(int size, const base::FilePath& path) { NativeImage::NativeImage(v8::Isolate* isolate, const gfx::Image& image) : image_(image), isolate_(isolate) { - AdjustAmountOfExternalAllocatedMemory(true); + UpdateExternalAllocatedMemoryUsage(); } #if BUILDFLAG(IS_WIN) @@ -120,22 +120,27 @@ NativeImage::NativeImage(v8::Isolate* isolate, const base::FilePath& hicon_path) electron::util::ReadImageSkiaFromICO(&image_skia, GetHICON(256)); image_ = gfx::Image(image_skia); - AdjustAmountOfExternalAllocatedMemory(true); + UpdateExternalAllocatedMemoryUsage(); } #endif NativeImage::~NativeImage() { - AdjustAmountOfExternalAllocatedMemory(false); + isolate_->AdjustAmountOfExternalAllocatedMemory(-memory_usage_); } -void NativeImage::AdjustAmountOfExternalAllocatedMemory(bool add) { +void NativeImage::UpdateExternalAllocatedMemoryUsage() { + int32_t new_memory_usage = 0; + if (image_.HasRepresentation(gfx::Image::kImageRepSkia)) { auto* const image_skia = image_.ToImageSkia(); if (!image_skia->isNull()) { - int64_t size = image_skia->bitmap()->computeByteSize(); - isolate_->AdjustAmountOfExternalAllocatedMemory(add ? size : -size); + new_memory_usage = image_skia->bitmap()->computeByteSize(); } } + + isolate_->AdjustAmountOfExternalAllocatedMemory(new_memory_usage - + memory_usage_); + memory_usage_ = new_memory_usage; } // static diff --git a/shell/common/api/electron_api_native_image.h b/shell/common/api/electron_api_native_image.h index a322631f9cfe2..7be02ad27b7af 100644 --- a/shell/common/api/electron_api_native_image.h +++ b/shell/common/api/electron_api_native_image.h @@ -121,7 +121,7 @@ class NativeImage : public gin::Wrappable { float GetAspectRatio(const absl::optional scale_factor); void AddRepresentation(const gin_helper::Dictionary& options); - void AdjustAmountOfExternalAllocatedMemory(bool add); + void UpdateExternalAllocatedMemoryUsage(); // Mark the image as template image. void SetTemplateImage(bool setAsTemplate); @@ -136,6 +136,7 @@ class NativeImage : public gin::Wrappable { gfx::Image image_; v8::Isolate* isolate_; + int32_t memory_usage_ = 0; }; } // namespace api From b2c5623a13c91a561704b46480b6c3a7a51f2db7 Mon Sep 17 00:00:00 2001 From: Robo Date: Thu, 17 Mar 2022 02:54:45 +0900 Subject: [PATCH 29/38] fix: crash when destroying node env with pending promises (#33280) * fix: crash when destroying node env with pending promises * chore: add spec --- shell/renderer/electron_renderer_client.cc | 19 ++++++++----- shell/renderer/web_worker_observer.cc | 9 ++++-- .../fs-promises-renderer-crash/index.html | 17 +++++++++++ .../fs-promises-renderer-crash/index.js | 28 +++++++++++++++++++ 4 files changed, 64 insertions(+), 9 deletions(-) create mode 100644 spec-main/fixtures/crash-cases/fs-promises-renderer-crash/index.html create mode 100644 spec-main/fixtures/crash-cases/fs-promises-renderer-crash/index.js diff --git a/shell/renderer/electron_renderer_client.cc b/shell/renderer/electron_renderer_client.cc index f24c8073935fe..2c80080172c1f 100644 --- a/shell/renderer/electron_renderer_client.cc +++ b/shell/renderer/electron_renderer_client.cc @@ -151,17 +151,22 @@ void ElectronRendererClient::WillReleaseScriptContext( if (env == node_bindings_->uv_env()) node_bindings_->set_uv_env(nullptr); - // Destroy the node environment. We only do this if node support has been - // enabled for sub-frames to avoid a change-of-behavior / introduce crashes - // for existing users. - // We also do this if we have disable electron site instance overrides to - // avoid memory leaks - auto prefs = render_frame->GetBlinkPreferences(); - gin_helper::MicrotasksScope microtasks_scope(env->isolate()); + // Destroying the node environment will also run the uv loop, + // Node.js expects `kExplicit` microtasks policy and will run microtasks + // checkpoints after every call into JavaScript. Since we use a different + // policy in the renderer - switch to `kExplicit` and then drop back to the + // previous policy value. + v8::Isolate* isolate = context->GetIsolate(); + auto old_policy = isolate->GetMicrotasksPolicy(); + DCHECK_EQ(v8::MicrotasksScope::GetCurrentDepth(isolate), 0); + isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kExplicit); + node::FreeEnvironment(env); if (env == node_bindings_->uv_env()) node::FreeIsolateData(node_bindings_->isolate_data()); + isolate->SetMicrotasksPolicy(old_policy); + // ElectronBindings is tracking node environments. electron_bindings_->EnvironmentDestroyed(env); } diff --git a/shell/renderer/web_worker_observer.cc b/shell/renderer/web_worker_observer.cc index 287be9ead13f0..ca929bf9e4bb9 100644 --- a/shell/renderer/web_worker_observer.cc +++ b/shell/renderer/web_worker_observer.cc @@ -37,8 +37,13 @@ WebWorkerObserver::WebWorkerObserver() WebWorkerObserver::~WebWorkerObserver() { lazy_tls.Pointer()->Set(nullptr); - gin_helper::MicrotasksScope microtasks_scope( - node_bindings_->uv_env()->isolate()); + // Destroying the node environment will also run the uv loop, + // Node.js expects `kExplicit` microtasks policy and will run microtasks + // checkpoints after every call into JavaScript. Since we use a different + // policy in the renderer - switch to `kExplicit` + v8::Isolate* isolate = node_bindings_->uv_env()->isolate(); + DCHECK_EQ(v8::MicrotasksScope::GetCurrentDepth(isolate), 0); + isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kExplicit); node::FreeEnvironment(node_bindings_->uv_env()); node::FreeIsolateData(node_bindings_->isolate_data()); } diff --git a/spec-main/fixtures/crash-cases/fs-promises-renderer-crash/index.html b/spec-main/fixtures/crash-cases/fs-promises-renderer-crash/index.html new file mode 100644 index 0000000000000..9721dac6ed821 --- /dev/null +++ b/spec-main/fixtures/crash-cases/fs-promises-renderer-crash/index.html @@ -0,0 +1,17 @@ + + + + + diff --git a/spec-main/fixtures/crash-cases/fs-promises-renderer-crash/index.js b/spec-main/fixtures/crash-cases/fs-promises-renderer-crash/index.js new file mode 100644 index 0000000000000..4c74ba39f74d6 --- /dev/null +++ b/spec-main/fixtures/crash-cases/fs-promises-renderer-crash/index.js @@ -0,0 +1,28 @@ +const { app, BrowserWindow, ipcMain } = require('electron'); +const path = require('path'); + +app.whenReady().then(() => { + let reloadCount = 0; + const win = new BrowserWindow({ + show: false, + webPreferences: { + nodeIntegration: true, + contextIsolation: false + } + }); + + win.loadFile('index.html'); + + win.webContents.on('render-process-gone', () => { + process.exit(1); + }); + + win.webContents.on('did-finish-load', () => { + if (reloadCount > 2) { + setImmediate(() => app.quit()); + } else { + reloadCount += 1; + win.webContents.send('reload', path.join(__dirname, '..', '..', 'cat.pdf')); + } + }); +}); From e9044860766affd5ded7baa3b44da6d4b9fe89e0 Mon Sep 17 00:00:00 2001 From: Jeremy Rose Date: Wed, 16 Mar 2022 16:23:14 -0700 Subject: [PATCH 30/38] fix: BrowserWindow.fromWebContents should work in browser-window-created (#33257) --- shell/common/gin_helper/trackable_object.h | 2 +- spec-main/api-browser-window-spec.ts | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/shell/common/gin_helper/trackable_object.h b/shell/common/gin_helper/trackable_object.h index 309e412e8a6f6..7f5b45c75fbcb 100644 --- a/shell/common/gin_helper/trackable_object.h +++ b/shell/common/gin_helper/trackable_object.h @@ -117,11 +117,11 @@ class TrackableObject : public TrackableObjectBase, public EventEmitter { ~TrackableObject() override { RemoveFromWeakMap(); } void InitWith(v8::Isolate* isolate, v8::Local wrapper) override { - gin_helper::WrappableBase::InitWith(isolate, wrapper); if (!weak_map_) { weak_map_ = new electron::KeyWeakMap; } weak_map_->Set(isolate, weak_map_id_, wrapper); + gin_helper::WrappableBase::InitWith(isolate, wrapper); } private: diff --git a/spec-main/api-browser-window-spec.ts b/spec-main/api-browser-window-spec.ts index 1ed8734711f33..89ff468ec5202 100644 --- a/spec-main/api-browser-window-spec.ts +++ b/spec-main/api-browser-window-spec.ts @@ -1816,6 +1816,18 @@ describe('BrowserWindow module', () => { expect(BrowserWindow.fromWebContents(webviewContents)!.id).to.equal(w.id); await p; }); + + it('is usable immediately on browser-window-created', async () => { + const w = new BrowserWindow({ show: false }); + w.loadURL('about:blank'); + w.webContents.executeJavaScript('window.open(""); null'); + const [win, winFromWebContents] = await new Promise((resolve) => { + app.once('browser-window-created', (e, win) => { + resolve([win, BrowserWindow.fromWebContents(win.webContents)]); + }); + }); + expect(winFromWebContents).to.equal(win); + }); }); describe('BrowserWindow.openDevTools()', () => { From 4342b7ff555a1707ab18f7a71da01ae27ef29cd1 Mon Sep 17 00:00:00 2001 From: Jeremy Rose Date: Wed, 16 Mar 2022 16:23:41 -0700 Subject: [PATCH 31/38] chore: remove awkward semi-documented preloadURL WebPreference (#33228) --- docs/api/web-contents.md | 3 --- docs/api/webview-tag.md | 3 --- docs/tutorial/security.md | 1 - lib/browser/guest-view-manager.ts | 3 ++- shell/browser/api/electron_api_net.cc | 13 +++++++++++++ shell/browser/web_contents_preferences.cc | 9 --------- shell/common/options_switches.cc | 3 --- shell/common/options_switches.h | 1 - spec/static/main.js | 1 - typings/internal-ambient.d.ts | 1 + typings/internal-electron.d.ts | 1 - 11 files changed, 16 insertions(+), 23 deletions(-) diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index 64af596682384..35ce46b590cc9 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -820,9 +820,6 @@ This event can be used to configure `webPreferences` for the `webContents` of a `` before it's loaded, and provides the ability to set settings that can't be set via `` attributes. -**Note:** The specified `preload` script option will appear as `preloadURL` -(not `preload`) in the `webPreferences` object emitted with this event. - #### Event: 'did-attach-webview' Returns: diff --git a/docs/api/webview-tag.md b/docs/api/webview-tag.md index fd90e8b5d5660..c2eab361cfd94 100644 --- a/docs/api/webview-tag.md +++ b/docs/api/webview-tag.md @@ -158,9 +158,6 @@ When the guest page doesn't have node integration this script will still have access to all Node APIs, but global objects injected by Node will be deleted after this script has finished executing. -**Note:** This option will appear as `preloadURL` (not `preload`) in -the `webPreferences` specified to the `will-attach-webview` event. - ### `httpreferrer` ```html diff --git a/docs/tutorial/security.md b/docs/tutorial/security.md index 688dda5a68961..d267a61a47d00 100644 --- a/docs/tutorial/security.md +++ b/docs/tutorial/security.md @@ -562,7 +562,6 @@ app.on('web-contents-created', (event, contents) => { contents.on('will-attach-webview', (event, webPreferences, params) => { // Strip away preload scripts if unused or verify their location is legitimate delete webPreferences.preload - delete webPreferences.preloadURL // Disable Node.js integration webPreferences.nodeIntegration = false diff --git a/lib/browser/guest-view-manager.ts b/lib/browser/guest-view-manager.ts index c973586e807d5..c9c4585de28e4 100644 --- a/lib/browser/guest-view-manager.ts +++ b/lib/browser/guest-view-manager.ts @@ -15,6 +15,7 @@ interface GuestInstance { const webViewManager = process._linkedBinding('electron_browser_web_view_manager'); const eventBinding = process._linkedBinding('electron_browser_event'); +const netBinding = process._linkedBinding('electron_browser_net'); const supportedWebViewEvents = Object.keys(webViewEvents); @@ -49,7 +50,7 @@ function makeWebPreferences (embedder: Electron.WebContents, params: Record #include "gin/handle.h" +#include "net/base/filename_util.h" #include "net/base/network_change_notifier.h" #include "net/http/http_util.h" #include "services/network/public/cpp/features.h" #include "shell/browser/api/electron_api_url_loader.h" +#include "shell/common/gin_converters/file_path_converter.h" +#include "shell/common/gin_converters/gurl_converter.h" #include "shell/common/gin_helper/dictionary.h" +#include "shell/common/gin_helper/error_thrower.h" #include "shell/common/gin_helper/object_template_builder.h" #include "shell/common/node_includes.h" @@ -28,6 +32,14 @@ bool IsValidHeaderValue(std::string header_value) { return net::HttpUtil::IsValidHeaderValue(header_value); } +base::FilePath FileURLToFilePath(v8::Isolate* isolate, const GURL& url) { + base::FilePath path; + if (!net::FileURLToFilePath(url, &path)) + gin_helper::ErrorThrower(isolate).ThrowError( + "Failed to convert URL to file path"); + return path; +} + using electron::api::SimpleURLLoaderWrapper; void Initialize(v8::Local exports, @@ -41,6 +53,7 @@ void Initialize(v8::Local exports, dict.SetMethod("isValidHeaderName", &IsValidHeaderName); dict.SetMethod("isValidHeaderValue", &IsValidHeaderValue); dict.SetMethod("createURLLoader", &SimpleURLLoaderWrapper::Create); + dict.SetMethod("fileURLToFilePath", &FileURLToFilePath); } } // namespace diff --git a/shell/browser/web_contents_preferences.cc b/shell/browser/web_contents_preferences.cc index e54772a0bfce2..c7bdcbf362241 100644 --- a/shell/browser/web_contents_preferences.cc +++ b/shell/browser/web_contents_preferences.cc @@ -258,15 +258,6 @@ void WebContentsPreferences::Merge( } else { LOG(ERROR) << "preload script must have absolute path."; } - } else if (web_preferences.Get(options::kPreloadURL, &preload_url_str)) { - // Translate to file path if there is "preload-url" option. - base::FilePath preload; - GURL preload_url(preload_url_str); - if (net::FileURLToFilePath(preload_url, &preload)) { - preload_path_ = preload; - } else { - LOG(ERROR) << "preload url must be file:// protocol."; - } } std::string type; diff --git a/shell/common/options_switches.cc b/shell/common/options_switches.cc index 5ae559c437eb9..94ffb637ff124 100644 --- a/shell/common/options_switches.cc +++ b/shell/common/options_switches.cc @@ -120,9 +120,6 @@ const char kPreloadScript[] = "preload"; const char kPreloadScripts[] = "preloadScripts"; -// Like --preload, but the passed argument is an URL. -const char kPreloadURL[] = "preloadURL"; - // Enable the node integration. const char kNodeIntegration[] = "nodeIntegration"; diff --git a/shell/common/options_switches.h b/shell/common/options_switches.h index cfe8a4a191ccc..d8f4819067911 100644 --- a/shell/common/options_switches.h +++ b/shell/common/options_switches.h @@ -66,7 +66,6 @@ extern const char kOverlayHeight[]; extern const char kZoomFactor[]; extern const char kPreloadScript[]; extern const char kPreloadScripts[]; -extern const char kPreloadURL[]; extern const char kNodeIntegration[]; extern const char kContextIsolation[]; extern const char kExperimentalFeatures[]; diff --git a/spec/static/main.js b/spec/static/main.js index 28ec06f524cc7..675c90fb42a9f 100644 --- a/spec/static/main.js +++ b/spec/static/main.js @@ -155,7 +155,6 @@ ipcMain.on('disable-preload-on-next-will-attach-webview', (event, id) => { event.sender.once('will-attach-webview', (event, webPreferences, params) => { params.src = `file://${path.join(__dirname, '..', 'fixtures', 'pages', 'webview-stripped-preload.html')}`; delete webPreferences.preload; - delete webPreferences.preloadURL; }); }); diff --git a/typings/internal-ambient.d.ts b/typings/internal-ambient.d.ts index 92d707c8edacc..c3b73935a2999 100644 --- a/typings/internal-ambient.d.ts +++ b/typings/internal-ambient.d.ts @@ -222,6 +222,7 @@ declare namespace NodeJS { isOnline(): boolean; isValidHeaderName: (headerName: string) => boolean; isValidHeaderValue: (headerValue: string) => boolean; + fileURLToFilePath: (url: string) => string; Net: any; net: any; createURLLoader(options: CreateURLLoaderOptions): URLLoader; diff --git a/typings/internal-electron.d.ts b/typings/internal-electron.d.ts index a0d645440652f..49568925fa80b 100644 --- a/typings/internal-electron.d.ts +++ b/typings/internal-electron.d.ts @@ -97,7 +97,6 @@ declare namespace Electron { interface WebPreferences { disablePopups?: boolean; - preloadURL?: string; embedder?: Electron.WebContents; type?: 'backgroundPage' | 'window' | 'browserView' | 'remote' | 'webview' | 'offscreen'; } From df8fd1b269ace37e7ad62ffa9ac8895bca463ef6 Mon Sep 17 00:00:00 2001 From: David Sanders Date: Thu, 17 Mar 2022 00:13:48 -0700 Subject: [PATCH 32/38] build: fix build by removing usage of removed preloadUrl (#33319) --- lib/browser/api/web-contents.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/browser/api/web-contents.ts b/lib/browser/api/web-contents.ts index cafe85cae4364..a8abf03fa6360 100644 --- a/lib/browser/api/web-contents.ts +++ b/lib/browser/api/web-contents.ts @@ -571,7 +571,7 @@ const loggingEnabled = () => { // Add JavaScript wrappers for WebContents class. WebContents.prototype._init = function () { const prefs = this.getLastWebPreferences() || {}; - if (!prefs.nodeIntegration && (prefs.preload != null || prefs.preloadURL != null) && prefs.sandbox == null) { + if (!prefs.nodeIntegration && prefs.preload != null && prefs.sandbox == null) { deprecate.log('The default sandbox option for windows without nodeIntegration is changing. Presently, by default, when a window has a preload script, it defaults to being unsandboxed. In Electron 20, this default will be changing, and all windows that have nodeIntegration: false (which is the default) will be sandboxed by default. If your preload script doesn\'t use Node, no action is needed. If your preload script does use Node, either refactor it to move Node usage to the main process, or specify sandbox: false in your WebPreferences.'); } // Read off the ID at construction time, so that it's accessible even after From ce8e248b60b2ae6547eb037a8b22e93a5edeb699 Mon Sep 17 00:00:00 2001 From: David Sanders Date: Thu, 17 Mar 2022 01:40:00 -0700 Subject: [PATCH 33/38] docs: remove unused images (#33310) --- docs/images/message-notification-renderer.png | Bin 10471 -> 0 bytes docs/images/online-event-detection.png | Bin 45114 -> 0 bytes docs/images/tutorial-release-schedule.svg | 97 ------------------ 3 files changed, 97 deletions(-) delete mode 100644 docs/images/message-notification-renderer.png delete mode 100644 docs/images/online-event-detection.png delete mode 100644 docs/images/tutorial-release-schedule.svg diff --git a/docs/images/message-notification-renderer.png b/docs/images/message-notification-renderer.png deleted file mode 100644 index 87c8a876a2b4f77c238abfeaa7aa6fc9f6cb9fac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10471 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 z - - - - - - - master - - - - - 2.0 - - v2.0.0-beta0 - - v2.0.0 - - - - - 2.1 - - v2.1.0-beta0 - - v2.1.0-beta1 - - v2.1.0 - - - - - 3.0 - - v3.0.0-beta0 - - v3.0.0 - - - - - bug fix - - - - - bug fix - - - - - bug fix - - - - - bug fix - - - - - bug fix - - - - - - feature - - - - feature - - - - feature - - - - - chromiumupdate - - - - ~1 week - - - - ~1 week - - - - ~1 week - - - - \ No newline at end of file From 7acb513ba675aee12bdf52cf5ca8c3d162a93ef4 Mon Sep 17 00:00:00 2001 From: David Sanders Date: Thu, 17 Mar 2022 05:45:55 -0700 Subject: [PATCH 34/38] docs: update links to Chromium source (#33309) --- docs/api/app.md | 4 ++-- docs/api/client-request.md | 2 +- docs/api/command-line-switches.md | 4 ++-- docs/api/content-tracing.md | 2 +- docs/api/session.md | 2 +- docs/api/structures/protocol-response.md | 2 +- docs/api/structures/trace-config.md | 8 ++++---- docs/api/web-contents.md | 2 +- docs/development/build-instructions-gn.md | 6 +++--- docs/development/build-instructions-windows.md | 2 +- docs/glossary.md | 2 +- docs/tutorial/sandbox.md | 2 +- 12 files changed, 19 insertions(+), 19 deletions(-) diff --git a/docs/api/app.md b/docs/api/app.md index 60eb2ee7785c2..b8c4780b22853 100755 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -714,7 +714,7 @@ Overrides the current application's name. ### `app.getLocale()` Returns `string` - The current application locale, fetched using Chromium's `l10n_util` library. -Possible return values are documented [here](https://source.chromium.org/chromium/chromium/src/+/master:ui/base/l10n/l10n_util.cc). +Possible return values are documented [here](https://source.chromium.org/chromium/chromium/src/+/main:ui/base/l10n/l10n_util.cc). To set the locale, you'll want to use a command line switch at app startup, which may be found [here](command-line-switches.md). @@ -1093,7 +1093,7 @@ Activation policy types: Imports the certificate in pkcs12 format into the platform certificate store. `callback` is called with the `result` of import operation, a value of `0` -indicates success while any other value indicates failure according to Chromium [net_error_list](https://source.chromium.org/chromium/chromium/src/+/master:net/base/net_error_list.h). +indicates success while any other value indicates failure according to Chromium [net_error_list](https://source.chromium.org/chromium/chromium/src/+/main:net/base/net_error_list.h). ### `app.configureHostResolver(options)` diff --git a/docs/api/client-request.md b/docs/api/client-request.md index 12f1ce1157e5b..81410a281816f 100644 --- a/docs/api/client-request.md +++ b/docs/api/client-request.md @@ -185,7 +185,7 @@ the first write will throw an error. If the passed value is not a `string`, its Certain headers are restricted from being set by apps. These headers are listed below. More information on restricted headers can be found in -[Chromium's header utils](https://source.chromium.org/chromium/chromium/src/+/master:services/network/public/cpp/header_util.cc;drc=1562cab3f1eda927938f8f4a5a91991fefde66d3;bpv=1;bpt=1;l=22). +[Chromium's header utils](https://source.chromium.org/chromium/chromium/src/+/main:services/network/public/cpp/header_util.cc;drc=1562cab3f1eda927938f8f4a5a91991fefde66d3;bpv=1;bpt=1;l=22). * `Content-Length` * `Host` diff --git a/docs/api/command-line-switches.md b/docs/api/command-line-switches.md index f395379c063fa..d628b0549c1dd 100644 --- a/docs/api/command-line-switches.md +++ b/docs/api/command-line-switches.md @@ -274,8 +274,8 @@ By default inspector websocket url is available in stderr and under /json/list e [ready]: app.md#event-ready [play-silent-audio]: https://github.com/atom/atom/pull/9485/files [debugging-main-process]: ../tutorial/debugging-main-process.md -[logging]: https://source.chromium.org/chromium/chromium/src/+/master:base/logging.h +[logging]: https://source.chromium.org/chromium/chromium/src/+/main:base/logging.h [node-cli]: https://nodejs.org/api/cli.html [play-silent-audio]: https://github.com/atom/atom/pull/9485/files [ready]: app.md#event-ready -[severities]: https://source.chromium.org/chromium/chromium/src/+/master:base/logging.h?q=logging::LogSeverity&ss=chromium +[severities]: https://source.chromium.org/chromium/chromium/src/+/main:base/logging.h?q=logging::LogSeverity&ss=chromium diff --git a/docs/api/content-tracing.md b/docs/api/content-tracing.md index 91e3ca43a2560..ec8e3f7979701 100644 --- a/docs/api/content-tracing.md +++ b/docs/api/content-tracing.md @@ -36,7 +36,7 @@ Returns `Promise` - resolves with an array of category groups once all Get a set of category groups. The category groups can change as new code paths are reached. See also the [list of built-in tracing -categories](https://chromium.googlesource.com/chromium/src/+/master/base/trace_event/builtin_categories.h). +categories](https://chromium.googlesource.com/chromium/src/+/main/base/trace_event/builtin_categories.h). > **NOTE:** Electron adds a non-default tracing category called `"electron"`. > This category can be used to capture Electron-specific tracing events. diff --git a/docs/api/session.md b/docs/api/session.md index 8bb1ad5ab3c5c..5dc29aba9b6d7 100644 --- a/docs/api/session.md +++ b/docs/api/session.md @@ -567,7 +567,7 @@ the original network configuration. * `errorCode` Integer - Error code. * `callback` Function * `verificationResult` Integer - Value can be one of certificate error codes - from [here](https://source.chromium.org/chromium/chromium/src/+/master:net/base/net_error_list.h). + from [here](https://source.chromium.org/chromium/chromium/src/+/main:net/base/net_error_list.h). Apart from the certificate error codes, the following special codes can be used. * `0` - Indicates success and disables Certificate Transparency verification. * `-2` - Indicates failure. diff --git a/docs/api/structures/protocol-response.md b/docs/api/structures/protocol-response.md index a20873ebb3b46..21a863240fabb 100644 --- a/docs/api/structures/protocol-response.md +++ b/docs/api/structures/protocol-response.md @@ -31,4 +31,4 @@ * `uploadData` [ProtocolResponseUploadData](protocol-response-upload-data.md) (optional) - The data used as upload data. This is only used for URL responses when `method` is `"POST"`. -[net-error]: https://source.chromium.org/chromium/chromium/src/+/master:net/base/net_error_list.h +[net-error]: https://source.chromium.org/chromium/chromium/src/+/main:net/base/net_error_list.h diff --git a/docs/api/structures/trace-config.md b/docs/api/structures/trace-config.md index d5b3795f228fd..4160b7121ca57 100644 --- a/docs/api/structures/trace-config.md +++ b/docs/api/structures/trace-config.md @@ -8,7 +8,7 @@ * `enable_argument_filter` boolean (optional) - if true, filter event data according to a specific list of events that have been manually vetted to not include any PII. See [the implementation in - Chromium][trace_event_args_whitelist.cc] for specifics. + Chromium][trace_event_args_allowlist.cc] for specifics. * `included_categories` string[] (optional) - a list of tracing categories to include. Can include glob-like patterns using `*` at the end of the category name. See [tracing categories][] for the list of categories. @@ -45,7 +45,7 @@ An example TraceConfig that roughly matches what Chrome DevTools records: } ``` -[tracing categories]: https://chromium.googlesource.com/chromium/src/+/master/base/trace_event/builtin_categories.h -[memory-infra docs]: https://chromium.googlesource.com/chromium/src/+/master/docs/memory-infra/memory_infra_startup_tracing.md#the-advanced-way -[trace_event_args_whitelist.cc]: https://chromium.googlesource.com/chromium/src/+/master/services/tracing/public/cpp/trace_event_args_whitelist.cc +[tracing categories]: https://chromium.googlesource.com/chromium/src/+/main/base/trace_event/builtin_categories.h +[memory-infra docs]: https://chromium.googlesource.com/chromium/src/+/main/docs/memory-infra/memory_infra_startup_tracing.md#the-advanced-way +[trace_event_args_allowlist.cc]: https://chromium.googlesource.com/chromium/src/+/main/services/tracing/public/cpp/trace_event_args_allowlist.cc [histogram]: https://chromium.googlesource.com/chromium/src.git/+/HEAD/tools/metrics/histograms/README.md diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index 35ce46b590cc9..bdfa225332567 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -92,7 +92,7 @@ Returns: * `frameRoutingId` Integer This event is like `did-finish-load` but emitted when the load failed. -The full list of error codes and their meaning is available [here](https://source.chromium.org/chromium/chromium/src/+/master:net/base/net_error_list.h). +The full list of error codes and their meaning is available [here](https://source.chromium.org/chromium/chromium/src/+/main:net/base/net_error_list.h). #### Event: 'did-fail-provisional-load' diff --git a/docs/development/build-instructions-gn.md b/docs/development/build-instructions-gn.md index 70b5c48ed857c..cd955743df3b9 100644 --- a/docs/development/build-instructions-gn.md +++ b/docs/development/build-instructions-gn.md @@ -196,12 +196,12 @@ If you test other combinations and find them to work, please update this documen See the GN reference for allowable values of [`target_os`][target_os values] and [`target_cpu`][target_cpu values]. -[target_os values]: https://gn.googlesource.com/gn/+/master/docs/reference.md#built_in-predefined-variables-target_os_the-desired-operating-system-for-the-build-possible-values -[target_cpu values]: https://gn.googlesource.com/gn/+/master/docs/reference.md#built_in-predefined-variables-target_cpu_the-desired-cpu-architecture-for-the-build-possible-values +[target_os values]: https://gn.googlesource.com/gn/+/main/docs/reference.md#built_in-predefined-variables-target_os_the-desired-operating-system-for-the-build-possible-values +[target_cpu values]: https://gn.googlesource.com/gn/+/main/docs/reference.md#built_in-predefined-variables-target_cpu_the-desired-cpu-architecture-for-the-build-possible-values #### Windows on Arm (experimental) -To cross-compile for Windows on Arm, [follow Chromium's guide](https://chromium.googlesource.com/chromium/src/+/refs/heads/master/docs/windows_build_instructions.md#Visual-Studio) to get the necessary dependencies, SDK and libraries, then build with `ELECTRON_BUILDING_WOA=1` in your environment before running `gclient sync`. +To cross-compile for Windows on Arm, [follow Chromium's guide](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/windows_build_instructions.md#Visual-Studio) to get the necessary dependencies, SDK and libraries, then build with `ELECTRON_BUILDING_WOA=1` in your environment before running `gclient sync`. ```bat set ELECTRON_BUILDING_WOA=1 diff --git a/docs/development/build-instructions-windows.md b/docs/development/build-instructions-windows.md index 49e436197d851..b827a713784b2 100644 --- a/docs/development/build-instructions-windows.md +++ b/docs/development/build-instructions-windows.md @@ -9,7 +9,7 @@ Follow the guidelines below for building **Electron itself** on Windows, for the * Windows 10 / Server 2012 R2 or higher * Visual Studio 2017 15.7.2 or higher - [download VS 2019 Community Edition for free](https://www.visualstudio.com/vs/) - * See [the Chromium build documentation](https://chromium.googlesource.com/chromium/src/+/master/docs/windows_build_instructions.md#visual-studio) for more details on which Visual Studio + * See [the Chromium build documentation](https://chromium.googlesource.com/chromium/src/+/main/docs/windows_build_instructions.md#visual-studio) for more details on which Visual Studio components are required. * If your Visual Studio is installed in a directory other than the default, you'll need to set a few environment variables to point the toolchains to your installation path. diff --git a/docs/glossary.md b/docs/glossary.md index a4bfa2a96071f..893c598c52b80 100644 --- a/docs/glossary.md +++ b/docs/glossary.md @@ -91,7 +91,7 @@ An IPC system for communicating intra- or inter-process, and that's important because Chrome is keen on being able to split its work into separate processes or not, depending on memory pressures etc. -See https://chromium.googlesource.com/chromium/src/+/master/mojo/README.md +See https://chromium.googlesource.com/chromium/src/+/main/mojo/README.md See also: [IPC](#ipc) diff --git a/docs/tutorial/sandbox.md b/docs/tutorial/sandbox.md index 0eb955c5da75f..db71727efb6cc 100644 --- a/docs/tutorial/sandbox.md +++ b/docs/tutorial/sandbox.md @@ -157,7 +157,7 @@ versions of Electron, we do not make a guarantee that every fix will be backported. Your best chance at staying secure is to be on the latest stable version of Electron. -[sandbox]: https://chromium.googlesource.com/chromium/src/+/master/docs/design/sandbox.md +[sandbox]: https://chromium.googlesource.com/chromium/src/+/main/docs/design/sandbox.md [issue-28466]: https://github.com/electron/electron/issues/28466 [browser-window]: ../api/browser-window.md [enable-sandbox]: ../api/app.md#appenablesandbox From ac6ed62ab96a0a0717ce3259f9c02da4dff7285f Mon Sep 17 00:00:00 2001 From: Sudowoodo Release Bot <88427002+sudowoodo-release-bot[bot]@users.noreply.github.com> Date: Thu, 17 Mar 2022 06:01:17 -0700 Subject: [PATCH 35/38] Bump v19.0.0-nightly.20220317 --- ELECTRON_VERSION | 2 +- package.json | 2 +- shell/browser/resources/win/electron.rc | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ELECTRON_VERSION b/ELECTRON_VERSION index a3fb7e2f9cea8..cd9d8360c400f 100644 --- a/ELECTRON_VERSION +++ b/ELECTRON_VERSION @@ -1 +1 @@ -19.0.0-nightly.20220316 \ No newline at end of file +19.0.0-nightly.20220317 \ No newline at end of file diff --git a/package.json b/package.json index b2b2ab389a8c3..678190af931e5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "electron", - "version": "19.0.0-nightly.20220316", + "version": "19.0.0-nightly.20220317", "repository": "https://github.com/electron/electron", "description": "Build cross platform desktop apps with JavaScript, HTML, and CSS", "devDependencies": { diff --git a/shell/browser/resources/win/electron.rc b/shell/browser/resources/win/electron.rc index d462bc89974f0..f0020411c7dd5 100644 --- a/shell/browser/resources/win/electron.rc +++ b/shell/browser/resources/win/electron.rc @@ -50,8 +50,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 19,0,0,20220316 - PRODUCTVERSION 19,0,0,20220316 + FILEVERSION 19,0,0,20220317 + PRODUCTVERSION 19,0,0,20220317 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L From f2b06324b8836a4a3acc93c86f77a624c04b855b Mon Sep 17 00:00:00 2001 From: Sudowoodo Release Bot <88427002+sudowoodo-release-bot[bot]@users.noreply.github.com> Date: Fri, 18 Mar 2022 06:01:12 -0700 Subject: [PATCH 36/38] Bump v19.0.0-nightly.20220318 --- ELECTRON_VERSION | 2 +- package.json | 2 +- shell/browser/resources/win/electron.rc | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ELECTRON_VERSION b/ELECTRON_VERSION index cd9d8360c400f..e1b801e28d07d 100644 --- a/ELECTRON_VERSION +++ b/ELECTRON_VERSION @@ -1 +1 @@ -19.0.0-nightly.20220317 \ No newline at end of file +19.0.0-nightly.20220318 \ No newline at end of file diff --git a/package.json b/package.json index 678190af931e5..90e4b2ae0145c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "electron", - "version": "19.0.0-nightly.20220317", + "version": "19.0.0-nightly.20220318", "repository": "https://github.com/electron/electron", "description": "Build cross platform desktop apps with JavaScript, HTML, and CSS", "devDependencies": { diff --git a/shell/browser/resources/win/electron.rc b/shell/browser/resources/win/electron.rc index f0020411c7dd5..14ba8ce3ae702 100644 --- a/shell/browser/resources/win/electron.rc +++ b/shell/browser/resources/win/electron.rc @@ -50,8 +50,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 19,0,0,20220317 - PRODUCTVERSION 19,0,0,20220317 + FILEVERSION 19,0,0,20220318 + PRODUCTVERSION 19,0,0,20220318 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L From e07c2b84d76e649478e44a81a445c4076c4e603f Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Fri, 18 Mar 2022 19:50:05 -0700 Subject: [PATCH 37/38] fix: ensure ElectronBrowser mojo service is only bound to appropriate render frames (#33323) * fix: ensure ElectronBrowser mojo service is only bound to authorized render frames Notes: no-notes * refactor: extract electron API IPC to its own mojo interface * fix: just check main frame not primary main frame --- filenames.gni | 6 +- .../browser/api/electron_api_web_contents.cc | 13 +- shell/browser/api/electron_api_web_contents.h | 16 +- shell/browser/api/event.h | 2 +- .../browser/electron_api_ipc_handler_impl.cc | 108 ++++++++++++++ ...impl.h => electron_api_ipc_handler_impl.h} | 37 ++--- shell/browser/electron_browser_client.cc | 30 +++- .../browser/electron_browser_handler_impl.cc | 141 ------------------ ...ctron_web_contents_utility_handler_impl.cc | 83 +++++++++++ ...ectron_web_contents_utility_handler_impl.h | 71 +++++++++ shell/browser/web_contents_preferences.h | 3 + shell/common/api/api.mojom | 28 ++-- shell/common/gin_helper/event_emitter.cc | 2 +- shell/common/gin_helper/event_emitter.h | 2 +- .../renderer/api/electron_api_ipc_renderer.cc | 39 +++-- shell/renderer/api/electron_api_web_frame.cc | 14 +- .../electron_render_frame_observer.cc | 15 +- 17 files changed, 381 insertions(+), 229 deletions(-) create mode 100644 shell/browser/electron_api_ipc_handler_impl.cc rename shell/browser/{electron_browser_handler_impl.h => electron_api_ipc_handler_impl.h} (58%) delete mode 100644 shell/browser/electron_browser_handler_impl.cc create mode 100644 shell/browser/electron_web_contents_utility_handler_impl.cc create mode 100644 shell/browser/electron_web_contents_utility_handler_impl.h diff --git a/filenames.gni b/filenames.gni index 8e6da3eb657f4..eae36f790483d 100644 --- a/filenames.gni +++ b/filenames.gni @@ -350,6 +350,8 @@ filenames = { "shell/browser/child_web_contents_tracker.h", "shell/browser/cookie_change_notifier.cc", "shell/browser/cookie_change_notifier.h", + "shell/browser/electron_api_ipc_handler_impl.cc", + "shell/browser/electron_api_ipc_handler_impl.h", "shell/browser/electron_autofill_driver.cc", "shell/browser/electron_autofill_driver.h", "shell/browser/electron_autofill_driver_factory.cc", @@ -358,8 +360,6 @@ filenames = { "shell/browser/electron_browser_client.h", "shell/browser/electron_browser_context.cc", "shell/browser/electron_browser_context.h", - "shell/browser/electron_browser_handler_impl.cc", - "shell/browser/electron_browser_handler_impl.h", "shell/browser/electron_browser_main_parts.cc", "shell/browser/electron_browser_main_parts.h", "shell/browser/electron_download_manager_delegate.cc", @@ -376,6 +376,8 @@ filenames = { "shell/browser/electron_quota_permission_context.h", "shell/browser/electron_speech_recognition_manager_delegate.cc", "shell/browser/electron_speech_recognition_manager_delegate.h", + "shell/browser/electron_web_contents_utility_handler_impl.cc", + "shell/browser/electron_web_contents_utility_handler_impl.h", "shell/browser/electron_web_ui_controller_factory.cc", "shell/browser/electron_web_ui_controller_factory.h", "shell/browser/event_emitter_mixin.cc", diff --git a/shell/browser/api/electron_api_web_contents.cc b/shell/browser/api/electron_api_web_contents.cc index 0da1f050e7695..f6d275e8f4c3b 100644 --- a/shell/browser/api/electron_api_web_contents.cc +++ b/shell/browser/api/electron_api_web_contents.cc @@ -1751,7 +1751,7 @@ void WebContents::Message(bool internal, // webContents.emit('-ipc-message', new Event(), internal, channel, // arguments); EmitWithSender("-ipc-message", render_frame_host, - electron::mojom::ElectronBrowser::InvokeCallback(), internal, + electron::mojom::ElectronApiIPC::InvokeCallback(), internal, channel, std::move(arguments)); } @@ -1759,7 +1759,7 @@ void WebContents::Invoke( bool internal, const std::string& channel, blink::CloneableMessage arguments, - electron::mojom::ElectronBrowser::InvokeCallback callback, + electron::mojom::ElectronApiIPC::InvokeCallback callback, content::RenderFrameHost* render_frame_host) { TRACE_EVENT1("electron", "WebContents::Invoke", "channel", channel); // webContents.emit('-ipc-invoke', new Event(), internal, channel, arguments); @@ -1785,7 +1785,7 @@ void WebContents::ReceivePostMessage( v8::Local message_value = electron::DeserializeV8Value(isolate, message); EmitWithSender("-ipc-ports", render_frame_host, - electron::mojom::ElectronBrowser::InvokeCallback(), false, + electron::mojom::ElectronApiIPC::InvokeCallback(), false, channel, message_value, std::move(wrapped_ports)); } @@ -1793,7 +1793,7 @@ void WebContents::MessageSync( bool internal, const std::string& channel, blink::CloneableMessage arguments, - electron::mojom::ElectronBrowser::MessageSyncCallback callback, + electron::mojom::ElectronApiIPC::MessageSyncCallback callback, content::RenderFrameHost* render_frame_host) { TRACE_EVENT1("electron", "WebContents::MessageSync", "channel", channel); // webContents.emit('-ipc-message-sync', new Event(sender, message), internal, @@ -1831,7 +1831,7 @@ void WebContents::MessageHost(const std::string& channel, TRACE_EVENT1("electron", "WebContents::MessageHost", "channel", channel); // webContents.emit('ipc-message-host', new Event(), channel, args); EmitWithSender("ipc-message-host", render_frame_host, - electron::mojom::ElectronBrowser::InvokeCallback(), channel, + electron::mojom::ElectronApiIPC::InvokeCallback(), channel, std::move(arguments)); } @@ -3270,7 +3270,8 @@ void WebContents::SetTemporaryZoomLevel(double level) { } void WebContents::DoGetZoomLevel( - electron::mojom::ElectronBrowser::DoGetZoomLevelCallback callback) { + electron::mojom::ElectronWebContentsUtility::DoGetZoomLevelCallback + callback) { std::move(callback).Run(GetZoomLevel()); } diff --git a/shell/browser/api/electron_api_web_contents.h b/shell/browser/api/electron_api_web_contents.h index b034167631fa3..996c90cbbbc39 100644 --- a/shell/browser/api/electron_api_web_contents.h +++ b/shell/browser/api/electron_api_web_contents.h @@ -355,7 +355,7 @@ class WebContents : public ExclusiveAccessContext, template bool EmitWithSender(base::StringPiece name, content::RenderFrameHost* sender, - electron::mojom::ElectronBrowser::InvokeCallback callback, + electron::mojom::ElectronApiIPC::InvokeCallback callback, Args&&... args) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); v8::Isolate* isolate = JavascriptEnvironment::GetIsolate(); @@ -399,7 +399,7 @@ class WebContents : public ExclusiveAccessContext, fullscreen_frame_ = rfh; } - // mojom::ElectronBrowser + // mojom::ElectronApiIPC void Message(bool internal, const std::string& channel, blink::CloneableMessage arguments, @@ -407,9 +407,8 @@ class WebContents : public ExclusiveAccessContext, void Invoke(bool internal, const std::string& channel, blink::CloneableMessage arguments, - electron::mojom::ElectronBrowser::InvokeCallback callback, + electron::mojom::ElectronApiIPC::InvokeCallback callback, content::RenderFrameHost* render_frame_host); - void OnFirstNonEmptyLayout(content::RenderFrameHost* render_frame_host); void ReceivePostMessage(const std::string& channel, blink::TransferableMessage message, content::RenderFrameHost* render_frame_host); @@ -417,7 +416,7 @@ class WebContents : public ExclusiveAccessContext, bool internal, const std::string& channel, blink::CloneableMessage arguments, - electron::mojom::ElectronBrowser::MessageSyncCallback callback, + electron::mojom::ElectronApiIPC::MessageSyncCallback callback, content::RenderFrameHost* render_frame_host); void MessageTo(int32_t web_contents_id, const std::string& channel, @@ -425,10 +424,15 @@ class WebContents : public ExclusiveAccessContext, void MessageHost(const std::string& channel, blink::CloneableMessage arguments, content::RenderFrameHost* render_frame_host); + + // mojom::ElectronWebContentsUtility + void OnFirstNonEmptyLayout(content::RenderFrameHost* render_frame_host); void UpdateDraggableRegions(std::vector regions); void SetTemporaryZoomLevel(double level); void DoGetZoomLevel( - electron::mojom::ElectronBrowser::DoGetZoomLevelCallback callback); + electron::mojom::ElectronWebContentsUtility::DoGetZoomLevelCallback + callback); + void SetImageAnimationPolicy(const std::string& new_policy); // Grants |origin| access to |device|. diff --git a/shell/browser/api/event.h b/shell/browser/api/event.h index 4a09575896e11..a9e4dec39e9d8 100644 --- a/shell/browser/api/event.h +++ b/shell/browser/api/event.h @@ -13,7 +13,7 @@ namespace gin_helper { class Event : public gin::Wrappable { public: - using InvokeCallback = electron::mojom::ElectronBrowser::InvokeCallback; + using InvokeCallback = electron::mojom::ElectronApiIPC::InvokeCallback; static gin::WrapperInfo kWrapperInfo; diff --git a/shell/browser/electron_api_ipc_handler_impl.cc b/shell/browser/electron_api_ipc_handler_impl.cc new file mode 100644 index 0000000000000..5a13fda3629e9 --- /dev/null +++ b/shell/browser/electron_api_ipc_handler_impl.cc @@ -0,0 +1,108 @@ +// Copyright (c) 2022 Slack Technologies, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "shell/browser/electron_api_ipc_handler_impl.h" + +#include + +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/render_process_host.h" +#include "mojo/public/cpp/bindings/self_owned_receiver.h" + +namespace electron { +ElectronApiIPCHandlerImpl::ElectronApiIPCHandlerImpl( + content::RenderFrameHost* frame_host, + mojo::PendingAssociatedReceiver receiver) + : render_process_id_(frame_host->GetProcess()->GetID()), + render_frame_id_(frame_host->GetRoutingID()) { + content::WebContents* web_contents = + content::WebContents::FromRenderFrameHost(frame_host); + DCHECK(web_contents); + content::WebContentsObserver::Observe(web_contents); + + receiver_.Bind(std::move(receiver)); + receiver_.set_disconnect_handler(base::BindOnce( + &ElectronApiIPCHandlerImpl::OnConnectionError, GetWeakPtr())); +} + +ElectronApiIPCHandlerImpl::~ElectronApiIPCHandlerImpl() = default; + +void ElectronApiIPCHandlerImpl::WebContentsDestroyed() { + delete this; +} + +void ElectronApiIPCHandlerImpl::OnConnectionError() { + delete this; +} + +void ElectronApiIPCHandlerImpl::Message(bool internal, + const std::string& channel, + blink::CloneableMessage arguments) { + api::WebContents* api_web_contents = api::WebContents::From(web_contents()); + if (api_web_contents) { + api_web_contents->Message(internal, channel, std::move(arguments), + GetRenderFrameHost()); + } +} +void ElectronApiIPCHandlerImpl::Invoke(bool internal, + const std::string& channel, + blink::CloneableMessage arguments, + InvokeCallback callback) { + api::WebContents* api_web_contents = api::WebContents::From(web_contents()); + if (api_web_contents) { + api_web_contents->Invoke(internal, channel, std::move(arguments), + std::move(callback), GetRenderFrameHost()); + } +} + +void ElectronApiIPCHandlerImpl::ReceivePostMessage( + const std::string& channel, + blink::TransferableMessage message) { + api::WebContents* api_web_contents = api::WebContents::From(web_contents()); + if (api_web_contents) { + api_web_contents->ReceivePostMessage(channel, std::move(message), + GetRenderFrameHost()); + } +} + +void ElectronApiIPCHandlerImpl::MessageSync(bool internal, + const std::string& channel, + blink::CloneableMessage arguments, + MessageSyncCallback callback) { + api::WebContents* api_web_contents = api::WebContents::From(web_contents()); + if (api_web_contents) { + api_web_contents->MessageSync(internal, channel, std::move(arguments), + std::move(callback), GetRenderFrameHost()); + } +} + +void ElectronApiIPCHandlerImpl::MessageTo(int32_t web_contents_id, + const std::string& channel, + blink::CloneableMessage arguments) { + api::WebContents* api_web_contents = api::WebContents::From(web_contents()); + if (api_web_contents) { + api_web_contents->MessageTo(web_contents_id, channel, std::move(arguments)); + } +} + +void ElectronApiIPCHandlerImpl::MessageHost(const std::string& channel, + blink::CloneableMessage arguments) { + api::WebContents* api_web_contents = api::WebContents::From(web_contents()); + if (api_web_contents) { + api_web_contents->MessageHost(channel, std::move(arguments), + GetRenderFrameHost()); + } +} + +content::RenderFrameHost* ElectronApiIPCHandlerImpl::GetRenderFrameHost() { + return content::RenderFrameHost::FromID(render_process_id_, render_frame_id_); +} + +// static +void ElectronApiIPCHandlerImpl::Create( + content::RenderFrameHost* frame_host, + mojo::PendingAssociatedReceiver receiver) { + new ElectronApiIPCHandlerImpl(frame_host, std::move(receiver)); +} +} // namespace electron diff --git a/shell/browser/electron_browser_handler_impl.h b/shell/browser/electron_api_ipc_handler_impl.h similarity index 58% rename from shell/browser/electron_browser_handler_impl.h rename to shell/browser/electron_api_ipc_handler_impl.h index fea3f11907d1d..7cddf88bedc4a 100644 --- a/shell/browser/electron_browser_handler_impl.h +++ b/shell/browser/electron_api_ipc_handler_impl.h @@ -1,9 +1,9 @@ -// Copyright (c) 2019 Slack Technologies, Inc. +// Copyright (c) 2022 Slack Technologies, Inc. // Use of this source code is governed by the MIT license that can be // found in the LICENSE file. -#ifndef ELECTRON_SHELL_BROWSER_ELECTRON_BROWSER_HANDLER_IMPL_H_ -#define ELECTRON_SHELL_BROWSER_ELECTRON_BROWSER_HANDLER_IMPL_H_ +#ifndef ELECTRON_SHELL_BROWSER_ELECTRON_API_IPC_HANDLER_IMPL_H_ +#define ELECTRON_SHELL_BROWSER_ELECTRON_API_IPC_HANDLER_IMPL_H_ #include #include @@ -18,23 +18,23 @@ class RenderFrameHost; } namespace electron { -class ElectronBrowserHandlerImpl : public mojom::ElectronBrowser, - public content::WebContentsObserver { +class ElectronApiIPCHandlerImpl : public mojom::ElectronApiIPC, + public content::WebContentsObserver { public: - explicit ElectronBrowserHandlerImpl( + explicit ElectronApiIPCHandlerImpl( content::RenderFrameHost* render_frame_host, - mojo::PendingAssociatedReceiver receiver); + mojo::PendingAssociatedReceiver receiver); static void Create( content::RenderFrameHost* frame_host, - mojo::PendingAssociatedReceiver receiver); + mojo::PendingAssociatedReceiver receiver); // disable copy - ElectronBrowserHandlerImpl(const ElectronBrowserHandlerImpl&) = delete; - ElectronBrowserHandlerImpl& operator=(const ElectronBrowserHandlerImpl&) = + ElectronApiIPCHandlerImpl(const ElectronApiIPCHandlerImpl&) = delete; + ElectronApiIPCHandlerImpl& operator=(const ElectronApiIPCHandlerImpl&) = delete; - // mojom::ElectronBrowser: + // mojom::ElectronApiIPC: void Message(bool internal, const std::string& channel, blink::CloneableMessage arguments) override; @@ -42,7 +42,6 @@ class ElectronBrowserHandlerImpl : public mojom::ElectronBrowser, const std::string& channel, blink::CloneableMessage arguments, InvokeCallback callback) override; - void OnFirstNonEmptyLayout() override; void ReceivePostMessage(const std::string& channel, blink::TransferableMessage message) override; void MessageSync(bool internal, @@ -54,17 +53,13 @@ class ElectronBrowserHandlerImpl : public mojom::ElectronBrowser, blink::CloneableMessage arguments) override; void MessageHost(const std::string& channel, blink::CloneableMessage arguments) override; - void UpdateDraggableRegions( - std::vector regions) override; - void SetTemporaryZoomLevel(double level) override; - void DoGetZoomLevel(DoGetZoomLevelCallback callback) override; - base::WeakPtr GetWeakPtr() { + base::WeakPtr GetWeakPtr() { return weak_factory_.GetWeakPtr(); } private: - ~ElectronBrowserHandlerImpl() override; + ~ElectronApiIPCHandlerImpl() override; // content::WebContentsObserver: void WebContentsDestroyed() override; @@ -76,9 +71,9 @@ class ElectronBrowserHandlerImpl : public mojom::ElectronBrowser, const int render_process_id_; const int render_frame_id_; - mojo::AssociatedReceiver receiver_{this}; + mojo::AssociatedReceiver receiver_{this}; - base::WeakPtrFactory weak_factory_{this}; + base::WeakPtrFactory weak_factory_{this}; }; } // namespace electron -#endif // ELECTRON_SHELL_BROWSER_ELECTRON_BROWSER_HANDLER_IMPL_H_ +#endif // ELECTRON_SHELL_BROWSER_ELECTRON_API_IPC_HANDLER_IMPL_H_ diff --git a/shell/browser/electron_browser_client.cc b/shell/browser/electron_browser_client.cc index 04e31a63b754d..50fff944a3af3 100644 --- a/shell/browser/electron_browser_client.cc +++ b/shell/browser/electron_browser_client.cc @@ -77,13 +77,14 @@ #include "shell/browser/api/electron_api_web_request.h" #include "shell/browser/badging/badge_manager.h" #include "shell/browser/child_web_contents_tracker.h" +#include "shell/browser/electron_api_ipc_handler_impl.h" #include "shell/browser/electron_autofill_driver_factory.h" #include "shell/browser/electron_browser_context.h" -#include "shell/browser/electron_browser_handler_impl.h" #include "shell/browser/electron_browser_main_parts.h" #include "shell/browser/electron_navigation_throttle.h" #include "shell/browser/electron_quota_permission_context.h" #include "shell/browser/electron_speech_recognition_manager_delegate.h" +#include "shell/browser/electron_web_contents_utility_handler_impl.h" #include "shell/browser/font_defaults.h" #include "shell/browser/javascript_environment.h" #include "shell/browser/media/media_capture_devices_dispatcher.h" @@ -1515,14 +1516,33 @@ void ElectronBrowserClient:: render_frame_host, // NOLINT(runtime/references) blink::AssociatedInterfaceRegistry& associated_registry) { // NOLINT(runtime/references) + auto* contents = + content::WebContents::FromRenderFrameHost(&render_frame_host); + if (contents) { + auto* prefs = WebContentsPreferences::From(contents); + if (render_frame_host.GetFrameTreeNodeId() == + contents->GetMainFrame()->GetFrameTreeNodeId() || + (prefs && prefs->AllowsNodeIntegrationInSubFrames())) { + associated_registry.AddInterface(base::BindRepeating( + [](content::RenderFrameHost* render_frame_host, + mojo::PendingAssociatedReceiver + receiver) { + ElectronApiIPCHandlerImpl::Create(render_frame_host, + std::move(receiver)); + }, + &render_frame_host)); + } + } + associated_registry.AddInterface(base::BindRepeating( [](content::RenderFrameHost* render_frame_host, - mojo::PendingAssociatedReceiver - receiver) { - ElectronBrowserHandlerImpl::Create(render_frame_host, - std::move(receiver)); + mojo::PendingAssociatedReceiver< + electron::mojom::ElectronWebContentsUtility> receiver) { + ElectronWebContentsUtilityHandlerImpl::Create(render_frame_host, + std::move(receiver)); }, &render_frame_host)); + associated_registry.AddInterface(base::BindRepeating( [](content::RenderFrameHost* render_frame_host, mojo::PendingAssociatedReceiver diff --git a/shell/browser/electron_browser_handler_impl.cc b/shell/browser/electron_browser_handler_impl.cc deleted file mode 100644 index e66968b0cb132..0000000000000 --- a/shell/browser/electron_browser_handler_impl.cc +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright (c) 2019 Slack Technologies, Inc. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -#include "shell/browser/electron_browser_handler_impl.h" - -#include - -#include "content/public/browser/browser_context.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/render_frame_host.h" -#include "content/public/browser/render_process_host.h" -#include "mojo/public/cpp/bindings/self_owned_receiver.h" - -namespace electron { -ElectronBrowserHandlerImpl::ElectronBrowserHandlerImpl( - content::RenderFrameHost* frame_host, - mojo::PendingAssociatedReceiver receiver) - : render_process_id_(frame_host->GetProcess()->GetID()), - render_frame_id_(frame_host->GetRoutingID()) { - content::WebContents* web_contents = - content::WebContents::FromRenderFrameHost(frame_host); - DCHECK(web_contents); - content::WebContentsObserver::Observe(web_contents); - - receiver_.Bind(std::move(receiver)); - receiver_.set_disconnect_handler(base::BindOnce( - &ElectronBrowserHandlerImpl::OnConnectionError, GetWeakPtr())); -} - -ElectronBrowserHandlerImpl::~ElectronBrowserHandlerImpl() = default; - -void ElectronBrowserHandlerImpl::WebContentsDestroyed() { - delete this; -} - -void ElectronBrowserHandlerImpl::OnConnectionError() { - delete this; -} - -void ElectronBrowserHandlerImpl::Message(bool internal, - const std::string& channel, - blink::CloneableMessage arguments) { - api::WebContents* api_web_contents = api::WebContents::From(web_contents()); - if (api_web_contents) { - api_web_contents->Message(internal, channel, std::move(arguments), - GetRenderFrameHost()); - } -} -void ElectronBrowserHandlerImpl::Invoke(bool internal, - const std::string& channel, - blink::CloneableMessage arguments, - InvokeCallback callback) { - api::WebContents* api_web_contents = api::WebContents::From(web_contents()); - if (api_web_contents) { - api_web_contents->Invoke(internal, channel, std::move(arguments), - std::move(callback), GetRenderFrameHost()); - } -} - -void ElectronBrowserHandlerImpl::OnFirstNonEmptyLayout() { - api::WebContents* api_web_contents = api::WebContents::From(web_contents()); - if (api_web_contents) { - api_web_contents->OnFirstNonEmptyLayout(GetRenderFrameHost()); - } -} - -void ElectronBrowserHandlerImpl::ReceivePostMessage( - const std::string& channel, - blink::TransferableMessage message) { - api::WebContents* api_web_contents = api::WebContents::From(web_contents()); - if (api_web_contents) { - api_web_contents->ReceivePostMessage(channel, std::move(message), - GetRenderFrameHost()); - } -} - -void ElectronBrowserHandlerImpl::MessageSync(bool internal, - const std::string& channel, - blink::CloneableMessage arguments, - MessageSyncCallback callback) { - api::WebContents* api_web_contents = api::WebContents::From(web_contents()); - if (api_web_contents) { - api_web_contents->MessageSync(internal, channel, std::move(arguments), - std::move(callback), GetRenderFrameHost()); - } -} - -void ElectronBrowserHandlerImpl::MessageTo(int32_t web_contents_id, - const std::string& channel, - blink::CloneableMessage arguments) { - api::WebContents* api_web_contents = api::WebContents::From(web_contents()); - if (api_web_contents) { - api_web_contents->MessageTo(web_contents_id, channel, std::move(arguments)); - } -} - -void ElectronBrowserHandlerImpl::MessageHost( - const std::string& channel, - blink::CloneableMessage arguments) { - api::WebContents* api_web_contents = api::WebContents::From(web_contents()); - if (api_web_contents) { - api_web_contents->MessageHost(channel, std::move(arguments), - GetRenderFrameHost()); - } -} - -void ElectronBrowserHandlerImpl::UpdateDraggableRegions( - std::vector regions) { - api::WebContents* api_web_contents = api::WebContents::From(web_contents()); - if (api_web_contents) { - api_web_contents->UpdateDraggableRegions(std::move(regions)); - } -} - -void ElectronBrowserHandlerImpl::SetTemporaryZoomLevel(double level) { - api::WebContents* api_web_contents = api::WebContents::From(web_contents()); - if (api_web_contents) { - api_web_contents->SetTemporaryZoomLevel(level); - } -} - -void ElectronBrowserHandlerImpl::DoGetZoomLevel( - DoGetZoomLevelCallback callback) { - api::WebContents* api_web_contents = api::WebContents::From(web_contents()); - if (api_web_contents) { - api_web_contents->DoGetZoomLevel(std::move(callback)); - } -} - -content::RenderFrameHost* ElectronBrowserHandlerImpl::GetRenderFrameHost() { - return content::RenderFrameHost::FromID(render_process_id_, render_frame_id_); -} - -// static -void ElectronBrowserHandlerImpl::Create( - content::RenderFrameHost* frame_host, - mojo::PendingAssociatedReceiver receiver) { - new ElectronBrowserHandlerImpl(frame_host, std::move(receiver)); -} -} // namespace electron diff --git a/shell/browser/electron_web_contents_utility_handler_impl.cc b/shell/browser/electron_web_contents_utility_handler_impl.cc new file mode 100644 index 0000000000000..807dcdbdf9cc1 --- /dev/null +++ b/shell/browser/electron_web_contents_utility_handler_impl.cc @@ -0,0 +1,83 @@ +// Copyright (c) 2022 Slack Technologies, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "shell/browser/electron_web_contents_utility_handler_impl.h" + +#include + +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/render_process_host.h" +#include "mojo/public/cpp/bindings/self_owned_receiver.h" + +namespace electron { +ElectronWebContentsUtilityHandlerImpl::ElectronWebContentsUtilityHandlerImpl( + content::RenderFrameHost* frame_host, + mojo::PendingAssociatedReceiver receiver) + : render_process_id_(frame_host->GetProcess()->GetID()), + render_frame_id_(frame_host->GetRoutingID()) { + content::WebContents* web_contents = + content::WebContents::FromRenderFrameHost(frame_host); + DCHECK(web_contents); + content::WebContentsObserver::Observe(web_contents); + + receiver_.Bind(std::move(receiver)); + receiver_.set_disconnect_handler(base::BindOnce( + &ElectronWebContentsUtilityHandlerImpl::OnConnectionError, GetWeakPtr())); +} + +ElectronWebContentsUtilityHandlerImpl:: + ~ElectronWebContentsUtilityHandlerImpl() = default; + +void ElectronWebContentsUtilityHandlerImpl::WebContentsDestroyed() { + delete this; +} + +void ElectronWebContentsUtilityHandlerImpl::OnConnectionError() { + delete this; +} + +void ElectronWebContentsUtilityHandlerImpl::OnFirstNonEmptyLayout() { + api::WebContents* api_web_contents = api::WebContents::From(web_contents()); + if (api_web_contents) { + api_web_contents->OnFirstNonEmptyLayout(GetRenderFrameHost()); + } +} + +void ElectronWebContentsUtilityHandlerImpl::UpdateDraggableRegions( + std::vector regions) { + api::WebContents* api_web_contents = api::WebContents::From(web_contents()); + if (api_web_contents) { + api_web_contents->UpdateDraggableRegions(std::move(regions)); + } +} + +void ElectronWebContentsUtilityHandlerImpl::SetTemporaryZoomLevel( + double level) { + api::WebContents* api_web_contents = api::WebContents::From(web_contents()); + if (api_web_contents) { + api_web_contents->SetTemporaryZoomLevel(level); + } +} + +void ElectronWebContentsUtilityHandlerImpl::DoGetZoomLevel( + DoGetZoomLevelCallback callback) { + api::WebContents* api_web_contents = api::WebContents::From(web_contents()); + if (api_web_contents) { + api_web_contents->DoGetZoomLevel(std::move(callback)); + } +} + +content::RenderFrameHost* +ElectronWebContentsUtilityHandlerImpl::GetRenderFrameHost() { + return content::RenderFrameHost::FromID(render_process_id_, render_frame_id_); +} + +// static +void ElectronWebContentsUtilityHandlerImpl::Create( + content::RenderFrameHost* frame_host, + mojo::PendingAssociatedReceiver + receiver) { + new ElectronWebContentsUtilityHandlerImpl(frame_host, std::move(receiver)); +} +} // namespace electron diff --git a/shell/browser/electron_web_contents_utility_handler_impl.h b/shell/browser/electron_web_contents_utility_handler_impl.h new file mode 100644 index 0000000000000..30a9baa40f835 --- /dev/null +++ b/shell/browser/electron_web_contents_utility_handler_impl.h @@ -0,0 +1,71 @@ +// Copyright (c) 2022 Slack Technologies, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ELECTRON_SHELL_BROWSER_ELECTRON_WEB_CONTENTS_UTILITY_HANDLER_IMPL_H_ +#define ELECTRON_SHELL_BROWSER_ELECTRON_WEB_CONTENTS_UTILITY_HANDLER_IMPL_H_ + +#include +#include + +#include "base/memory/weak_ptr.h" +#include "content/public/browser/web_contents_observer.h" +#include "electron/shell/common/api/api.mojom.h" +#include "shell/browser/api/electron_api_web_contents.h" + +namespace content { +class RenderFrameHost; +} + +namespace electron { +class ElectronWebContentsUtilityHandlerImpl + : public mojom::ElectronWebContentsUtility, + public content::WebContentsObserver { + public: + explicit ElectronWebContentsUtilityHandlerImpl( + content::RenderFrameHost* render_frame_host, + mojo::PendingAssociatedReceiver + receiver); + + static void Create( + content::RenderFrameHost* frame_host, + mojo::PendingAssociatedReceiver + receiver); + + // disable copy + ElectronWebContentsUtilityHandlerImpl( + const ElectronWebContentsUtilityHandlerImpl&) = delete; + ElectronWebContentsUtilityHandlerImpl& operator=( + const ElectronWebContentsUtilityHandlerImpl&) = delete; + + // mojom::ElectronWebContentsUtility: + void OnFirstNonEmptyLayout() override; + void UpdateDraggableRegions( + std::vector regions) override; + void SetTemporaryZoomLevel(double level) override; + void DoGetZoomLevel(DoGetZoomLevelCallback callback) override; + + base::WeakPtr GetWeakPtr() { + return weak_factory_.GetWeakPtr(); + } + + private: + ~ElectronWebContentsUtilityHandlerImpl() override; + + // content::WebContentsObserver: + void WebContentsDestroyed() override; + + void OnConnectionError(); + + content::RenderFrameHost* GetRenderFrameHost(); + + const int render_process_id_; + const int render_frame_id_; + + mojo::AssociatedReceiver receiver_{this}; + + base::WeakPtrFactory weak_factory_{ + this}; +}; +} // namespace electron +#endif // ELECTRON_SHELL_BROWSER_ELECTRON_WEB_CONTENTS_UTILITY_HANDLER_IMPL_H_ diff --git a/shell/browser/web_contents_preferences.h b/shell/browser/web_contents_preferences.h index 912540ac0aad0..544bc54a80e46 100644 --- a/shell/browser/web_contents_preferences.h +++ b/shell/browser/web_contents_preferences.h @@ -71,6 +71,9 @@ class WebContentsPreferences bool ShouldDisableHtmlFullscreenWindowResize() const { return disable_html_fullscreen_window_resize_; } + bool AllowsNodeIntegrationInSubFrames() const { + return node_integration_in_sub_frames_; + } bool ShouldDisableDialogs() const { return disable_dialogs_; } bool ShouldUseSafeDialogs() const { return safe_dialogs_; } bool GetSafeDialogsMessage(std::string* message) const; diff --git a/shell/common/api/api.mojom b/shell/common/api/api.mojom index 1206b5858a183..4515b82ac48d0 100644 --- a/shell/common/api/api.mojom +++ b/shell/common/api/api.mojom @@ -31,7 +31,21 @@ struct DraggableRegion { gfx.mojom.Rect bounds; }; -interface ElectronBrowser { +interface ElectronWebContentsUtility { + // Informs underlying WebContents that first non-empty layout was performed + // by compositor. + OnFirstNonEmptyLayout(); + + UpdateDraggableRegions( + array regions); + + SetTemporaryZoomLevel(double zoom_level); + + [Sync] + DoGetZoomLevel() => (double result); +}; + +interface ElectronApiIPC { // Emits an event on |channel| from the ipcMain JavaScript object in the main // process. Message( @@ -46,10 +60,6 @@ interface ElectronBrowser { string channel, blink.mojom.CloneableMessage arguments) => (blink.mojom.CloneableMessage result); - // Informs underlying WebContents that first non-empty layout was performed - // by compositor. - OnFirstNonEmptyLayout(); - ReceivePostMessage(string channel, blink.mojom.TransferableMessage message); // Emits an event on |channel| from the ipcMain JavaScript object in the main @@ -70,12 +80,4 @@ interface ElectronBrowser { MessageHost( string channel, blink.mojom.CloneableMessage arguments); - - UpdateDraggableRegions( - array regions); - - SetTemporaryZoomLevel(double zoom_level); - - [Sync] - DoGetZoomLevel() => (double result); }; diff --git a/shell/common/gin_helper/event_emitter.cc b/shell/common/gin_helper/event_emitter.cc index 8779c05507ba1..32a3e4b1b8183 100644 --- a/shell/common/gin_helper/event_emitter.cc +++ b/shell/common/gin_helper/event_emitter.cc @@ -54,7 +54,7 @@ v8::Local CreateNativeEvent( v8::Isolate* isolate, v8::Local sender, content::RenderFrameHost* frame, - electron::mojom::ElectronBrowser::MessageSyncCallback callback) { + electron::mojom::ElectronApiIPC::MessageSyncCallback callback) { v8::Local event; if (frame && callback) { gin::Handle native_event = Event::Create(isolate); diff --git a/shell/common/gin_helper/event_emitter.h b/shell/common/gin_helper/event_emitter.h index a69b595551ffb..90af3f7478df4 100644 --- a/shell/common/gin_helper/event_emitter.h +++ b/shell/common/gin_helper/event_emitter.h @@ -29,7 +29,7 @@ v8::Local CreateNativeEvent( v8::Isolate* isolate, v8::Local sender, content::RenderFrameHost* frame, - electron::mojom::ElectronBrowser::MessageSyncCallback callback); + electron::mojom::ElectronApiIPC::MessageSyncCallback callback); } // namespace internal diff --git a/shell/renderer/api/electron_api_ipc_renderer.cc b/shell/renderer/api/electron_api_ipc_renderer.cc index 6b4f2698a968a..6f24ed17c4a3d 100644 --- a/shell/renderer/api/electron_api_ipc_renderer.cc +++ b/shell/renderer/api/electron_api_ipc_renderer.cc @@ -60,16 +60,16 @@ class IPCRenderer : public gin::Wrappable, weak_context_.SetWeak(); render_frame->GetRemoteAssociatedInterfaces()->GetInterface( - &electron_browser_remote_); + &electron_ipc_remote_); } - void OnDestruct() override { electron_browser_remote_.reset(); } + void OnDestruct() override { electron_ipc_remote_.reset(); } void WillReleaseScriptContext(v8::Local context, int32_t world_id) override { if (weak_context_.IsEmpty() || weak_context_.Get(context->GetIsolate()) == context) - electron_browser_remote_.reset(); + electron_ipc_remote_.reset(); } // gin::Wrappable: @@ -92,7 +92,7 @@ class IPCRenderer : public gin::Wrappable, bool internal, const std::string& channel, v8::Local arguments) { - if (!electron_browser_remote_) { + if (!electron_ipc_remote_) { thrower.ThrowError(kIPCMethodCalledAfterContextReleasedError); return; } @@ -100,7 +100,7 @@ class IPCRenderer : public gin::Wrappable, if (!electron::SerializeV8Value(isolate, arguments, &message)) { return; } - electron_browser_remote_->Message(internal, channel, std::move(message)); + electron_ipc_remote_->Message(internal, channel, std::move(message)); } v8::Local Invoke(v8::Isolate* isolate, @@ -108,7 +108,7 @@ class IPCRenderer : public gin::Wrappable, bool internal, const std::string& channel, v8::Local arguments) { - if (!electron_browser_remote_) { + if (!electron_ipc_remote_) { thrower.ThrowError(kIPCMethodCalledAfterContextReleasedError); return v8::Local(); } @@ -119,7 +119,7 @@ class IPCRenderer : public gin::Wrappable, gin_helper::Promise p(isolate); auto handle = p.GetHandle(); - electron_browser_remote_->Invoke( + electron_ipc_remote_->Invoke( internal, channel, std::move(message), base::BindOnce( [](gin_helper::Promise p, @@ -134,7 +134,7 @@ class IPCRenderer : public gin::Wrappable, const std::string& channel, v8::Local message_value, absl::optional> transfer) { - if (!electron_browser_remote_) { + if (!electron_ipc_remote_) { thrower.ThrowError(kIPCMethodCalledAfterContextReleasedError); return; } @@ -166,8 +166,8 @@ class IPCRenderer : public gin::Wrappable, } transferable_message.ports = std::move(ports); - electron_browser_remote_->ReceivePostMessage( - channel, std::move(transferable_message)); + electron_ipc_remote_->ReceivePostMessage(channel, + std::move(transferable_message)); } void SendTo(v8::Isolate* isolate, @@ -175,7 +175,7 @@ class IPCRenderer : public gin::Wrappable, int32_t web_contents_id, const std::string& channel, v8::Local arguments) { - if (!electron_browser_remote_) { + if (!electron_ipc_remote_) { thrower.ThrowError(kIPCMethodCalledAfterContextReleasedError); return; } @@ -183,15 +183,15 @@ class IPCRenderer : public gin::Wrappable, if (!electron::SerializeV8Value(isolate, arguments, &message)) { return; } - electron_browser_remote_->MessageTo(web_contents_id, channel, - std::move(message)); + electron_ipc_remote_->MessageTo(web_contents_id, channel, + std::move(message)); } void SendToHost(v8::Isolate* isolate, gin_helper::ErrorThrower thrower, const std::string& channel, v8::Local arguments) { - if (!electron_browser_remote_) { + if (!electron_ipc_remote_) { thrower.ThrowError(kIPCMethodCalledAfterContextReleasedError); return; } @@ -199,7 +199,7 @@ class IPCRenderer : public gin::Wrappable, if (!electron::SerializeV8Value(isolate, arguments, &message)) { return; } - electron_browser_remote_->MessageHost(channel, std::move(message)); + electron_ipc_remote_->MessageHost(channel, std::move(message)); } v8::Local SendSync(v8::Isolate* isolate, @@ -207,7 +207,7 @@ class IPCRenderer : public gin::Wrappable, bool internal, const std::string& channel, v8::Local arguments) { - if (!electron_browser_remote_) { + if (!electron_ipc_remote_) { thrower.ThrowError(kIPCMethodCalledAfterContextReleasedError); return v8::Local(); } @@ -217,14 +217,13 @@ class IPCRenderer : public gin::Wrappable, } blink::CloneableMessage result; - electron_browser_remote_->MessageSync(internal, channel, std::move(message), - &result); + electron_ipc_remote_->MessageSync(internal, channel, std::move(message), + &result); return electron::DeserializeV8Value(isolate, result); } v8::Global weak_context_; - mojo::AssociatedRemote - electron_browser_remote_; + mojo::AssociatedRemote electron_ipc_remote_; }; gin::WrapperInfo IPCRenderer::kWrapperInfo = {gin::kEmbedderNativeGin}; diff --git a/shell/renderer/api/electron_api_web_frame.cc b/shell/renderer/api/electron_api_web_frame.cc index 25d2b5433b680..6ec08e583da96 100644 --- a/shell/renderer/api/electron_api_web_frame.cc +++ b/shell/renderer/api/electron_api_web_frame.cc @@ -453,10 +453,11 @@ class WebFrameRenderer : public gin::Wrappable, if (!MaybeGetRenderFrame(isolate, "setZoomLevel", &render_frame)) return; - mojo::AssociatedRemote browser_remote; + mojo::AssociatedRemote + web_contents_utility_remote; render_frame->GetRemoteAssociatedInterfaces()->GetInterface( - &browser_remote); - browser_remote->SetTemporaryZoomLevel(level); + &web_contents_utility_remote); + web_contents_utility_remote->SetTemporaryZoomLevel(level); } double GetZoomLevel(v8::Isolate* isolate) { @@ -465,10 +466,11 @@ class WebFrameRenderer : public gin::Wrappable, if (!MaybeGetRenderFrame(isolate, "getZoomLevel", &render_frame)) return result; - mojo::AssociatedRemote browser_remote; + mojo::AssociatedRemote + web_contents_utility_remote; render_frame->GetRemoteAssociatedInterfaces()->GetInterface( - &browser_remote); - browser_remote->DoGetZoomLevel(&result); + &web_contents_utility_remote); + web_contents_utility_remote->DoGetZoomLevel(&result); return result; } diff --git a/shell/renderer/electron_render_frame_observer.cc b/shell/renderer/electron_render_frame_observer.cc index 4c763315f3539..2c22d1fceb62b 100644 --- a/shell/renderer/electron_render_frame_observer.cc +++ b/shell/renderer/electron_render_frame_observer.cc @@ -149,9 +149,11 @@ void ElectronRenderFrameObserver::DraggableRegionsChanged() { regions.push_back(std::move(region)); } - mojo::AssociatedRemote browser_remote; - render_frame_->GetRemoteAssociatedInterfaces()->GetInterface(&browser_remote); - browser_remote->UpdateDraggableRegions(std::move(regions)); + mojo::AssociatedRemote + web_contents_utility_remote; + render_frame_->GetRemoteAssociatedInterfaces()->GetInterface( + &web_contents_utility_remote); + web_contents_utility_remote->UpdateDraggableRegions(std::move(regions)); } void ElectronRenderFrameObserver::WillReleaseScriptContext( @@ -168,10 +170,11 @@ void ElectronRenderFrameObserver::OnDestruct() { void ElectronRenderFrameObserver::DidMeaningfulLayout( blink::WebMeaningfulLayout layout_type) { if (layout_type == blink::WebMeaningfulLayout::kVisuallyNonEmpty) { - mojo::AssociatedRemote browser_remote; + mojo::AssociatedRemote + web_contents_utility_remote; render_frame_->GetRemoteAssociatedInterfaces()->GetInterface( - &browser_remote); - browser_remote->OnFirstNonEmptyLayout(); + &web_contents_utility_remote); + web_contents_utility_remote->OnFirstNonEmptyLayout(); } } From 08d54d241693441ef672efa87009c0eb01ae86cb Mon Sep 17 00:00:00 2001 From: Keeley Hammond Date: Fri, 18 Mar 2022 21:29:42 -0700 Subject: [PATCH 38/38] fix: intialize FPS file in network service (#33339) --- shell/browser/net/system_network_context_manager.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/shell/browser/net/system_network_context_manager.cc b/shell/browser/net/system_network_context_manager.cc index d1f474d59ead7..de3989ad88678 100644 --- a/shell/browser/net/system_network_context_manager.cc +++ b/shell/browser/net/system_network_context_manager.cc @@ -288,6 +288,10 @@ void SystemNetworkContextManager::OnNetworkServiceCreated( base::FeatureList::IsEnabled(features::kAsyncDns), default_secure_dns_mode, doh_config, additional_dns_query_types_enabled); + // Initializes first party sets component + // CL: https://chromium-review.googlesource.com/c/chromium/src/+/3449280 + content::GetNetworkService()->SetFirstPartySets(base::File()); + std::string app_name = electron::Browser::Get()->GetName(); #if BUILDFLAG(IS_MAC) KeychainPassword::GetServiceName() = app_name + " Safe Storage";