Files
cromite/build/patches/Viewport-Protection-flag.patch

892 lines
40 KiB
Diff

From: uazo <uazo@users.noreply.github.com>
Date: Tue, 20 Dec 2022 11:06:42 +0000
Subject: Viewport Protection flag
Scale the viewport and the screen by a random factor to
prevent coordinate-based fingerprinting scripts.
The factor is changed at each change of origin.
The feature is controlled by a feature flag (default enabled)
Require: Content-settings-infrastructure.patch
---
.../impl/BromiteViewportContentSetting.java | 94 ++++++++++++++++++
.../bromite_content_settings/viewport.grdp | 27 ++++++
.../bromite_content_settings/viewport.inc | 22 +++++
.../bromite_content_settings/VIEWPORT.inc | 1 +
.../guest_view/browser/guest_view_base.cc | 8 ++
.../Viewport-Protection-flag.inc | 10 ++
.../features_cc/Viewport-Protection-flag.inc | 3 +
.../features_h/Viewport-Protection-flag.inc | 2 +
.../common/widget/device_emulation_params.h | 6 +-
.../renderer/core/css/css_properties.json5 | 2 +-
.../blink/renderer/core/css/media_values.cc | 2 +-
.../core/css/resolver/style_resolver.cc | 7 +-
.../blink/renderer/core/events/mouse_event.h | 19 +++-
.../renderer/core/events/pointer_event.h | 11 +++
.../renderer/core/exported/web_view_impl.cc | 2 +-
.../renderer/core/frame/local_dom_window.cc | 43 ++++++++-
.../blink/renderer/core/frame/local_frame.cc | 17 +++-
.../blink/renderer/core/frame/local_frame.h | 6 +-
.../core/frame/screen_metrics_emulator.cc | 18 +++-
.../core/frame/screen_metrics_emulator.h | 14 +++
.../core/frame/web_frame_widget_impl.cc | 9 ++
.../core/frame/web_remote_frame_impl.cc | 3 +-
.../blink/renderer/core/input/touch.cc | 17 +++-
third_party/blink/renderer/core/page/page.cc | 96 +++++++++++++++++++
third_party/blink/renderer/core/page/page.h | 9 ++
.../renderer/core/style/computed_style.h | 6 ++
26 files changed, 434 insertions(+), 20 deletions(-)
create mode 100644 components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/impl/BromiteViewportContentSetting.java
create mode 100644 components/browser_ui/strings/bromite_content_settings/viewport.grdp
create mode 100644 components/content_settings/core/browser/bromite_content_settings/viewport.inc
create mode 100644 components/content_settings/core/common/bromite_content_settings/VIEWPORT.inc
create mode 100644 cromite_flags/chrome/browser/about_flags_cc/Viewport-Protection-flag.inc
create mode 100644 cromite_flags/third_party/blink/common/features_cc/Viewport-Protection-flag.inc
create mode 100644 cromite_flags/third_party/blink/common/features_h/Viewport-Protection-flag.inc
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/impl/BromiteViewportContentSetting.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/impl/BromiteViewportContentSetting.java
new file mode 100644
--- /dev/null
+++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/impl/BromiteViewportContentSetting.java
@@ -0,0 +1,94 @@
+/*
+ This file is part of Bromite.
+
+ Bromite is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Bromite is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Bromite. If not, see <https://www.gnu.org/licenses/>.
+*/
+
+package org.chromium.components.browser_ui.site_settings.impl;
+
+import org.chromium.components.browser_ui.site_settings.R;
+
+import org.chromium.components.browser_ui.site_settings.BromiteCustomContentSetting;
+import org.chromium.components.browser_ui.site_settings.ContentSettingsResources;
+import org.chromium.components.browser_ui.site_settings.SiteSettingsCategory;
+import org.chromium.components.content_settings.ContentSetting;
+import org.chromium.components.content_settings.ContentSettingsType;
+import org.chromium.content_public.browser.BrowserContextHandle;
+
+import androidx.annotation.Nullable;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import java.util.ArrayList;
+
+public class BromiteViewportContentSetting extends BromiteCustomContentSetting {
+ public BromiteViewportContentSetting() {
+ super(/*contentSettingsType*/ ContentSettingsType.VIEWPORT,
+ /*defaultEnabledValue*/ ContentSetting.ALLOW,
+ /*defaultDisabledValue*/ ContentSetting.BLOCK,
+ /*allowException*/ true,
+ /*preferenceKey*/ "viewport",
+ /*profilePrefKey*/ "viewport");
+ }
+
+ @Override
+ public ContentSettingsResources.ResourceItem getResourceItem() {
+ return new ContentSettingsResources.ResourceItem(
+ /*icon*/ R.drawable.web_asset,
+ /*title*/ R.string.viewport_permission_title,
+ /*defaultEnabledValue*/ getDefaultEnabledValue(),
+ /*defaultDisabledValue*/ getDefaultDisabledValue(),
+ /*enabledSummary*/ R.string.website_settings_category_viewport_enabled,
+ /*disabledSummary*/ R.string.website_settings_category_viewport_disabled,
+ /*summaryOverrideForScreenReader*/ 0);
+ }
+
+ @Override
+ public int getCategorySummary(@Nullable @ContentSetting int value) {
+ switch (value) {
+ case ContentSetting.ALLOW:
+ return R.string.website_settings_category_viewport_enabled;
+ case ContentSetting.BLOCK:
+ return R.string.website_settings_category_viewport_disabled;
+ default:
+ // this will cause a runtime exception
+ return 0;
+ }
+ }
+
+ @Override
+ public int getCategoryDescription() {
+ return R.string.settings_site_settings_viewport_protection_description;
+ }
+
+ @Override
+ public boolean requiresTriStateContentSetting() {
+ return false;
+ }
+
+ @Override
+ public boolean showOnlyDescriptions() {
+ return true;
+ }
+
+ @Override
+ public int getAddExceptionDialogMessage() {
+ return R.string.website_settings_category_viewport_enabled;
+ }
+
+ @Override
+ public @Nullable Boolean considerException(SiteSettingsCategory category, @ContentSetting int value) {
+ return value != ContentSetting.BLOCK;
+ }
+}
diff --git a/components/browser_ui/strings/bromite_content_settings/viewport.grdp b/components/browser_ui/strings/bromite_content_settings/viewport.grdp
new file mode 100644
--- /dev/null
+++ b/components/browser_ui/strings/bromite_content_settings/viewport.grdp
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<grit-part>
+ <message name="IDS_SITE_SETTINGS_TYPE_VIEWPORT" desc="The label used for viewport size change site settings controls." formatter_data="android_java">
+ Viewport Size Protection
+ </message>
+ <message name="IDS_VIEWPORT_PERMISSION_TITLE" desc="Title of the permission to use viewport size change [CHAR-LIMIT=32]" formatter_data="android_java">
+ Viewport Size Protection
+ </message>
+ <message name="IDS_SITE_SETTINGS_TYPE_VIEWPORT_MID_SENTENCE" desc="The label used for viewport size change site settings controls when used mid-sentence." formatter_data="android_java">
+ Viewport Size Protection
+ </message>
+ <message name="IDS_SETTINGS_SITE_SETTINGS_VIEWPORT_PROTECTION_DESCRIPTION" desc="Description of the viewport protection content setting." formatter_data="android_java">
+ Hides the screen size by randomly changing the values for each website
+ </message>
+ <message name="IDS_WEBSITE_SETTINGS_CATEGORY_VIEWPORT_ENABLED" desc="Summary text explaining that viewport size change is full enabled." formatter_data="android_java">
+ Enabled
+ </message>
+ <message name="IDS_WEBSITE_SETTINGS_CATEGORY_VIEWPORT_DISABLED" desc="Summary text explaining that viewport size change is full disabled." formatter_data="android_java">
+ Disabled
+ </message>
+ <message name="IDS_SETTINGS_SITE_SETTINGS_VIEWPORT_PROTECTION_ALLOWED_EXCEPTIONS" desc="Label for the allowed exceptions site list of the viewport protection setting.">
+ Viewport Protection is enabled with these websites
+ </message>
+ <message name="IDS_SETTINGS_SITE_SETTINGS_VIEWPORT_PROTECTION_BLOCKED_EXCEPTIONS" desc="Label for the blocked exceptions site list of the viewport protection setting.">
+ Not allowed to use Viewport Protection
+ </message>
+</grit-part>
diff --git a/components/content_settings/core/browser/bromite_content_settings/viewport.inc b/components/content_settings/core/browser/bromite_content_settings/viewport.inc
new file mode 100644
--- /dev/null
+++ b/components/content_settings/core/browser/bromite_content_settings/viewport.inc
@@ -0,0 +1,22 @@
+ Register(ContentSettingsType::VIEWPORT, "viewport", CONTENT_SETTING_ALLOW,
+ WebsiteSettingsInfo::SYNCABLE,
+ /*allowlisted_schemes=*/{},
+ /*valid_settings=*/{CONTENT_SETTING_ALLOW,
+ CONTENT_SETTING_BLOCK},
+ WebsiteSettingsInfo::TOP_ORIGIN_ONLY_SCOPE,
+ WebsiteSettingsRegistry::ALL_PLATFORMS,
+ ContentSettingsInfo::INHERIT_IN_INCOGNITO,
+ PermissionSettingsInfo::EXCEPTIONS_ON_SECURE_AND_INSECURE_ORIGINS);
+
+ content_settings::WebsiteSettingsRegistry::GetInstance()
+ ->GetMutable(ContentSettingsType::VIEWPORT)
+ ->set_show_into_info_page()
+ .set_desktop_ui()
+ .set_is_renderer_content_setting()
+ .set_title_ui(IDS_SITE_SETTINGS_TYPE_VIEWPORT)
+ .set_description_ui(IDS_SETTINGS_SITE_SETTINGS_VIEWPORT_PROTECTION_DESCRIPTION)
+ .set_allowed_ui(IDS_WEBSITE_SETTINGS_CATEGORY_VIEWPORT_ENABLED)
+ .set_blocked_ui(IDS_WEBSITE_SETTINGS_CATEGORY_VIEWPORT_DISABLED)
+ .set_allowed_exceptions_ui(IDS_SETTINGS_SITE_SETTINGS_VIEWPORT_PROTECTION_ALLOWED_EXCEPTIONS)
+ .set_blocked_exceptions_ui(IDS_SETTINGS_SITE_SETTINGS_VIEWPORT_PROTECTION_BLOCKED_EXCEPTIONS)
+ .set_mid_sentence_ui(IDS_SITE_SETTINGS_TYPE_VIEWPORT_MID_SENTENCE);
diff --git a/components/content_settings/core/common/bromite_content_settings/VIEWPORT.inc b/components/content_settings/core/common/bromite_content_settings/VIEWPORT.inc
new file mode 100644
--- /dev/null
+++ b/components/content_settings/core/common/bromite_content_settings/VIEWPORT.inc
@@ -0,0 +1 @@
+ VIEWPORT,
diff --git a/components/guest_view/browser/guest_view_base.cc b/components/guest_view/browser/guest_view_base.cc
--- a/components/guest_view/browser/guest_view_base.cc
+++ b/components/guest_view/browser/guest_view_base.cc
@@ -691,6 +691,14 @@ void GuestViewBase::AttachToOuterWebContentsFrame(
std::move(attachment_callback).Run();
}
+ // Disable viewport protection
+ // I use this hack, i.e. I reuse the SetPageScale method for my own purposes,
+ // so that I do not have to enter a new call in mojo and thus edit
+ // so many files.
+ // the chromium code never uses negative values, so there is no
+ // danger of inserting problems
+ embedder_web_contents->SetPageScale(-999);
+
// Completing attachment will resume suspended resource loads and then send
// queued events.
SignalWhenReady(base::BindOnce(&GuestViewBase::DidAttach,
diff --git a/cromite_flags/chrome/browser/about_flags_cc/Viewport-Protection-flag.inc b/cromite_flags/chrome/browser/about_flags_cc/Viewport-Protection-flag.inc
new file mode 100644
--- /dev/null
+++ b/cromite_flags/chrome/browser/about_flags_cc/Viewport-Protection-flag.inc
@@ -0,0 +1,10 @@
+#ifdef FLAG_SECTION
+
+ {"viewport-protection",
+ "Viewport Protection",
+ "Scale the viewport and the screen by a random factor to prevent "
+ "coordinate-based fingerprinting scripts. The factor is changed at each "
+ "change of origin.", kOsAll,
+ FEATURE_VALUE_TYPE(blink::features::kViewportProtection)},
+
+#endif
diff --git a/cromite_flags/third_party/blink/common/features_cc/Viewport-Protection-flag.inc b/cromite_flags/third_party/blink/common/features_cc/Viewport-Protection-flag.inc
new file mode 100644
--- /dev/null
+++ b/cromite_flags/third_party/blink/common/features_cc/Viewport-Protection-flag.inc
@@ -0,0 +1,3 @@
+CROMITE_FEATURE(kViewportProtection,
+ "ViewportProtection",
+ base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/cromite_flags/third_party/blink/common/features_h/Viewport-Protection-flag.inc b/cromite_flags/third_party/blink/common/features_h/Viewport-Protection-flag.inc
new file mode 100644
--- /dev/null
+++ b/cromite_flags/third_party/blink/common/features_h/Viewport-Protection-flag.inc
@@ -0,0 +1,2 @@
+// Enable blink viewport protection
+BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kViewportProtection);
diff --git a/third_party/blink/public/common/widget/device_emulation_params.h b/third_party/blink/public/common/widget/device_emulation_params.h
--- a/third_party/blink/public/common/widget/device_emulation_params.h
+++ b/third_party/blink/public/common/widget/device_emulation_params.h
@@ -21,6 +21,9 @@ namespace blink {
struct DeviceEmulationParams {
mojom::EmulatedScreenType screen_type = mojom::EmulatedScreenType::kDesktop;
+ // Forces screen recalculation the same way as mobile
+ bool force_mobile_calc = false;
+
// Emulated screen size. Typically full / physical size of the device screen
// in DIP. Empty size means using default value: original one for kDesktop
// screen position, equal to |view_size| for kMobile.
@@ -82,7 +85,8 @@ inline bool operator==(const DeviceEmulationParams& a,
a.viewport_scale == b.viewport_scale &&
a.viewport_segments == b.viewport_segments &&
a.device_posture == b.device_posture &&
- a.force_android_overlay_scrollbar == b.force_android_overlay_scrollbar;
+ a.force_android_overlay_scrollbar == b.force_android_overlay_scrollbar &&
+ a.force_mobile_calc == b.force_mobile_calc;
}
} // namespace blink
diff --git a/third_party/blink/renderer/core/css/css_properties.json5 b/third_party/blink/renderer/core/css/css_properties.json5
--- a/third_party/blink/renderer/core/css/css_properties.json5
+++ b/third_party/blink/renderer/core/css/css_properties.json5
@@ -4581,6 +4581,7 @@
},
{
name: "opacity",
+ computed_style_custom_functions: ["setter","getter"],
property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal"],
interpolable: true,
compositable: true,
@@ -4588,7 +4589,6 @@
field_template: "primitive",
default_value: "1.0",
type_name: "float",
- computed_style_custom_functions: ["setter"],
typedom_types: ["Number"],
valid_for_first_letter: true,
valid_for_first_line: true,
diff --git a/third_party/blink/renderer/core/css/media_values.cc b/third_party/blink/renderer/core/css/media_values.cc
--- a/third_party/blink/renderer/core/css/media_values.cc
+++ b/third_party/blink/renderer/core/css/media_values.cc
@@ -193,7 +193,7 @@ bool MediaValues::CalculateStrictMode(LocalFrame* frame) {
}
float MediaValues::CalculateDevicePixelRatio(LocalFrame* frame) {
- return frame->DevicePixelRatio();
+ return frame->DevicePixelRatio(false);
}
bool MediaValues::CalculateDeviceSupportsHDR(LocalFrame* frame) {
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver.cc b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
--- a/third_party/blink/renderer/core/css/resolver/style_resolver.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
@@ -2361,7 +2361,12 @@ ComputedStyleBuilder StyleResolver::InitialStyleBuilderForElement() const {
ComputedStyleBuilder builder = CreateComputedStyleBuilder();
builder.SetRtlOrdering(GetDocument().VisuallyOrdered() ? EOrder::kVisual
: EOrder::kLogical);
- builder.SetZoom(InitialZoom());
+ if (GetDocument().GetPage() && GetDocument().GetPage()->IsScreenEmulated()) {
+ // hides the zoom override to the dom on the html tag
+ builder.SetZoom(1);
+ } else {
+ builder.SetZoom(InitialZoom());
+ }
builder.SetEffectiveZoom(InitialZoom());
builder.SetInForcedColorsMode(GetDocument().InForcedColorsMode());
builder.SetTapHighlightColor(
diff --git a/third_party/blink/renderer/core/events/mouse_event.h b/third_party/blink/renderer/core/events/mouse_event.h
--- a/third_party/blink/renderer/core/events/mouse_event.h
+++ b/third_party/blink/renderer/core/events/mouse_event.h
@@ -29,6 +29,7 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/events/simulated_click_options.h"
#include "third_party/blink/renderer/core/events/ui_event_with_key_state.h"
+#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/platform/wtf/casting.h"
#include "ui/base/mojom/menu_source_type.mojom-blink.h"
@@ -148,8 +149,22 @@ class CORE_EXPORT MouseEvent : public UIEventWithKeyState {
// Note that these values are adjusted to counter the effects of zoom, so that
// values exposed via DOM APIs are invariant under zooming.
- virtual double screenX() const { return std::floor(screen_x_); }
- virtual double screenY() const { return std::floor(screen_y_); }
+ virtual double screenX() const {
+ if (view() && view()->GetFrame() &&
+ view()->GetFrame()->GetPage() &&
+ view()->GetFrame()->GetPage()->IsScreenEmulated()) {
+ return std::floor(page_x_);
+ }
+ return std::floor(screen_x_);
+ }
+ virtual double screenY() const {
+ if (view() && view()->GetFrame() &&
+ view()->GetFrame()->GetPage() &&
+ view()->GetFrame()->GetPage()->IsScreenEmulated()) {
+ return std::floor(page_y_);
+ }
+ return std::floor(screen_y_);
+ }
virtual double clientX() const { return std::floor(client_x_); }
virtual double clientY() const { return std::floor(client_y_); }
diff --git a/third_party/blink/renderer/core/events/pointer_event.h b/third_party/blink/renderer/core/events/pointer_event.h
--- a/third_party/blink/renderer/core/events/pointer_event.h
+++ b/third_party/blink/renderer/core/events/pointer_event.h
@@ -9,6 +9,7 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/events/mouse_event.h"
#include "third_party/blink/renderer/platform/wtf/casting.h"
+#include "third_party/blink/renderer/core/page/page.h"
namespace blink {
@@ -61,11 +62,21 @@ class CORE_EXPORT PointerEvent : public MouseEvent {
double screenX() const override {
if (ShouldHaveIntegerCoordinates())
return MouseEvent::screenX();
+ if (view() && view()->GetFrame() &&
+ view()->GetFrame()->GetPage() &&
+ view()->GetFrame()->GetPage()->IsScreenEmulated()) {
+ return page_x_;
+ }
return screen_x_;
}
double screenY() const override {
if (ShouldHaveIntegerCoordinates())
return MouseEvent::screenY();
+ if (view() && view()->GetFrame() &&
+ view()->GetFrame()->GetPage() &&
+ view()->GetFrame()->GetPage()->IsScreenEmulated()) {
+ return page_y_;
+ }
return screen_y_;
}
double clientX() const override {
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.cc b/third_party/blink/renderer/core/exported/web_view_impl.cc
--- a/third_party/blink/renderer/core/exported/web_view_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_view_impl.cc
@@ -1094,7 +1094,7 @@ WebPagePopupImpl* WebViewImpl::OpenPagePopup(PagePopupClient* client) {
page_popup_ = WebPagePopupImpl::Create(
std::move(popup_widget_host), std::move(widget_host),
std::move(widget_receiver), this, agent_group_scheduler,
- opener_widget->GetOriginalScreenInfos(), client);
+ opener_widget->GetScreenInfos(), client);
EnablePopupMouseWheelEventListener(web_opener_frame->LocalRoot());
return page_popup_.get();
}
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_party/blink/renderer/core/frame/local_dom_window.cc
--- a/third_party/blink/renderer/core/frame/local_dom_window.cc
+++ b/third_party/blink/renderer/core/frame/local_dom_window.cc
@@ -1581,7 +1581,12 @@ int LocalDOMWindow::outerHeight() const {
if (frame->IsInFencedFrameTree()) {
return innerHeight();
}
-
+ // If screen is emulated and this frame is remote cross-origin
+ // return innerHeight
+ if (frame->GetPage() && frame->GetPage()->IsScreenEmulated()
+ && frame->IsCrossOriginToOutermostMainFrame()) {
+ return innerHeight();
+ }
Page* page = frame->GetPage();
if (!page)
return 0;
@@ -1606,7 +1611,12 @@ int LocalDOMWindow::outerWidth() const {
if (frame->IsInFencedFrameTree()) {
return innerWidth();
}
-
+ // If screen is emulated and this frame is remote cross-origin
+ // return innerWidth
+ if (frame->GetPage() && frame->GetPage()->IsScreenEmulated()
+ && frame->IsCrossOriginToOutermostMainFrame()) {
+ return innerWidth();
+ }
Page* page = frame->GetPage();
if (!page)
return 0;
@@ -1802,7 +1812,8 @@ double LocalDOMWindow::devicePixelRatio() const {
if (!GetFrame())
return 0.0;
- return GetFrame()->DevicePixelRatio();
+ // never send the zoom factor override value
+ return GetFrame()->DevicePixelRatio(/*with_zoom_factor*/false);
}
ScriptPromise<ScrollResult> LocalDOMWindow::scrollBy(ScriptState* script_state,
@@ -2439,6 +2450,23 @@ DOMWindow* LocalDOMWindow::open(v8::Isolate* isolate,
if (!completed_url.IsEmpty() || result.new_window)
result.frame->Navigate(frame_request, WebFrameLoadType::kStandard);
+ if (result.frame->IsLocalFrame()) {
+ // we need to use opener setting when opening a iframe without url
+ // (as "about:blank") to force emulated screen
+ // since result.frame.GetContentSettingsClient()->AllowViewportChange()
+ // in the Page::DidCommitLoad() event returns false for these urls
+ //
+ // prevent this js code:
+ // var w = window.open()
+ // var not_emulated_screen_info = w.screen
+ bool protection_enabled = base::FeatureList::IsEnabled(features::kViewportProtection);
+ protection_enabled |= GetFrame()->GetContentSettingsClient()->AllowContentSetting(
+ ContentSettingsType::VIEWPORT, false);
+ result.frame->GetPage()->CalculateEmulatedScreenSetting(
+ To<LocalFrame>(result.frame),
+ /*force*/ protection_enabled);
+ }
+
// TODO(japhet): window-open-noopener.html?_top and several tests in
// html/browsers/windows/browsing-context-names/ appear to require that
// the special case target names (_top, _parent, _self) ignore opener
@@ -2490,6 +2518,15 @@ DOMWindow* LocalDOMWindow::openPictureInPictureWindow(
DCHECK(result.new_window);
result.frame->Navigate(frame_request, WebFrameLoadType::kStandard);
+
+ bool protection_enabled = base::FeatureList::IsEnabled(features::kViewportProtection);
+ protection_enabled |= GetFrame()->GetContentSettingsClient()->AllowContentSetting(
+ ContentSettingsType::VIEWPORT, false);
+ result.frame->GetPage()->CalculateEmulatedScreenSetting(
+ To<LocalFrame>(result.frame),
+ /*force*/ protection_enabled);
+ LOG(INFO) << "---protection_enabled " << protection_enabled;
+
LocalDOMWindow* pip_dom_window =
To<LocalDOMWindow>(result.frame->DomWindow());
pip_dom_window->SetIsPictureInPictureWindow();
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc
--- a/third_party/blink/renderer/core/frame/local_frame.cc
+++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -1670,6 +1670,10 @@ void LocalFrame::RestoreScrollOffsets() {
saved_scroll_offsets_ = nullptr;
}
+void LocalFrame::SetPageZoomFactorBaseValue(float factor) {
+ page_zoom_factor_base_value_ = factor;
+}
+
void LocalFrame::SetLayoutZoomFactor(float factor) {
SetZoomFactors(factor, text_zoom_factor_, css_zoom_factor_);
}
@@ -1859,12 +1863,16 @@ mojom::blink::DevicePostureType LocalFrame::GetDevicePosture() {
return mojo_handler_->GetDevicePosture();
}
-double LocalFrame::DevicePixelRatio() const {
+double LocalFrame::DevicePixelRatio(bool with_zoom_factor) const {
if (!page_)
return 0;
double ratio = page_->InspectorDeviceScaleFactorOverride();
- ratio *= LayoutZoomFactor();
+ // with_zoom_factor is default true
+ if (with_zoom_factor)
+ ratio *= LayoutZoomFactor();
+ else
+ ratio = layout_zoom_factor_;
return ratio;
}
@@ -3470,6 +3478,11 @@ void LocalFrame::SetScaleFactor(float scale_factor) {
DCHECK(!GetDocument() || !GetDocument()->Printing());
DCHECK(IsMainFrame());
+ if (scale_factor <= -999) {
+ GetPage()->DisableScreenEmulated();
+ return;
+ }
+
const PageScaleConstraints& constraints =
GetPage()->GetPageScaleConstraintsSet().FinalConstraints();
scale_factor = constraints.ClampToConstraints(scale_factor);
diff --git a/third_party/blink/renderer/core/frame/local_frame.h b/third_party/blink/renderer/core/frame/local_frame.h
--- a/third_party/blink/renderer/core/frame/local_frame.h
+++ b/third_party/blink/renderer/core/frame/local_frame.h
@@ -435,7 +435,8 @@ class CORE_EXPORT LocalFrame final
void SetInViewSourceMode(bool = true);
void SetLayoutZoomFactor(float);
- float LayoutZoomFactor() const { return layout_zoom_factor_; }
+ void SetPageZoomFactorBaseValue(float factor);
+ float LayoutZoomFactor() const { return layout_zoom_factor_ + page_zoom_factor_base_value_; }
void SetTextZoomFactor(float);
float TextZoomFactor() const { return text_zoom_factor_; }
void SetCssZoomFactor(float);
@@ -444,7 +445,7 @@ class CORE_EXPORT LocalFrame final
float text_zoom_factor,
float css_zoom_factor);
- double DevicePixelRatio() const;
+ double DevicePixelRatio(bool with_zoom_factor = true) const;
// Informs the local root's document and its local descendant subtree that a
// media query value changed.
@@ -1104,6 +1105,7 @@ class CORE_EXPORT LocalFrame final
unsigned did_run_detach_impl_ : 1 = false;
float layout_zoom_factor_;
+ float page_zoom_factor_base_value_ = 0;
float text_zoom_factor_;
float css_zoom_factor_;
diff --git a/third_party/blink/renderer/core/frame/screen_metrics_emulator.cc b/third_party/blink/renderer/core/frame/screen_metrics_emulator.cc
--- a/third_party/blink/renderer/core/frame/screen_metrics_emulator.cc
+++ b/third_party/blink/renderer/core/frame/screen_metrics_emulator.cc
@@ -34,6 +34,7 @@ void ScreenMetricsEmulator::Trace(Visitor* vistor) const {
}
void ScreenMetricsEmulator::DisableAndApply() {
+ override_screen_type_ = false;
frame_widget_->SetScreenMetricsEmulationParameters(false, emulation_params_);
frame_widget_->SetScreenRects(original_view_screen_rect_,
original_window_screen_rect_);
@@ -49,7 +50,16 @@ void ScreenMetricsEmulator::DisableAndApply() {
void ScreenMetricsEmulator::ChangeEmulationParams(
const DeviceEmulationParams& params,
const mojom::blink::DeviceEmulationCacheBehavior& cache_behavior) {
+ if (!params.force_mobile_calc) {
+ // user has activated device emulator via devtools
+ override_screen_type_ = true;
+ // we need to save requested value
+ last_screen_type_ = params.screen_type;
+ }
emulation_params_ = params;
+ if (override_screen_type_) {
+ emulation_params_.screen_type = last_screen_type_;
+ }
Apply(cache_behavior);
}
@@ -171,6 +181,9 @@ void ScreenMetricsEmulator::Apply(
frame_widget_->SetScreenInfoAndSize(emulated_screen_infos,
/*widget_size=*/widget_size,
/*visible_viewport_size=*/widget_size);
+
+ // save emulated window size
+ window_size_ = window_size;
}
void ScreenMetricsEmulator::UpdateVisualProperties(
@@ -204,9 +217,8 @@ void ScreenMetricsEmulator::OnUpdateScreenRects(
const gfx::Rect& window_screen_rect) {
original_view_screen_rect_ = view_screen_rect;
original_window_screen_rect_ = window_screen_rect;
- if (emulating_desktop()) {
- Apply();
- }
+ // needed as we need browser ui size
+ Apply();
}
} // namespace blink
diff --git a/third_party/blink/renderer/core/frame/screen_metrics_emulator.h b/third_party/blink/renderer/core/frame/screen_metrics_emulator.h
--- a/third_party/blink/renderer/core/frame/screen_metrics_emulator.h
+++ b/third_party/blink/renderer/core/frame/screen_metrics_emulator.h
@@ -64,6 +64,11 @@ class ScreenMetricsEmulator : public GarbageCollected<ScreenMetricsEmulator> {
// Emulated position of the main frame widget (aka view) rect.
gfx::Point ViewRectOrigin();
+ // Get emulated window size
+ const gfx::Size& ViewWindowSize() const {
+ return window_size_;
+ }
+
// Disables emulation and applies non-emulated values to the
// WebFrameWidgetImpl. Call this before destroying the ScreenMetricsEmulator.
void DisableAndApply();
@@ -83,6 +88,8 @@ class ScreenMetricsEmulator : public GarbageCollected<ScreenMetricsEmulator> {
private:
bool emulating_desktop() const {
+ if (emulation_params_.force_mobile_calc == true)
+ return false;
return emulation_params_.screen_type ==
mojom::blink::EmulatedScreenType::kDesktop;
}
@@ -96,6 +103,10 @@ class ScreenMetricsEmulator : public GarbageCollected<ScreenMetricsEmulator> {
// Parameters as passed by `WebFrameWidgetImpl::EnableDeviceEmulation()`
DeviceEmulationParams emulation_params_;
+ // Used to remember the user's choice if devtools are activated
+ bool override_screen_type_ = false;
+ mojom::EmulatedScreenType last_screen_type_;
+
// Original values to restore back after emulation ends.
display::ScreenInfos original_screen_infos_;
gfx::Size original_widget_size_dips_;
@@ -105,6 +116,9 @@ class ScreenMetricsEmulator : public GarbageCollected<ScreenMetricsEmulator> {
std::vector<gfx::Rect> original_root_viewport_segments_
ALLOW_DISCOURAGED_TYPE(
"WebFrameWidgetImpl::SetViewportSegments() uses STL");
+
+ // Actual size after apply
+ gfx::Size window_size_;
};
} // namespace blink
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
--- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
+++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
@@ -1950,6 +1950,15 @@ void WebFrameWidgetImpl::ApplyVisualPropertiesSizing(
if (DeviceEmulator() && widget_base_ && !widget_base_->WillBeDestroyed()) {
DeviceEmulator()->UpdateVisualProperties(visual_properties);
+ // Shink the view according to browsercontrols
+ auto* device_emulator = DeviceEmulator();
+ size_ = widget_base_->DIPsToCeiledBlinkSpace(
+ device_emulator->ViewWindowSize());
+ View()->ResizeWithBrowserControls(
+ size_.value(),
+ widget_base_->DIPsToCeiledBlinkSpace(
+ widget_base_->VisibleViewportSize()),
+ visual_properties.browser_controls_params);
return;
}
diff --git a/third_party/blink/renderer/core/frame/web_remote_frame_impl.cc b/third_party/blink/renderer/core/frame/web_remote_frame_impl.cc
--- a/third_party/blink/renderer/core/frame/web_remote_frame_impl.cc
+++ b/third_party/blink/renderer/core/frame/web_remote_frame_impl.cc
@@ -360,7 +360,8 @@ void WebRemoteFrameImpl::InitializeFrameVisualProperties(
visual_properties.page_scale_factor = ancestor_widget->PageScaleInMainFrame();
visual_properties.is_pinch_gesture_active =
ancestor_widget->PinchGestureActiveInMainFrame();
- visual_properties.screen_infos = ancestor_widget->GetOriginalScreenInfos();
+ // for a cross-site iframe, set the actual (original or emulated) screen infos
+ visual_properties.screen_infos = ancestor_widget->GetScreenInfos();
visual_properties.visible_viewport_size =
ancestor_widget->VisibleViewportSize();
const std::vector<gfx::Rect>& viewport_segments =
diff --git a/third_party/blink/renderer/core/input/touch.cc b/third_party/blink/renderer/core/input/touch.cc
--- a/third_party/blink/renderer/core/input/touch.cc
+++ b/third_party/blink/renderer/core/input/touch.cc
@@ -30,6 +30,7 @@
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "ui/gfx/geometry/point_f.h"
+#include "third_party/blink/renderer/core/page/page.h"
namespace blink {
@@ -75,7 +76,13 @@ Touch::Touch(LocalFrame* frame,
radius_(radius),
rotation_angle_(rotation_angle),
force_(force),
- absolute_location_(PageToAbsolute(frame, page_pos)) {}
+ absolute_location_(PageToAbsolute(frame, page_pos)) {
+ if (frame->GetPage() && frame->GetPage()->IsScreenEmulated()) {
+ // use page_pos instead of screen_pos
+ screen_pos_.set_x(page_pos_.x());
+ screen_pos_.set_y(page_pos_.y());
+ }
+ }
Touch::Touch(EventTarget* target,
int identifier,
@@ -105,7 +112,13 @@ Touch::Touch(LocalFrame* frame, const TouchInit* initializer)
radius_(initializer->radiusX(), initializer->radiusY()),
rotation_angle_(initializer->rotationAngle()),
force_(initializer->force()),
- absolute_location_(PageToAbsolute(frame, page_pos_)) {}
+ absolute_location_(PageToAbsolute(frame, page_pos_)) {
+ if (frame->GetPage() && frame->GetPage()->IsScreenEmulated()) {
+ // use page_pos instead of screen_pos
+ screen_pos_.set_x(page_pos_.x());
+ screen_pos_.set_y(page_pos_.y());
+ }
+ }
Touch* Touch::CloneWithNewTarget(EventTarget* event_target) const {
return MakeGarbageCollected<Touch>(
diff --git a/third_party/blink/renderer/core/page/page.cc b/third_party/blink/renderer/core/page/page.cc
--- a/third_party/blink/renderer/core/page/page.cc
+++ b/third_party/blink/renderer/core/page/page.cc
@@ -108,6 +108,13 @@
#include "ui/color/color_provider_utils.h"
#include "ui/gfx/geometry/insets_conversions.h"
+#include "base/rand_util.h"
+#include "build/build_config.h"
+#include "third_party/blink/public/common/scheme_registry.h"
+#include "third_party/blink/public/common/widget/device_emulation_params.h"
+#include "third_party/blink/renderer/core/exported/web_view_impl.h"
+#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
+
namespace blink {
namespace {
@@ -1280,7 +1287,96 @@ void Page::UpdateAcceleratedCompositingSettings() {
}
}
+void Page::CalculateEmulatedScreenSetting(LocalFrame* frame, bool force) {
+ bool isEnabled = base::FeatureList::IsEnabled(features::kViewportProtection);
+ blink::WebContentSettingsClient* settings = frame->GetContentSettingsClient();
+ isEnabled |= (settings && settings->AllowContentSetting(
+ ContentSettingsType::VIEWPORT, /*default_value*/ false));
+ String protocol =
+ frame->GetSecurityContext()->GetSecurityOrigin()->Protocol();
+ if (SchemeRegistry::IsWebUIScheme(protocol)
+ || CommonSchemeRegistry::IsExtensionScheme(protocol.Ascii())
+ || disable_screen_emulated_) {
+ isEnabled = false;
+ }
+ if (isEnabled || force) {
+ // this is the maximum (and minimum) value which in percentage
+ // corresponds to +- 0.03%
+ // more or less 3-6 pixels according to the resolution 300-600px
+ // little enough not to change the page view the user is used to,
+ // but enough to change all bounds, especially those in floating point
+ const int max_range = 300;
+
+ // only for the local main frame
+ // the other local frames use the values from main
+ // while the remote ones do not communicate the values to the parent
+ // (and they will be local main frame in their page context)
+ if (main_frame_ == frame) {
+ // set the scale factor
+ double scale_factor = 0;
+ if (override_window_scale_factor_ != 0) {
+ scale_factor = override_window_scale_factor_;
+ } else {
+ // we allow the increase or decrease of the screen size (and view)
+ scale_factor = 1.0 + base::RandInt(-max_range, max_range) / 10000.0;
+ }
+
+ // save the value, so a same domain navigation will reuse same value
+ override_window_scale_factor_ = scale_factor;
+
+ // we divide the value in half: half for the screen and the view,
+ // which then the latter will be scaled again by the zoom
+ double half_random = (scale_factor - 1.0) / 2.0;
+
+ // set emulation params
+ DeviceEmulationParams params;
+ // the screen size is changed to match the widget size with force_mobile_calc
+ params.force_mobile_calc = true;
+ params.screen_type = mojom::EmulatedScreenType::kDesktop;
+ // scale the widget size (and the screen size) by half_random scale factor
+ params.scale = 1 / (1.0 + half_random);
+
+ GetChromeClient().GetWebView()->EnableDeviceEmulation(params);
+
+ // set zoom factor
+ // the zoom factor is used by all the functions that manage the bounds,
+ // which is multiplied by the values in pixels when computed
+ // we do not modify the actual value but only the one used internally
+ // it becomes the base value used as the zoom property of the css, but
+ // it does not appear on the dom (which always remains 1.0)
+ double zoom_factor = 0;
+ if (override_zoom_factor_ != 0) {
+ zoom_factor = override_zoom_factor_;
+ } else {
+ // we only allow the page size to decrease, otherwise the scroll
+ // bars would not be visible
+ zoom_factor = base::RandInt(0, max_range/2) / 10000.0;
+ }
+
+ // save the value, so a same domain navigation will reuse same value
+ override_zoom_factor_ = zoom_factor;
+
+ frame->SetPageZoomFactorBaseValue(zoom_factor);
+ }
+ is_screen_emulated_ = true;
+ } else {
+ if (is_screen_emulated_ && main_frame_ == frame) {
+ GetChromeClient().GetWebView()->DisableDeviceEmulation();
+ frame->SetPageZoomFactorBaseValue(0);
+ }
+ is_screen_emulated_ = false;
+ }
+}
+
+void Page::DisableScreenEmulated() {
+ disable_screen_emulated_ = true;
+ GetChromeClient().GetWebView()->DisableDeviceEmulation();
+ DeprecatedLocalMainFrame()->SetPageZoomFactorBaseValue(0);
+ is_screen_emulated_ = false;
+}
+
void Page::DidCommitLoad(LocalFrame* frame) {
+ CalculateEmulatedScreenSetting(frame);
if (main_frame_ == frame) {
GetConsoleMessageStorage().Clear();
GetInspectorIssueStorage().Clear();
diff --git a/third_party/blink/renderer/core/page/page.h b/third_party/blink/renderer/core/page/page.h
--- a/third_party/blink/renderer/core/page/page.h
+++ b/third_party/blink/renderer/core/page/page.h
@@ -536,6 +536,10 @@ class CORE_EXPORT Page final : public GarbageCollected<Page>,
// related pages will include the new page instead of the old page, etc.
void TakePropertiesForLocalMainFrameSwap(Page* old_page);
+ void CalculateEmulatedScreenSetting(LocalFrame* frame, bool force = false);
+ bool IsScreenEmulated() { return is_screen_emulated_; }
+ void DisableScreenEmulated();
+
private:
friend class ScopedPagePauser;
class CloseTaskHandler;
@@ -708,6 +712,11 @@ class CORE_EXPORT Page final : public GarbageCollected<Page>,
// browser side FrameTree has the FrameTree::Type of kFencedFrame.
bool is_fenced_frame_tree_ = false;
+ bool is_screen_emulated_ = false;
+ bool disable_screen_emulated_ = false;
+ double override_window_scale_factor_ = 0;
+ double override_zoom_factor_ = 0;
+
// This tracks the mode that the fenced frame is set to.
blink::FencedFrame::DeprecatedFencedFrameMode fenced_frame_mode_ =
blink::FencedFrame::DeprecatedFencedFrameMode::kDefault;
diff --git a/third_party/blink/renderer/core/style/computed_style.h b/third_party/blink/renderer/core/style/computed_style.h
--- a/third_party/blink/renderer/core/style/computed_style.h
+++ b/third_party/blink/renderer/core/style/computed_style.h
@@ -2085,6 +2085,12 @@ class ComputedStyle final : public ComputedStyleBase {
IsRunningBackdropFilterAnimationOnCompositor();
}
+ float Opacity() const {
+ float v = OpacityInternal();
+ if (v >= 0.991f) v = 1.0f;
+ return v;
+ }
+
// Opacity utility functions.
bool HasOpacity() const { return Opacity() < 1.0f; }
--