Compare commits

..

3 Commits

Author SHA1 Message Date
Shelley Vohr
29fe95a77c Merge branch 'main' into fix/webrequest-checks 2026-04-09 15:22:43 +02:00
Samuel Maddock
3a18e564f5 test: webRequest no crash 2024-12-23 12:50:33 -05:00
Sam Maddock
4e0acd65e0 fix: checks in extensions webRequest when using net.fetch
Several DCHECKs require `frame_host` data to proceed with proxying.
https://source.chromium.org/chromium/chromium/src/+/main:extensions/browser/api/web_request/web_request_api.cc;l=446-450;drc=f5e280b6c11f41545154266cd2317d3c730e9b30

Note that even if our URLLoader is updated to not use `content::ContentBrowserClient::URLLoaderFactoryType::kNavigation`, further checks are still thrown.
dc74092a09/shell/browser/electron_browser_context.cc (L547)
2024-12-17 00:05:53 -05:00
19 changed files with 461 additions and 93 deletions

View File

@@ -442,7 +442,34 @@ jobs:
contents: read
needs: [docs-only, macos-x64, macos-arm64, linux-x64, linux-x64-asan, linux-arm, linux-arm64, windows-x64, windows-x86, windows-arm64]
if: always() && github.repository == 'electron/electron' && !contains(needs.*.result, 'failure')
steps:
steps:
- name: GitHub Actions Jobs Done
run: |
echo "All GitHub Actions Jobs are done"
check-signed-commits:
name: Check signed commits in green PR
needs: gha-done
if: ${{ contains(github.event.pull_request.labels.*.name, 'needs-signed-commits')}}
runs-on: ubuntu-slim
permissions:
contents: read
pull-requests: write
steps:
- name: Check signed commits in PR
uses: 1Password/check-signed-commits-action@ed2885f3ed2577a4f5d3c3fe895432a557d23d52 # v1
with:
comment: |
⚠️ This PR contains unsigned commits. This repository enforces [commit signatures](https://docs.github.com/en/authentication/managing-commit-signature-verification)
for all incoming PRs. To get your PR merged, please sign those commits
(`git rebase --exec 'git commit -S --amend --no-edit -n' @{upstream}`) and force push them to this branch
(`git push --force-with-lease`)
For more information on signing commits, see GitHub's documentation on [Telling Git about your signing key](https://docs.github.com/en/authentication/managing-commit-signature-verification/telling-git-about-your-signing-key).
- name: Remove needs-signed-commits label
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_URL: ${{ github.event.pull_request.html_url }}
run: |
gh pr edit $PR_URL --remove-label needs-signed-commits

View File

@@ -13,6 +13,7 @@ permissions: {}
jobs:
check-signed-commits:
name: Check signed commits in PR
if: ${{ !contains(github.event.pull_request.labels.*.name, 'needs-signed-commits')}}
runs-on: ubuntu-slim
permissions:
contents: read
@@ -22,9 +23,9 @@ jobs:
uses: 1Password/check-signed-commits-action@ed2885f3ed2577a4f5d3c3fe895432a557d23d52 # v1
with:
comment: |
⚠️ This PR contains unsigned commits. This repository enforces [commit signatures](https://docs.github.com/en/authentication/managing-commit-signature-verification)
for all incoming PRs. To get your PR merged, please sign those commits
(`git rebase --exec 'git commit -S --amend --no-edit -n' @{upstream}`) and force push them to this branch
⚠️ This PR contains unsigned commits. This repository enforces [commit signatures](https://docs.github.com/en/authentication/managing-commit-signature-verification)
for all incoming PRs. To get your PR merged, please sign those commits
(`git rebase --exec 'git commit -S --amend --no-edit -n' @{upstream}`) and force push them to this branch
(`git push --force-with-lease`)
For more information on signing commits, see GitHub's documentation on [Telling Git about your signing key](https://docs.github.com/en/authentication/managing-commit-signature-verification/telling-git-about-your-signing-key).
@@ -36,11 +37,3 @@ jobs:
PR_URL: ${{ github.event.pull_request.html_url }}
run: |
gh pr edit $PR_URL --add-label needs-signed-commits
- name: Remove needs-signed-commits label
if: ${{ success() && contains(github.event.pull_request.labels.*.name, 'needs-signed-commits') }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_URL: ${{ github.event.pull_request.html_url }}
run: |
gh pr edit $PR_URL --remove-label needs-signed-commits

View File

@@ -11,6 +11,13 @@ app.on('window-all-closed', () => {
app.quit();
});
function decorateURL (url: string) {
// safely add `?utm_source=default_app
const parsedUrl = new URL(url);
parsedUrl.searchParams.append('utm_source', 'default_app');
return parsedUrl.toString();
}
// Find the shortest path to the electron binary
const absoluteElectronPath = process.execPath;
const relativeElectronPath = path.relative(process.cwd(), absoluteElectronPath);
@@ -62,7 +69,7 @@ async function createWindow (backgroundColor?: string) {
mainWindow.on('ready-to-show', () => mainWindow!.show());
mainWindow.webContents.setWindowOpenHandler(details => {
shell.openExternal(details.url);
shell.openExternal(decorateURL(details.url));
return { action: 'deny' };
});

View File

@@ -125,6 +125,7 @@ feat_separate_content_settings_callback_for_sync_and_async_clipboard.patch
fix_win32_synchronous_spellcheck.patch
chore_grandfather_in_electron_views_and_delegates.patch
refactor_patch_electron_permissiontypes_into_blink.patch
revert_views_remove_desktopwindowtreehostwin_window_enlargement.patch
fix_add_macos_memory_query_fallback_to_avoid_crash.patch
fix_resolve_dynamic_background_material_update_issue_on_windows_11.patch
feat_add_support_for_embedder_snapshot_validation.patch

View File

@@ -8,10 +8,10 @@ such as the background turning black when maximizing the window and
dynamic background material settings not taking effect.
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
index e4da40256ce94d6a0896792a8ef2faa18e1fa5d2..3a5833fcc018f32e86c0a95a42937fb9ac6c5a40 100644
index d1e06b675b19226cf3b78e1aada8d8f2d684fada..ce810555b8501797643987916a728cad8f5adaa5 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
@@ -167,6 +167,10 @@ void DesktopWindowTreeHostWin::FinishTouchDrag(gfx::Point screen_point) {
@@ -184,6 +184,10 @@ void DesktopWindowTreeHostWin::FinishTouchDrag(gfx::Point screen_point) {
}
}
@@ -23,7 +23,7 @@ index e4da40256ce94d6a0896792a8ef2faa18e1fa5d2..3a5833fcc018f32e86c0a95a42937fb9
void DesktopWindowTreeHostWin::Init(const Widget::InitParams& params) {
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
index 27322ef34edf3fa8bfbd20b1baddcaf3b7555618..b8d1fa863fd05ebc3ab8ac5ef8c4d81361ce45fe 100644
index a40bd9f25fa07a553c011cf19f155f8158f4ae5f..ae2baec731b5fcd8be97f2177d23b860d67ab8bc 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
@@ -93,6 +93,8 @@ class VIEWS_EXPORT DesktopWindowTreeHostWin

View File

@@ -0,0 +1,285 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: John Kleinschmidt <jkleinsc@electronjs.org>
Date: Sat, 14 Jun 2025 16:21:07 -0400
Subject: Revert "[views] Remove DesktopWindowTreeHostWin::window_enlargement_"
This reverts commit 1771dbae6961e7bb7c22bbc6c77f84d90ef2be46.
Electron needs this patch to allow windows smaller than 64x64
on Windows. We should refactor our code so that this patch isn't
necessary.
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 988866d79a5d1dbd366ebdbff0e8eb2c0c498168..5761ac48be0a64618be0a94606149dd944e46e27 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -22626,6 +22626,21 @@
]
}
],
+ "TransparentHwndEnlargement": [
+ {
+ "platforms": [
+ "windows"
+ ],
+ "experiments": [
+ {
+ "name": "DisableTransparentHwndEnlargement",
+ "disable_features": [
+ "EnableTransparentHwndEnlargement"
+ ]
+ }
+ ]
+ }
+ ],
"TransportSecurityFileWriterScheduleAndroid": [
{
"platforms": [
diff --git a/ui/views/views_features.cc b/ui/views/views_features.cc
index 47077e16870889ef8f8c8b2adf58015bd5aff7fa..ba59e6e1609e61579bf49aca095490b083d72051 100644
--- a/ui/views/views_features.cc
+++ b/ui/views/views_features.cc
@@ -30,6 +30,14 @@ BASE_FEATURE(kEnableInputProtection, base::FEATURE_DISABLED_BY_DEFAULT);
// crbug.com/370856871.
BASE_FEATURE(kEnableTouchDragCursorSync, base::FEATURE_ENABLED_BY_DEFAULT);
+// Enables enlargement of HWNDs to a minimum size of 64x64 to handle reported
+// graphical glitches on certain hardware.
+// TODO(crbug.com/401996981): Remove this once enlargement is confirmed to no
+// longer be needed.
+BASE_FEATURE(kEnableTransparentHwndEnlargement,
+ "EnableTransparentHwndEnlargement",
+ base::FEATURE_DISABLED_BY_DEFAULT);
+
// Used to enable keyboard-accessible tooltips in Views UI, as opposed
// to kKeyboardAccessibleTooltip in //ui/base/ui_base_features.cc.
BASE_FEATURE(kKeyboardAccessibleTooltipInViews,
diff --git a/ui/views/views_features.h b/ui/views/views_features.h
index 888a16fb6213eceb131ae636dc643d7f2d5bcad9..6077412165081cd4abeaf0b061feb2f795ee8131 100644
--- a/ui/views/views_features.h
+++ b/ui/views/views_features.h
@@ -15,6 +15,7 @@ namespace views::features {
VIEWS_EXPORT BASE_DECLARE_FEATURE(kApplyInitialUrlToWebContents);
VIEWS_EXPORT BASE_DECLARE_FEATURE(kEnableInputProtection);
VIEWS_EXPORT BASE_DECLARE_FEATURE(kEnableTouchDragCursorSync);
+VIEWS_EXPORT BASE_DECLARE_FEATURE(kEnableTransparentHwndEnlargement);
VIEWS_EXPORT BASE_DECLARE_FEATURE(kKeyboardAccessibleTooltipInViews);
} // namespace views::features
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
index e4da40256ce94d6a0896792a8ef2faa18e1fa5d2..d1e06b675b19226cf3b78e1aada8d8f2d684fada 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
@@ -85,6 +85,23 @@ namespace {
// This constant controls how many pixels wide that border is.
const int kMouseCaptureRegionBorder = 5;
+gfx::Size GetExpandedWindowSize(bool is_translucent, gfx::Size size) {
+ if (!base::FeatureList::IsEnabled(
+ features::kEnableTransparentHwndEnlargement) ||
+ !is_translucent) {
+ return size;
+ }
+
+ // Some AMD drivers can't display windows that are less than 64x64 pixels,
+ // so expand them to be at least that size. http://crbug.com/286609
+ gfx::Size expanded(std::max(size.width(), 64), std::max(size.height(), 64));
+ return expanded;
+}
+
+void InsetBottomRight(gfx::Rect* rect, const gfx::Vector2d& vector) {
+ rect->Inset(gfx::Insets::TLBR(0, 0, vector.y(), vector.x()));
+}
+
// Updates the cursor clip region. Used for mouse locking.
void UpdateMouseLockRegion(aura::Window* window, bool locked) {
if (!locked) {
@@ -342,9 +359,14 @@ bool DesktopWindowTreeHostWin::IsVisible() const {
}
void DesktopWindowTreeHostWin::SetSize(const gfx::Size& size) {
- const gfx::Size size_in_pixels =
+ gfx::Size size_in_pixels =
display::win::GetScreenWin()->DIPToScreenSize(GetHWND(), size);
- message_handler_->SetSize(size_in_pixels);
+ gfx::Size expanded =
+ GetExpandedWindowSize(message_handler_->is_translucent(), size_in_pixels);
+ window_enlargement_ =
+ gfx::Vector2d(expanded.width() - size_in_pixels.width(),
+ expanded.height() - size_in_pixels.height());
+ message_handler_->SetSize(expanded);
}
void DesktopWindowTreeHostWin::StackAbove(aura::Window* window) {
@@ -359,30 +381,40 @@ void DesktopWindowTreeHostWin::StackAtTop() {
}
void DesktopWindowTreeHostWin::CenterWindow(const gfx::Size& size) {
- const gfx::Size size_in_pixels =
+ gfx::Size size_in_pixels =
display::win::GetScreenWin()->DIPToScreenSize(GetHWND(), size);
- message_handler_->CenterWindow(size_in_pixels);
+ gfx::Size expanded_size;
+ expanded_size =
+ GetExpandedWindowSize(message_handler_->is_translucent(), size_in_pixels);
+ window_enlargement_ =
+ gfx::Vector2d(expanded_size.width() - size_in_pixels.width(),
+ expanded_size.height() - size_in_pixels.height());
+ message_handler_->CenterWindow(expanded_size);
}
void DesktopWindowTreeHostWin::GetWindowPlacement(
gfx::Rect* bounds,
ui::mojom::WindowShowState* show_state) const {
message_handler_->GetWindowPlacement(bounds, show_state);
+ InsetBottomRight(bounds, window_enlargement_);
*bounds = display::win::GetScreenWin()->ScreenToDIPRect(GetHWND(), *bounds);
}
gfx::Rect DesktopWindowTreeHostWin::GetWindowBoundsInScreen() const {
gfx::Rect pixel_bounds = message_handler_->GetWindowBoundsInScreen();
+ InsetBottomRight(&pixel_bounds, window_enlargement_);
return display::win::GetScreenWin()->ScreenToDIPRect(GetHWND(), pixel_bounds);
}
gfx::Rect DesktopWindowTreeHostWin::GetClientAreaBoundsInScreen() const {
gfx::Rect pixel_bounds = message_handler_->GetClientAreaBoundsInScreen();
+ InsetBottomRight(&pixel_bounds, window_enlargement_);
return display::win::GetScreenWin()->ScreenToDIPRect(GetHWND(), pixel_bounds);
}
gfx::Rect DesktopWindowTreeHostWin::GetRestoredBounds() const {
gfx::Rect pixel_bounds = message_handler_->GetRestoredBounds();
+ InsetBottomRight(&pixel_bounds, window_enlargement_);
return display::win::GetScreenWin()->ScreenToDIPRect(GetHWND(), pixel_bounds);
}
@@ -701,37 +733,44 @@ void DesktopWindowTreeHostWin::HideImpl() {
// other get/set methods work in DIP.
gfx::Rect DesktopWindowTreeHostWin::GetBoundsInPixels() const {
- const gfx::Rect bounds_px(message_handler_->GetClientAreaBounds());
+ gfx::Rect bounds(message_handler_->GetClientAreaBounds());
// If the window bounds were expanded we need to return the original bounds
// To achieve this we do the reverse of the expansion, i.e. add the
// window_expansion_top_left_delta_ to the origin and subtract the
// window_expansion_bottom_right_delta_ from the width and height.
- const gfx::Rect without_expansion_bounds_px(
- bounds_px.x() + window_expansion_top_left_delta_.x(),
- bounds_px.y() + window_expansion_top_left_delta_.y(),
- bounds_px.width() - window_expansion_bottom_right_delta_.x(),
- bounds_px.height() - window_expansion_bottom_right_delta_.y());
- return without_expansion_bounds_px;
+ gfx::Rect without_expansion(
+ bounds.x() + window_expansion_top_left_delta_.x(),
+ bounds.y() + window_expansion_top_left_delta_.y(),
+ bounds.width() - window_expansion_bottom_right_delta_.x() -
+ window_enlargement_.x(),
+ bounds.height() - window_expansion_bottom_right_delta_.y() -
+ window_enlargement_.y());
+ return without_expansion;
}
-void DesktopWindowTreeHostWin::SetBoundsInPixels(
- const gfx::Rect& bounds_in_pixels) {
+void DesktopWindowTreeHostWin::SetBoundsInPixels(const gfx::Rect& bounds) {
// If the window bounds have to be expanded we need to subtract the
// window_expansion_top_left_delta_ from the origin and add the
// window_expansion_bottom_right_delta_ to the width and height
- const gfx::Size old_content_size_px = GetBoundsInPixels().size();
-
- const gfx::Rect expanded_bounds_px(
- bounds_in_pixels.x() - window_expansion_top_left_delta_.x(),
- bounds_in_pixels.y() - window_expansion_top_left_delta_.y(),
- bounds_in_pixels.width() + window_expansion_bottom_right_delta_.x(),
- bounds_in_pixels.height() + window_expansion_bottom_right_delta_.y());
-
- // When `expanded_bounds_px` causes the window to be moved to a display with a
+ gfx::Size old_content_size = GetBoundsInPixels().size();
+
+ gfx::Rect expanded(
+ bounds.x() - window_expansion_top_left_delta_.x(),
+ bounds.y() - window_expansion_top_left_delta_.y(),
+ bounds.width() + window_expansion_bottom_right_delta_.x(),
+ bounds.height() + window_expansion_bottom_right_delta_.y());
+
+ gfx::Rect new_expanded(
+ expanded.origin(),
+ GetExpandedWindowSize(message_handler_->is_translucent(),
+ expanded.size()));
+ window_enlargement_ =
+ gfx::Vector2d(new_expanded.width() - expanded.width(),
+ new_expanded.height() - expanded.height());
+ // When |new_expanded| causes the window to be moved to a display with a
// different DSF, HWNDMessageHandler::OnDpiChanged() will be called and the
// window size will be scaled automatically.
- message_handler_->SetBounds(expanded_bounds_px,
- old_content_size_px != bounds_in_pixels.size());
+ message_handler_->SetBounds(new_expanded, old_content_size != bounds.size());
}
gfx::Rect
@@ -943,18 +982,26 @@ int DesktopWindowTreeHostWin::GetNonClientComponent(
void DesktopWindowTreeHostWin::GetWindowMask(const gfx::Size& size_px,
SkPath* path) {
- Widget* widget = GetWidget();
- if (!widget || !widget->non_client_view()) {
- return;
- }
+ // Request the window mask for hwnd of `size_px`. The hwnd size must be
+ // adjusted by `window_enlargement` to return to the client-expected window
+ // size (see crbug.com/41047830).
+ const gfx::Size adjusted_size_in_px =
+ size_px - gfx::Size(window_enlargement_.x(), window_enlargement_.y());
- widget->non_client_view()->GetWindowMask(
- display::win::GetScreenWin()->ScreenToDIPSize(GetHWND(), size_px), path);
- // Convert path in DIPs to pixels.
- if (!path->isEmpty()) {
- const float scale =
- display::win::GetScreenWin()->GetScaleFactorForHWND(GetHWND());
- *path = path->makeTransform(SkMatrix::Scale(scale, scale));
+ if (Widget* widget = GetWidget(); widget && widget->non_client_view()) {
+ widget->non_client_view()->GetWindowMask(
+ display::win::GetScreenWin()->ScreenToDIPSize(GetHWND(),
+ adjusted_size_in_px),
+ path);
+ // Convert path in DIPs to pixels.
+ if (!path->isEmpty()) {
+ const float scale =
+ display::win::GetScreenWin()->GetScaleFactorForHWND(GetHWND());
+ *path = path->makeTransform(SkMatrix::Scale(scale, scale));
+ }
+ } else if (!window_enlargement_.IsZero()) {
+ *path = SkPath::Rect(SkRect::MakeXYWH(0, 0, adjusted_size_in_px.width(),
+ adjusted_size_in_px.height()));
}
}
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
index 27322ef34edf3fa8bfbd20b1baddcaf3b7555618..a40bd9f25fa07a553c011cf19f155f8158f4ae5f 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
@@ -175,7 +175,7 @@ class VIEWS_EXPORT DesktopWindowTreeHostWin
void ShowImpl() override;
void HideImpl() override;
gfx::Rect GetBoundsInPixels() const override;
- void SetBoundsInPixels(const gfx::Rect& bounds_in_pixels) override;
+ void SetBoundsInPixels(const gfx::Rect& bounds) override;
gfx::Rect GetBoundsInAcceleratedWidgetPixelCoordinates() override;
gfx::Point GetLocationOnScreenInPixels() const override;
void SetCapture() override;
@@ -330,6 +330,12 @@ class VIEWS_EXPORT DesktopWindowTreeHostWin
gfx::Vector2d window_expansion_top_left_delta_;
gfx::Vector2d window_expansion_bottom_right_delta_;
+ // Windows are enlarged to be at least 64x64 pixels, so keep track of the
+ // extra added here.
+ // TODO(crbug.com/401996981): This is likely no longer necessary and should be
+ // removed.
+ gfx::Vector2d window_enlargement_;
+
// Whether the window close should be converted to a hide, and then actually
// closed on the completion of the hide animation. This is cached because
// the property is set on the contained window which has a shorter lifetime.

View File

@@ -2889,8 +2889,8 @@ v8::Local<v8::Promise> WebContents::SavePage(
return handle;
}
auto* handler = new SavePageHandler{std::move(promise)};
handler->Handle(full_file_path, save_type, web_contents());
auto* handler = new SavePageHandler(web_contents(), std::move(promise));
handler->Handle(full_file_path, save_type);
return handle;
}

View File

@@ -12,8 +12,9 @@
namespace electron::api {
SavePageHandler::SavePageHandler(gin_helper::Promise<void> promise)
: promise_{std::move(promise)} {}
SavePageHandler::SavePageHandler(content::WebContents* web_contents,
gin_helper::Promise<void> promise)
: web_contents_(web_contents), promise_(std::move(promise)) {}
SavePageHandler::~SavePageHandler() = default;
@@ -25,10 +26,9 @@ void SavePageHandler::OnDownloadCreated(content::DownloadManager* manager,
}
bool SavePageHandler::Handle(const base::FilePath& full_path,
const content::SavePageType& save_type,
content::WebContents* web_contents) {
const content::SavePageType& save_type) {
auto* download_manager =
web_contents->GetBrowserContext()->GetDownloadManager();
web_contents_->GetBrowserContext()->GetDownloadManager();
download_manager->AddObserver(this);
// Chromium will create a 'foo_files' directory under the directory of saving
// page 'foo.html' for holding other resource files of 'foo.html'.
@@ -36,7 +36,7 @@ bool SavePageHandler::Handle(const base::FilePath& full_path,
full_path.RemoveExtension().BaseName().value() +
FILE_PATH_LITERAL("_files"));
bool result =
web_contents->SavePage(full_path, saved_main_directory_path, save_type);
web_contents_->SavePage(full_path, saved_main_directory_path, save_type);
download_manager->RemoveObserver(this);
// If initialization fails which means fail to create |DownloadItem|, we need
// to delete the |SavePageHandler| instance to avoid memory-leak.

View File

@@ -5,6 +5,7 @@
#ifndef ELECTRON_SHELL_BROWSER_API_SAVE_PAGE_HANDLER_H_
#define ELECTRON_SHELL_BROWSER_API_SAVE_PAGE_HANDLER_H_
#include "base/memory/raw_ptr.h"
#include "components/download/public/common/download_item.h"
#include "content/public/browser/download_manager.h"
#include "content/public/browser/save_page_type.h"
@@ -25,12 +26,12 @@ namespace electron::api {
class SavePageHandler : private content::DownloadManager::Observer,
private download::DownloadItem::Observer {
public:
explicit SavePageHandler(gin_helper::Promise<void> promise);
SavePageHandler(content::WebContents* web_contents,
gin_helper::Promise<void> promise);
~SavePageHandler() override;
bool Handle(const base::FilePath& full_path,
const content::SavePageType& save_type,
content::WebContents* web_contents);
const content::SavePageType& save_type);
private:
void Destroy(download::DownloadItem* item);
@@ -42,6 +43,7 @@ class SavePageHandler : private content::DownloadManager::Observer,
// download::DownloadItem::Observer:
void OnDownloadUpdated(download::DownloadItem* item) override;
raw_ptr<content::WebContents> web_contents_; // weak
gin_helper::Promise<void> promise_;
};

View File

@@ -63,7 +63,6 @@
#include "mojo/public/cpp/bindings/self_owned_associated_receiver.h"
#include "net/ssl/ssl_cert_request_info.h"
#include "net/ssl/ssl_private_key.h"
#include "pdf/pdf_features.h"
#include "printing/buildflags/buildflags.h"
#include "services/device/public/cpp/geolocation/geolocation_system_permission_manager.h"
#include "services/device/public/cpp/geolocation/location_provider.h"
@@ -1358,7 +1357,11 @@ void ElectronBrowserClient::WillCreateURLLoaderFactory(
DCHECK(web_request);
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
if (!web_request->HasListener()) {
// If Electron's webRequest API has no listeners, proxy requests using
// chrome.webRequest extension APIs.
// Note that Electron's net.fetch and protocol.handle APIs do not include the
// frame host which is required for proxying requests.
if (!web_request->HasListener() && frame_host) {
auto* web_request_api = extensions::BrowserContextKeyedAPIFactory<
extensions::WebRequestAPI>::Get(browser_context);
@@ -1592,46 +1595,6 @@ bool ElectronBrowserClient::ShouldEnableStrictSiteIsolation() {
return true;
}
bool ElectronBrowserClient::ShouldEnableSubframeZoom() {
#if BUILDFLAG(ENABLE_PDF_VIEWER)
return chrome_pdf::features::IsOopifPdfEnabled();
#else
return false;
#endif
}
#if BUILDFLAG(ENABLE_PDF_VIEWER)
std::optional<network::CrossOriginEmbedderPolicy>
ElectronBrowserClient::MaybeOverrideLocalURLCrossOriginEmbedderPolicy(
content::NavigationHandle* navigation_handle) {
if (!chrome_pdf::features::IsOopifPdfEnabled() ||
!navigation_handle->IsPdf()) {
return std::nullopt;
}
content::RenderFrameHost* pdf_extension = navigation_handle->GetParentFrame();
if (!pdf_extension) {
return std::nullopt;
}
content::RenderFrameHost* pdf_embedder = pdf_extension->GetParent();
CHECK(pdf_embedder);
return pdf_embedder->GetCrossOriginEmbedderPolicy();
}
#endif // BUILDFLAG(ENABLE_PDF_VIEWER)
bool ElectronBrowserClient::DoesSiteRequireDedicatedProcess(
content::BrowserContext* browser_context,
const GURL& effective_site_url) {
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
return GetEnabledExtensionFromEffectiveURL(browser_context,
effective_site_url) != nullptr;
#else
return content::ContentBrowserClient::DoesSiteRequireDedicatedProcess(
browser_context, effective_site_url);
#endif
}
void ElectronBrowserClient::BindHostReceiverForRenderer(
content::RenderProcessHost* render_process_host,
mojo::GenericPendingReceiver receiver) {

View File

@@ -30,7 +30,6 @@ class FilePath;
namespace content {
class ClientCertificateDelegate;
class NavigationHandle;
class PlatformNotificationService;
class NavigationThrottleRegistry;
class QuotaPermissionContext;
@@ -83,14 +82,6 @@ class ElectronBrowserClient : public content::ContentBrowserClient,
// content::ContentBrowserClient:
std::string GetApplicationLocale() override;
bool ShouldEnableStrictSiteIsolation() override;
bool ShouldEnableSubframeZoom() override;
#if BUILDFLAG(ENABLE_PDF_VIEWER)
std::optional<network::CrossOriginEmbedderPolicy>
MaybeOverrideLocalURLCrossOriginEmbedderPolicy(
content::NavigationHandle* navigation_handle) override;
#endif // BUILDFLAG(ENABLE_PDF_VIEWER)
bool DoesSiteRequireDedicatedProcess(content::BrowserContext* browser_context,
const GURL& effective_site_url) override;
void BindHostReceiverForRenderer(
content::RenderProcessHost* render_process_host,
mojo::GenericPendingReceiver receiver) override;

View File

@@ -71,7 +71,7 @@ void StreamsPrivateAPI::SendExecuteMimeTypeHandlerEvent(
std::move(transferrable_loader), original_url);
#if BUILDFLAG(ENABLE_PDF_VIEWER)
if (chrome_pdf::features::IsOopifPdfEnabled() &&
if (base::FeatureList::IsEnabled(chrome_pdf::features::kPdfOopif) &&
extension_id == extension_misc::kPdfExtensionId) {
pdf::PdfViewerStreamManager::Create(web_contents);
pdf::PdfViewerStreamManager::FromWebContents(web_contents)

View File

@@ -34,6 +34,10 @@
#include "printing/printing_features.h"
#endif
#if BUILDFLAG(IS_WIN)
#include "ui/views/views_features.h"
#endif
namespace electron {
void InitializeFeatureList() {
@@ -67,6 +71,13 @@ void InitializeFeatureList() {
blink::features::kDropInputEventsWhilePaintHolding.name;
#if BUILDFLAG(IS_WIN)
// Refs https://issues.chromium.org/issues/401996981
// TODO(deepak1556): Remove this once test added in
// https://github.com/electron/electron/pull/12904
// can work without this feature.
enable_features += std::string(",") +
views::features::kEnableTransparentHwndEnlargement.name;
// See https://chromium-review.googlesource.com/c/chromium/src/+/7204292
// This feature causes the following sandbox failure on Windows:
// sandbox\policy\win\sandbox_win.cc:777 Sandbox cannot access executable

View File

@@ -31,6 +31,11 @@
#include "shell/browser/ui/views/frameless_view.h"
#endif
#if BUILDFLAG(IS_WIN)
#include "ui/display/win/screen_win.h"
#include "ui/views/views_features.h"
#endif
#if defined(USE_OZONE)
#include "ui/base/ui_base_features.h"
#include "ui/ozone/public/ozone_platform.h"
@@ -66,6 +71,31 @@ struct Converter<electron::NativeWindow::TitleBarStyle> {
namespace electron {
namespace {
#if BUILDFLAG(IS_WIN)
gfx::Size GetExpandedWindowSize(const NativeWindow* window,
bool transparent,
gfx::Size size) {
if (!base::FeatureList::IsEnabled(
views::features::kEnableTransparentHwndEnlargement) ||
!transparent) {
return size;
}
gfx::Size min_size = display::win::GetScreenWin()->ScreenToDIPSize(
window->GetAcceleratedWidget(), gfx::Size{64, 64});
// Some AMD drivers can't display windows that are less than 64x64 pixels,
// so expand them to be at least that size. http://crbug.com/286609
gfx::Size expanded(std::max(size.width(), min_size.width()),
std::max(size.height(), min_size.height()));
return expanded;
}
#endif
} // namespace
NativeWindow::NativeWindow(const int32_t base_window_id,
const gin_helper::Dictionary& options,
NativeWindow* parent)
@@ -368,7 +398,15 @@ gfx::Size NativeWindow::GetContentMinimumSize() const {
}
gfx::Size NativeWindow::GetContentMaximumSize() const {
return GetContentSizeConstraints().GetMaximumSize();
const auto size_constraints = GetContentSizeConstraints();
gfx::Size maximum_size = size_constraints.GetMaximumSize();
#if BUILDFLAG(IS_WIN)
if (size_constraints.HasMaximumSize())
maximum_size = GetExpandedWindowSize(this, transparent(), maximum_size);
#endif
return maximum_size;
}
void NativeWindow::SetSheetOffset(const double offsetX, const double offsetY) {

View File

@@ -106,19 +106,29 @@ int WinFrameView::NonClientHitTest(const gfx::Point& point) {
if (SUCCEEDED(DwmGetWindowAttribute(
views::HWNDForWidget(frame()), DWMWA_CAPTION_BUTTON_BOUNDS,
&button_bounds, sizeof(button_bounds)))) {
gfx::Rect button_bounds_px(button_bounds);
// There is a small one-pixel strip right above the caption buttons in
// which the resize border "peeks" through. Inset in physical pixels
// before converting to DIPs so the resize strip remains exposed at
// fractional scale factors.
button_bounds_px.Inset(gfx::Insets::TLBR(1, 0, 0, 0));
const gfx::RectF button_bounds_in_dips =
gfx::ConvertRectToDips(button_bounds_px, display::win::GetDPIScale());
// GetMirroredRect() requires an integer rect. Use ToEnclosedRect() so
// the top inset is preserved (rounded up) at fractional scale factors.
gfx::RectF button_bounds_in_dips = gfx::ConvertRectToDips(
gfx::Rect(button_bounds), display::win::GetDPIScale());
// TODO(crbug.com/1131681): GetMirroredRect() requires an integer rect,
// but the size in DIPs may not be an integer with a fractional device
// scale factor. If we want to keep using integers, the choice to use
// ToFlooredRectDeprecated() seems to be doing the wrong thing given the
// comment below about insetting 1 DIP instead of 1 physical pixel. We
// should probably use ToEnclosedRect() and then we could have inset 1
// physical pixel here.
gfx::Rect buttons =
GetMirroredRect(gfx::ToEnclosedRect(button_bounds_in_dips));
GetMirroredRect(gfx::ToFlooredRectDeprecated(button_bounds_in_dips));
// There is a small one-pixel strip right above the caption buttons in
// which the resize border "peeks" through.
constexpr int kCaptionButtonTopInset = 1;
// The sizing region at the window edge above the caption buttons is
// 1 px regardless of scale factor. If we inset by 1 before converting
// to DIPs, the precision loss might eliminate this region entirely. The
// best we can do is to inset after conversion. This guarantees we'll
// show the resize cursor when resizing is possible. The cost of which
// is also maybe showing it over the portion of the DIP that isn't the
// outermost pixel.
buttons.Inset(gfx::Insets::TLBR(0, kCaptionButtonTopInset, 0, 0));
if (buttons.Contains(point))
return HTNOWHERE;
}

View File

@@ -5641,6 +5641,21 @@ describe('BrowserWindow module', () => {
expectBoundsEqual(w.getSize(), [400, 300]);
});
ifit(process.platform !== 'darwin')('works for a window smaller than 64x64', () => {
const w = new BrowserWindow({
show: false,
frame: false,
resizable: false,
transparent: true
});
w.setContentSize(60, 60);
expectBoundsEqual(w.getContentSize(), [60, 60]);
w.setContentSize(30, 30);
expectBoundsEqual(w.getContentSize(), [30, 30]);
w.setContentSize(10, 10);
expectBoundsEqual(w.getContentSize(), [10, 10]);
});
ifit(process.platform === 'win32')('do not change window with frame bounds when maximized', () => {
const w = new BrowserWindow({
show: true,

View File

@@ -1,4 +1,4 @@
import { app, session, webFrameMain, BrowserWindow, ipcMain, WebContents, Extension, Session, ServiceWorkerInfo, ServiceWorkersRunningStatusChangedEventParams } from 'electron/main';
import { app, session, webFrameMain, BrowserWindow, ipcMain, net, WebContents, Extension, Session, ServiceWorkerInfo, ServiceWorkersRunningStatusChangedEventParams } from 'electron/main';
import { expect } from 'chai';
import * as WebSocket from 'ws';
@@ -434,6 +434,12 @@ describe('chrome extensions', () => {
});
});
});
it('does not crash when net.fetch is called', async () => {
await session.defaultSession.loadExtension(path.join(fixtures, 'extensions', 'chrome-webRequest-non-blocking'));
const requestUrl = `${url}/test.zip`;
await net.fetch(requestUrl);
});
});
describe('chrome.tabs', () => {

View File

@@ -0,0 +1,9 @@
/* global chrome */
chrome.webRequest.onBeforeRequest.addListener(
// eslint-disable-next-line @typescript-eslint/no-unused-vars
(details) => {
console.log(details);
},
{ urls: ['<all_urls>'] }
);

View File

@@ -0,0 +1,10 @@
{
"name": "chrome-webRequest-non-blocking",
"version": "1.0",
"background": {
"service_worker": "background.js"
},
"permissions": ["webRequest"],
"manifest_version": 3,
"host_permissions": ["<all_urls>"]
}