Compare commits

...
Author SHA1 Message Date
Carmelo Messina 7cde6f6d28 [DOCS] Android protected keyboard geometry
Update patches doc / build (push) Waiting to run
Check git apply / build (push) Waiting to run
2026-07-24 07:09:30 +02:00
Carmelo Messina 8bc8c04e63 Supporting Dangling Ptr Detection via BackupRefPtr: no functional change, only context lines and hunk offsets differ. 2026-07-24 07:06:03 +02:00
Carmelo Messina 7085986549 Protect keyboard geometry on Android
Prevent websites from inferring on-screen keyboard dimensions through
viewport changes, dynamic CSS viewport units, browser-controls geometry,
and the Virtual Keyboard API.

Keep Chromium content at its neutral pre-IME height inside a native
ProtectedViewportScrollView. Force overlays-content while protection is
active, expose an empty virtual-keyboard rectangle, and retain stable
browser-controls geometry throughout the IME transition.

Use the focused editable or caret bounds to pan the physical viewport
without resizing Blink. Preserve continuous scrolling by handing
unconsumed motion between the native ScrollView and cc while retaining
normal compositor hit testing for inner and root scrollers.

Add an enabled-by-default feature flag and a per-site content setting.
WebUI and extension pages retain Chromium's standard keyboard behavior.
2026-07-24 07:03:22 +02:00
Carmelo Messina dfaf564244 Disable Android HDR: Prevents websites from detecting HDR support on Android 2026-07-24 07:01:50 +02:00
Carmelo Messina 160e170b1e Use browser navigation handler: remove unused code 2026-07-24 06:57:57 +02:00
Carmelo Messina a688e03bcb Move navigation bar to bottom: preserve keyboard insets in overlays-content mode
Do not clear the application bottom inset when the virtual keyboard uses
OVERLAYS_CONTENT.

The bottom-toolbar workaround is only required for keyboard modes that
resize Chromium content. Overlay mode owns its keyboard geometry and the
protected keyboard implementation needs the original inset to track the
IME transition consistently.

Keep the existing inset suppression for all non-overlay keyboard modes.

Test: Verified on Android with the bottom toolbar enabled across keyboard
      open and close transitions.
2026-07-24 06:56:37 +02:00
Carmelo Messina 40c0283e1e Viewport Protection flag: normalize DPR under viewport protection
Bucket the physical device pixel ratio to the nearest 0.5 while viewport
emulation is active and retain the selected value for the Page lifetime.

Expose the same protected DPR through window.devicePixelRatio and CSS
resolution media queries. This prevents the physical value from leaking
through either API and avoids inconsistencies between JavaScript and CSS.

Include the viewport-emulation scale when converting the virtual keyboard
overlay rectangle, keeping its geometry in the same emulated coordinate
space.

Test: Verified on Android that a physical DPR of 3.8 is exposed as 4
through window.devicePixelRatio and resolution media queries.
2026-07-24 06:51:38 +02:00
Carmelo Messina 7bfd4e7e07 Reduce input capability fingerprinting through normalization: reduce the amount of hardware-specific information exposed through pointer and touch capability APIs.
Normalize pointer type, hover capability, and maximum touch points to common
profiles instead of exposing the exact input hardware configuration.
This avoids exposing differences between devices with similar usage patterns,
such as desktop systems with optional touchscreen hardware.
2026-07-10 13:39:41 +02:00
Carmelo Messina 7a53b69f4b Multiple fingerprinting mitigations: Apply canvas fingerprinting noise to tiny readbacks
Canvas readbacks smaller than 8x8 can still expose deterministic rendering
differences. Apply the canvas fingerprinting mitigation to those surfaces as
well, while bounding pixel selection to the SkPixmap dimensions to avoid
out-of-range coordinates.
2026-07-10 13:37:37 +02:00
Carmelo Messina 4751fc6afc Supporting Dangling Ptr Detection via BackupRefPtr: Fixes the incorrect sequence of the dtor when creating icons on the home screen (#2922) 2026-07-10 13:34:12 +02:00
Carmelo Messina 36e44acc71 Set the screen frame rate to 60 Hz: fix video playback extremely choppy (#2877)
Fixes a destructive conflict between the 60Hz anti-fingerprinting
snapping logic (kThrottleMainFrameTo60Hz) and the native
kOnBeginFrameThrottleVideo feature when hardware VSync is disabled.

The artificial timestamp snapping introduced by the anti-fingerprinting
patch tricks the viz video throttling heuristics into thinking the
playback is unstable, forcing the compositor to drop BeginFrame
intervals to 30Hz (33.3ms). This leads to false lost frames and severe
stuttering in the media pipeline. Disabling kOnBeginFrameThrottleVideo
restores the continuous 60Hz rhythm.
2026-07-10 13:30:20 +02:00
Carmelo Messina 010ed3a42e Enable extensions in incognito: fix crashes when folding/unfolding phone when extensions are enabled
(#2942)
2026-07-10 13:27:56 +02:00
Carmelo Messina 0a17bb4619 Disable CSS blink-feature support: fix ::backdrop css pseudo element not working (#2918) 2026-07-10 13:26:41 +02:00
Carmelo Messina 95ba972914 Viewport Protection flag: Disable viewport protection in extension pop-ups 2026-07-10 13:25:29 +02:00
Carmelo Messina 3ed6c329a0 Eyeo Adblock for Cromite: filters transferred to uazo.github.io 2026-07-10 13:22:38 +02:00
Carmelo Messina 897623bd16 Enable component updater: components transferred to uazo.github.io 2026-07-10 13:21:42 +02:00
Carmelo Messina 3cfe04956c Android Pixel Perfect Mode: Disable viewport protection if pixel perfect mode is enabled 2026-07-10 13:20:18 +02:00
Carmelo Messina 85cc5643de Add cromite test support: Update to the latest version of chrome-driver 2026-07-10 13:18:33 +02:00
Carmelo Messina 87004d9443 [TOOLS] Automated update of filter lists: Trim leading and trailing whitespace and skip empty lines or lines starting with # 2026-06-05 13:52:35 +02:00
Carmelo Messina adafd623f6 [TOOLS] use pat 2026-06-05 12:32:38 +02:00
Carmelo Messina 822f836684 [TOOLS] fix branch name 2026-06-05 11:48:03 +02:00
Carmelo Messina 922ed6c8d2 [TOOLS] update filter list 2026-06-05 11:41:37 +02:00
Carmelo Messina 7c1f66263e [TOOLS] Update filter: show download errors 2026-06-05 11:37:10 +02:00
Carmelo Messina 1facdd51de [TOOLS] remove ref 2026-06-05 11:31:38 +02:00
Carmelo Messina 037678c93d [TOOLS] Use @v2 checkout 2026-06-05 11:28:10 +02:00
Carmelo Messina 7cd61d4205 [TOOLS] Update filters action 2026-06-05 11:15:02 +02:00
Carmelo Messina 9c4e2ea0b5 TOOLS: publish filters on git pages 2026-06-05 10:55:06 +02:00
Carmelo Messina c266f670b3 Partition blobs by top frame URL: Fix renderer crash in PublicURLManager and clean up Blob URL partitioning (#2922)
Fix a Null Pointer Dereference crash in `GetInsecureTopLevelSite()`
affecting sites with heavy Service Worker usage (e.g., Discord, Reddit).
This rewrite also hardens our custom `Partition-blobs-by-top-frame-URL`
logic against upstream cross-partition token leak vectors.

In `public_url_manager.cc`, the custom helper was passing the result of
`worker_global_scope->top_level_frame_security_origin()` straight into the
`BlinkSchemefulSite` constructor. However, this property is intentionally
null for Service Workers, causing a fatal null pointer dereference crash.

Additionally, since Cromite's partition checks execute downstream from
vanilla Chromium's native mitigations, the browser-side fallback using
`agent_cluster_id` inside `IsSamePartition()` was redundant dead code.

Changes:
1. Blink: Fully rewrote `GetInsecureTopLevelSite()` using safe `DynamicTo`
   casts. For Service Workers, it now safely pulls the browser-validated
   partition directly via `service_worker->storage_key().top_level_site()`,
   eliminating the null pointer crash surface.
2. Blink / Hardening: Intentionally excluded Shared Workers from Blob URL
   support (`IsSharedWorkerGlobalScope()`) by returning `std::nullopt` to prevent
   unpartitioned fallback vectors in shared contexts.
3. Storage: Streamlined `IsSamePartition()` in `blob_url_store_impl.cc`
   by removing the obsolete `agent_cluster_id` fallback, leaving a clean,
   deterministic verification of the top-level site partition.
2026-06-03 14:54:19 +02:00
20 changed files with 4528 additions and 194 deletions
+109
View File
@@ -0,0 +1,109 @@
name: Update Filters
on:
schedule:
- cron: "0 3 */2 * *" # every 2 days at 03:00 UTC
workflow_dispatch:
permissions:
contents: write
jobs:
build:
runs-on: ubuntu-latest
steps:
# -------------------------------
# Checkout main branch
# -------------------------------
- name: Checkout main branch
uses: actions/checkout@v2
with:
repository: 'uazo/cromite'
path: main
fetch-depth: 1
# -------------------------------
# Checkout pages branch
# -------------------------------
- name: Checkout pages branch
uses: actions/checkout@v2
with:
repository: 'uazo/cromite'
ref: pages
path: pages
fetch-depth: 1
token: ${{ secrets.PAGE_PUBLISH }}
# -------------------------------
# Prepare output directory
# -------------------------------
- name: Prepare output directory
run: mkdir -p main/out/filters
# -------------------------------
# Download filter lists (fail-safe, detailed errors)
# -------------------------------
- name: Download filter lists
run: |
set -e
FAILED=()
while IFS= read -r line || [[ -n "$line" ]]; do
# Trim leading and trailing whitespace
line="${line#"${line%%[![:space:]]*}"}"
line="${line%"${line##*[![:space:]]}"}"
# Skip empty lines or lines starting with #
[[ -z "$line" || "${line:0:1}" == "#" ]] && continue
url=$(echo "$line" | cut -d '=' -f1 | xargs)
file=$(echo "$line" | cut -d '=' -f2 | xargs)
if [ -z "$file" ]; then
file=$(basename "$url")
fi
echo "Downloading $url -> $file"
if ! curl -fsSL "$url" -o "main/out/filters/$file"; then
echo "FAILED: $url"
FAILED+=("$file")
fi
done < main/tools/images/update-cromite-org/filters-sources.txt
if [ ${#FAILED[@]} -ne 0 ]; then
echo "One or more downloads failed. Aborting deploy."
echo "Failed files:"
for f in "${FAILED[@]}"; do
echo "- $f"
done
exit 1
fi
# -------------------------------
# Deploy filters (only .txt)
# -------------------------------
- name: Deploy to pages
run: |
cd pages
rm -rf filters
mkdir -p filters
cp -r ../main/out/filters/. filters/
git config user.name "github-actions"
git config user.email "github-actions@github.com"
# add ONLY .txt files
find filters -type f -name "*.txt" -exec git add {} +
if git diff --cached --quiet; then
echo "No changes detected"
exit 0
fi
git commit -m "Update filters ($(date -u))"
git push https://x-access-token:${{ secrets.PAGE_PUBLISH }}@github.com/uazo/cromite.git HEAD:pages
+3
View File
@@ -308,6 +308,9 @@ Disable-minikin-hyphenation.patch
Disable-integration-with-Gemini.patch
Disable-AppRating.patch
Enable-Android-DevTools-Frontend.patch
Reduce-input-capability-fingerprinting-through-normalization.patch
Disable-Android-HDR.patch
Protect-keyboard-geometry-on-Android.patch
# temporary or wip patches
Temp-disable-predictive-back-gesture.patch
+3 -3
View File
@@ -88,7 +88,7 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessIni
- mDevToolsServer = new DevToolsServer(DEV_TOOLS_SERVER_SOCKET_PREFIX);
+ String socketPrefix = DEV_TOOLS_SERVER_SOCKET_PREFIX;
+ if (sActAsWebView.getInstance().isEnabled())
+ socketPrefix = "weblayer";
+ socketPrefix = "webview";
+ mDevToolsServer = new DevToolsServer(socketPrefix);
mDevToolsServer.setRemoteDebuggingEnabled(
true, DevToolsServer.Security.ALLOW_DEBUG_PERMISSION);
@@ -163,8 +163,8 @@ diff --git a/chrome/browser/android/devtools_server.cc b/chrome/browser/android/
if (is_started_)
return;
+ DLOG(INFO) << "---DevToolsServer::Start allow_debug_permission=" << allow_debug_permission;
+ DLOG(INFO) << "---socket_name_=" << socket_name_;
+ LOG(INFO) << "---DevToolsServer::Start allow_debug_permission=" << allow_debug_permission;
+ LOG(INFO) << "---socket_name_=" << socket_name_;
net::UnixDomainServerSocket::AuthCallback auth_callback =
allow_debug_permission
? base::BindRepeating(&AuthorizeSocketAccessWithDebugPermission)
@@ -1957,9 +1957,9 @@ diff --git a/third_party/blink/renderer/core/inspector/inspector_emulation_agent
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
@@ -1301,6 +1301,10 @@ void Page::CalculateEmulatedScreenSetting(LocalFrame* frame, bool force) {
|| disable_screen_emulated_) {
@@ -1305,6 +1305,10 @@ void Page::CalculateEmulatedScreenSetting(LocalFrame* frame, bool force) {
isEnabled = false;
force = false;
}
+ if (RuntimeEnabledFeatures::PixelPerfectEnabled()) {
+ isEnabled = false;
+21
View File
@@ -0,0 +1,21 @@
From: uazo <uazo@users.noreply.github.com>
Date: Mon, 20 Jul 2026 06:36:17 +0000
Subject: Disable Android HDR
License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html
---
ui/android/ui_android_features.cc | 1 +
1 file changed, 1 insertion(+)
diff --git a/ui/android/ui_android_features.cc b/ui/android/ui_android_features.cc
--- a/ui/android/ui_android_features.cc
+++ b/ui/android/ui_android_features.cc
@@ -8,6 +8,7 @@
namespace ui {
BASE_FEATURE(kAndroidHDR, base::FEATURE_ENABLED_BY_DEFAULT);
+SET_CROMITE_FEATURE_DISABLED(kAndroidHDR);
BASE_FEATURE(kAndroidUseCorrectDisplayWorkArea,
base::FEATURE_DISABLED_BY_DEFAULT);
--
@@ -9,22 +9,105 @@ see https://chromium-review.googlesource.com/c/chromium/src/+/5540782
License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html
---
.../blink/renderer/core/css/parser/css_supports_parser.cc | 2 +-
.../renderer/core/speculation_rules/document_rule_predicate.cc | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
.../build/scripts/cromite_feature_gen.py | 63 +++++++++++++++++++
.../core/css/parser/css_supports_parser.cc | 4 +-
.../document_rule_predicate.cc | 2 +-
third_party/blink/renderer/platform/BUILD.gn | 21 +++++++
4 files changed, 88 insertions(+), 2 deletions(-)
create mode 100644 third_party/blink/renderer/build/scripts/cromite_feature_gen.py
diff --git a/third_party/blink/renderer/build/scripts/cromite_feature_gen.py b/third_party/blink/renderer/build/scripts/cromite_feature_gen.py
new file mode 100644
--- /dev/null
+++ b/third_party/blink/renderer/build/scripts/cromite_feature_gen.py
@@ -0,0 +1,63 @@
+#!/usr/bin/env python3
+import sys
+import os
+import json
+import re
+
+sys.path.append(os.path.join(os.path.dirname(__file__), '../../build/scripts'))
+import json5_generator
+
+def main():
+ if len(sys.argv) < 4:
+ print("Uso: cromite_feature_gen.py <input.json5> <output.h> <output.cc>")
+ sys.exit(1)
+
+ input_file = sys.argv[1]
+ out_h_path = sys.argv[2]
+ out_cc_path = sys.argv[3]
+
+ data = json5_generator.Json5File.load_from_files([input_file])
+
+ stable_features = []
+ for feature in data.name_dictionaries:
+ status = feature.get('status')
+ if status == 'stable' or (isinstance(status, dict) and status.get('default') == 'stable'):
+ stable_features.append(feature['name'])
+
+ h_code = """#ifndef THIRD_PARTY_BLINK_CROMITE_ENABLED_FEATURES_H_
+#define THIRD_PARTY_BLINK_CROMITE_ENABLED_FEATURES_H_
+
+#include <string>
+#include "third_party/blink/renderer/core/core_export.h"
+
+namespace blink {
+class CORE_EXPORT CromiteCSSFeatures {
+ public:
+ static bool IsFeatureStableFromString(const std::string& name);
+};
+} // namespace blink
+#endif // THIRD_PARTY_BLINK_CROMITE_ENABLED_FEATURES_H_
+"""
+ with open(out_h_path, 'w') as f:
+ f.write(h_code)
+
+ cc_elements = []
+ for feat in stable_features:
+ cc_elements.append(f' if (name == "{feat}") return true;')
+
+ joined_elements = "\n".join(cc_elements)
+
+ cc_code = f"""#include "third_party/blink/renderer/platform/cromite_enabled_features.h"
+
+namespace blink {{
+bool CromiteCSSFeatures::IsFeatureStableFromString(const std::string& name) {{
+{joined_elements}
+ return false;
+}}
+}} // namespace blink
+"""
+ with open(out_cc_path, 'w') as f:
+ f.write(cc_code)
+
+if __name__ == '__main__':
+ main()
diff --git a/third_party/blink/renderer/core/css/parser/css_supports_parser.cc b/third_party/blink/renderer/core/css/parser/css_supports_parser.cc
--- a/third_party/blink/renderer/core/css/parser/css_supports_parser.cc
+++ b/third_party/blink/renderer/core/css/parser/css_supports_parser.cc
@@ -302,7 +302,7 @@ bool CSSSupportsParser::ConsumeBlinkFeatureFn(CSSParserTokenStream& stream) {
@@ -13,6 +13,7 @@
#include "third_party/blink/renderer/core/css/style_rule.h"
#include "third_party/blink/renderer/core/css_value_keywords.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+#include "third_party/blink/renderer/platform/cromite_enabled_features.h"
namespace blink {
@@ -298,10 +299,11 @@ bool CSSSupportsParser::ConsumeBlinkFeatureFn(CSSParserTokenStream& stream) {
if (stream.Peek().GetType() == kIdentToken) {
const CSSParserToken& feature_name = stream.ConsumeIncludingWhitespace();
- if (RuntimeEnabledFeatures::IsFeatureEnabledFromString(
+ if (CromiteCSSFeatures::IsFeatureStableFromString(
feature_name.Value().Utf8()) &&
guard.Release()) {
stream.ConsumeWhitespace();
- return true;
+ return false;
+ DLOG(INFO) << "---Blink feature: " << feature_name.Value().Utf8();
return true;
}
}
return false;
diff --git a/third_party/blink/renderer/core/speculation_rules/document_rule_predicate.cc b/third_party/blink/renderer/core/speculation_rules/document_rule_predicate.cc
--- a/third_party/blink/renderer/core/speculation_rules/document_rule_predicate.cc
+++ b/third_party/blink/renderer/core/speculation_rules/document_rule_predicate.cc
@@ -37,4 +120,49 @@ diff --git a/third_party/blink/renderer/core/speculation_rules/document_rule_pre
CSSParserContext* css_parser_context =
MakeGarbageCollected<CSSParserContext>(*execution_context);
for (auto* raw_selector : raw_selectors) {
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn
--- a/third_party/blink/renderer/platform/BUILD.gn
+++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -43,6 +43,23 @@ make_names("font_family_names") {
output_dir = blink_platform_output_dir
}
+blink_python_runner("generate_cromite_enabled_features") {
+ script = "../build/scripts/cromite_feature_gen.py"
+
+ inputs = [ "runtime_enabled_features.json5" ]
+
+ outputs = [
+ "$blink_platform_output_dir/cromite_enabled_features.h",
+ "$blink_platform_output_dir/cromite_enabled_features.cc",
+ ]
+
+ args = [
+ rebase_path(inputs[0], root_build_dir),
+ rebase_path(outputs[0], root_build_dir),
+ rebase_path(outputs[1], root_build_dir),
+ ]
+}
+
blink_python_runner("runtime_enabled_features") {
script = "../build/scripts/make_runtime_features.py"
@@ -172,6 +189,7 @@ group("make_platform_generated") {
":color_data",
":font_family_names",
":runtime_enabled_features",
+ ":generate_cromite_enabled_features",
":runtime_feature_state_override_context",
"//third_party/blink/public:buildflags",
"//third_party/blink/public/common:buildflags",
@@ -1691,6 +1709,9 @@ component("platform") {
sources += [ _output ]
}
}
+ foreach(_output, get_target_outputs(":generate_cromite_enabled_features")) {
+ sources += [ _output ]
+ }
if (current_cpu == "loong64") {
cflags = [
--
+25 -5
View File
@@ -26,18 +26,18 @@ License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html
.../prediction_model_download_manager.cc | 2 +-
components/update_client/component.cc | 13 ++++++
components/update_client/crx_downloader.cc | 5 ++
components/update_client/net/network_impl.cc | 2 +
components/update_client/net/network_impl.cc | 4 +-
components/update_client/op_install.cc | 2 +-
components/update_client/protocol_parser.cc | 2 +
.../update_client/protocol_parser_json.cc | 2 +
components/update_client/request_sender.cc | 3 +-
components/update_client/request_sender.cc | 7 +--
components/update_client/unpacker.cc | 7 +--
components/update_client/unpacker.h | 4 +-
components/update_client/update_checker.cc | 6 ++-
components/update_client/update_engine.cc | 9 ++++
components/update_client/utils.cc | 4 ++
extensions/browser/sandboxed_unpacker.cc | 2 +-
29 files changed, 155 insertions(+), 62 deletions(-)
29 files changed, 158 insertions(+), 65 deletions(-)
diff --git a/android_webview/browser/aw_browser_main_parts.cc b/android_webview/browser/aw_browser_main_parts.cc
--- a/android_webview/browser/aw_browser_main_parts.cc
@@ -401,7 +401,7 @@ diff --git a/components/component_updater/component_updater_url_constants.cc b/c
// --component-updater=url-source=someurl.
const char kUpdaterJSONDefaultUrl[] =
- "https://update.googleapis.com/service/update2/json";
+ "https://www.cromite.org/components/query4_0.json";
+ "https://uazo.github.io/cromite/components/query4_0.json";
const char kUpdaterJSONFallbackUrl[] =
- "http://update.googleapis.com/service/update2/json";
@@ -647,11 +647,20 @@ diff --git a/components/update_client/crx_downloader.cc b/components/update_clie
diff --git a/components/update_client/net/network_impl.cc b/components/update_client/net/network_impl.cc
--- a/components/update_client/net/network_impl.cc
+++ b/components/update_client/net/network_impl.cc
@@ -117,7 +117,7 @@ void NetworkFetcherImpl::PostRequest(
PostRequestCompleteCallback post_request_complete_callback) {
auto resource_request = std::make_unique<network::ResourceRequest>();
resource_request->url = url;
- resource_request->method = "POST";
+ resource_request->method = "GET";
resource_request->load_flags = net::LOAD_DISABLE_CACHE;
resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
for (const auto& [name, value] : post_additional_headers) {
@@ -131,7 +131,9 @@ void NetworkFetcherImpl::PostRequest(
network::SimpleURLLoader::RETRY_ON_NETWORK_CHANGE);
// The `Content-Type` header set by |AttachStringForUpload| overwrites any
// `Content-Type` header present in the |ResourceRequest| above.
+#if !BUILDFLAG(IS_ANDROID)
+#if ((false)) && !BUILDFLAG(IS_ANDROID)
simple_url_loader->AttachStringForUpload(post_data, content_type);
+#endif
simple_url_loader->SetOnResponseStartedCallback(base::BindOnce(
@@ -720,6 +729,17 @@ diff --git a/components/update_client/request_sender.cc b/components/update_clie
if (!fetcher_factory_) {
// The request was cancelled.
@@ -133,8 +134,8 @@ void RequestSender::SendInternalComplete(
const std::string& response_set_cookie,
int retry_after_sec) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- VLOG(2) << "Omaha response received: " << response_body;
- VLOG_IF(2, error) << "Omaha send error: " << error;
+ LOG(INFO) << "Omaha response received: " << response_body;
+ LOG(INFO) << "Omaha send error: " << error;
if (!error) {
if (!use_signing_) {
diff --git a/components/update_client/unpacker.cc b/components/update_client/unpacker.cc
--- a/components/update_client/unpacker.cc
+++ b/components/update_client/unpacker.cc
@@ -7,7 +7,7 @@ Full activation of incognito mode in experimental extension
License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html
---
.../chrome/browser/ChromeTabbedActivity.java | 5 +
.../chrome/browser/app/ChromeActivity.java | 42 +++++-
.../chrome/browser/app/ChromeActivity.java | 42 ++++-
.../CustomTabIntentDataProvider.java | 3 +
.../browser/tabmodel/TabModelJniBridge.java | 3 +-
.../tabmodel/TabModelSelectorBase.java | 14 ++
@@ -20,7 +20,8 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html
.../extensions/extension_actions_bridge.h | 4 +-
.../ui/extensions/ExtensionActionsBridge.java | 62 +++++++-
.../ui/extensions/ExtensionsMenuBridge.java | 103 ++++++++++---
.../extensions/ExtensionsToolbarBridge.java | 137 ++++++++++++------
.../extensions/ExtensionsToolbarBridge.java | 145 ++++++++++++------
.../ExtensionAccessControlButtonMediator.java | 3 +-
.../ExtensionActionListCoordinator.java | 12 +-
.../ExtensionActionListMediator.java | 24 +--
.../extensions/ExtensionsMenuCoordinator.java | 14 +-
@@ -32,7 +33,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html
.../ChromeAndroidTaskFeature.java | 2 +-
components/tabs/impl/tab_collection.cc | 16 ++
components/tabs/impl/tab_strip_collection.cc | 4 +-
26 files changed, 449 insertions(+), 122 deletions(-)
27 files changed, 458 insertions(+), 124 deletions(-)
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -688,7 +689,7 @@ diff --git a/chrome/browser/ui/android/extensions/java/src/org/chromium/chrome/b
// TODO(crbug.com/423483658): Consider moving ExtensionsMenuButtonState and related types
// (e.g., RequestAccessButtonParams) into a new ExtensionControls.java file.
@IntDef({
@@ -48,21 +55,61 @@ public class ExtensionsToolbarBridge implements Destroyable {
@@ -48,49 +55,96 @@ public class ExtensionsToolbarBridge implements Destroyable {
private final @Nullable LifetimeAssert mLifetimeAssert = LifetimeAssert.create(this);
private long mNativeExtensionsToolbarAndroid;
private final ObserverList<Observer> mObservers = new ObserverList<>();
@@ -712,6 +713,8 @@ diff --git a/chrome/browser/ui/android/extensions/java/src/org/chromium/chrome/b
ExtensionsToolbarBridgeJni.get()
- .init(this, task.getOrCreateNativeBrowserWindowPtr(profile));
+ .init(this, mTask.getOrCreateNativeBrowserWindowPtr(mProfile));
+ if (Instance().mNativeExtensionsToolbarAndroid == 0)
+ Instance().mNativeExtensionsToolbarAndroid = mNativeExtensionsToolbarAndroid;
+ }
+
+ @Override
@@ -754,8 +757,10 @@ diff --git a/chrome/browser/ui/android/extensions/java/src/org/chromium/chrome/b
+ private void destroy() {
assert mNativeExtensionsToolbarAndroid != 0;
ExtensionsToolbarBridgeJni.get().destroy(mNativeExtensionsToolbarAndroid);
+ if (Instance().mNativeExtensionsToolbarAndroid == mNativeExtensionsToolbarAndroid)
+ Instance().mNativeExtensionsToolbarAndroid = 0;
mNativeExtensionsToolbarAndroid = 0;
@@ -70,27 +117,30 @@ public class ExtensionsToolbarBridge implements Destroyable {
LifetimeAssert.destroy(mLifetimeAssert);
}
public void addObserver(Observer observer) {
@@ -792,7 +797,7 @@ diff --git a/chrome/browser/ui/android/extensions/java/src/org/chromium/chrome/b
}
@Nullable
@@ -106,9 +156,10 @@ public class ExtensionsToolbarBridge implements Destroyable {
@@ -106,9 +160,10 @@ public class ExtensionsToolbarBridge implements Destroyable {
// ChromeAndroidTask}'s destruction, and it is currently being worked on.
return null;
}
@@ -804,7 +809,7 @@ diff --git a/chrome/browser/ui/android/extensions/java/src/org/chromium/chrome/b
actionId,
webContents,
canvasWidthDp,
@@ -127,52 +178,52 @@ public class ExtensionsToolbarBridge implements Destroyable {
@@ -127,52 +182,53 @@ public class ExtensionsToolbarBridge implements Destroyable {
}
public String[] getPinnedActionIds() {
@@ -860,19 +865,23 @@ diff --git a/chrome/browser/ui/android/extensions/java/src/org/chromium/chrome/b
public @ExtensionsMenuButtonState int getExtensionsMenuButtonState(WebContents webContents) {
- assert mNativeExtensionsToolbarAndroid != 0;
+ assert Instance().mNativeExtensionsToolbarAndroid != 0;
+ if (Instance().mNativeExtensionsToolbarAndroid == 0)
+ return ExtensionsMenuButtonState.DEFAULT;
return ExtensionsToolbarBridgeJni.get()
- .getExtensionsMenuButtonState(mNativeExtensionsToolbarAndroid, webContents);
+ .getExtensionsMenuButtonState(Instance().mNativeExtensionsToolbarAndroid, webContents);
}
public void onRequestAccessButtonClicked(WebContents webContents) {
@@ -184,10 +235,10 @@ public class ExtensionsToolbarBridge implements Destroyable {
@@ -183,11 +239,12 @@ public class ExtensionsToolbarBridge implements Destroyable {
.onRequestAccessButtonClicked(mNativeExtensionsToolbarAndroid, webContents);
}
public RequestAccessButtonParams getRequestAccessButtonParams(WebContents webContents) {
- public RequestAccessButtonParams getRequestAccessButtonParams(WebContents webContents) {
- assert mNativeExtensionsToolbarAndroid != 0;
+ assert Instance().mNativeExtensionsToolbarAndroid != 0;
+ public RequestAccessButtonParams getNullableRequestAccessButtonParams(WebContents webContents) {
+ if (Instance().mNativeExtensionsToolbarAndroid == 0)
+ return null;
RequestAccessButtonParams params =
ExtensionsToolbarBridgeJni.get()
- .getRequestAccessButtonParams(mNativeExtensionsToolbarAndroid, webContents);
@@ -880,7 +889,7 @@ diff --git a/chrome/browser/ui/android/extensions/java/src/org/chromium/chrome/b
assert params != null;
return params;
}
@@ -201,29 +252,29 @@ public class ExtensionsToolbarBridge implements Destroyable {
@@ -201,29 +258,29 @@ public class ExtensionsToolbarBridge implements Destroyable {
@CalledByNative
public void triggerPopup(@JniType("std::string") String actionId, long nativeHostPtr) {
// {@link mDelegate} should be set in {@code ExtensionActionListMediator}'s constructor.
@@ -916,7 +925,7 @@ diff --git a/chrome/browser/ui/android/extensions/java/src/org/chromium/chrome/b
observer.onToolbarControlStateUpdated();
}
}
@@ -231,65 +282,65 @@ public class ExtensionsToolbarBridge implements Destroyable {
@@ -231,65 +288,65 @@ public class ExtensionsToolbarBridge implements Destroyable {
@CalledByNative
public boolean hasPoppedOutAction() {
// {@link mDelegate} should be set in {@code ExtensionActionListMediator}'s constructor.
@@ -994,6 +1003,19 @@ diff --git a/chrome/browser/ui/android/extensions/java/src/org/chromium/chrome/b
observer.onActiveWebContentsChanged(webContents);
}
}
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionAccessControlButtonMediator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionAccessControlButtonMediator.java
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionAccessControlButtonMediator.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionAccessControlButtonMediator.java
@@ -79,7 +79,8 @@ class ExtensionAccessControlButtonMediator implements Destroyable {
private void refreshRequestAccessButtonWithWebContents(WebContents webContents) {
RequestAccessButtonParams params =
- mExtensionsToolbarBridge.getRequestAccessButtonParams(webContents);
+ mExtensionsToolbarBridge.getNullableRequestAccessButtonParams(webContents);
+ if (params == null) return;
if (params.getExtensionIds().length > 0) {
mModel.set(ExtensionsToolbarProperties.IS_REQUEST_ACCESS_BUTTON_VISIBLE, true);
mModel.set(
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionActionListCoordinator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionActionListCoordinator.java
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionActionListCoordinator.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionActionListCoordinator.java
+23 -19
View File
@@ -104,7 +104,7 @@ suit Cromite logic.
.../adblock/core/subscription/subscription.cc | 20 +
.../adblock/core/subscription/subscription.h | 3 +
.../subscription_collection_impl.cc | 7 +-
.../core/subscription/subscription_config.cc | 86 +-
.../core/subscription/subscription_config.cc | 88 +-
.../core/subscription/subscription_config.h | 6 +-
.../subscription_downloader_impl.cc | 19 +-
.../subscription_persistent_metadata.h | 1 +
@@ -132,7 +132,7 @@ suit Cromite logic.
.../renderer/core/exported/web_document.cc | 13 +-
.../blink/renderer/core/html/html_element.cc | 8 +-
.../definitions/adblock_private.d.ts | 14 +
127 files changed, 9444 insertions(+), 709 deletions(-)
127 files changed, 9442 insertions(+), 713 deletions(-)
rename chrome/browser/adblock/android/java/res/xml/{adblock_preferences.xml => eyeo_adblock_preferences.xml} (59%)
create mode 100644 chrome/browser/resources/settings/adblock_page/adblock_page.html
create mode 100644 chrome/browser/resources/settings/adblock_page/adblock_page.ts
@@ -274,7 +274,7 @@ diff --git a/chrome/browser/adblock/android/adblock_strings.grd b/chrome/browser
+ <message name="IDS_ADBLOCK_SETTINGS_PRIVILEGED_FILTERS_ENABLED_SUMMARY" desc="">
+ Snippets are pieces of JavaScript code, injected by the Adblock Plus, that execute within the context of a website and combat advanced ads that circumvent ordinary blocking.
+The functionality is ONLY allowed for the list
+https://www.cromite.org/filters/abp-filters-anti-cv.txt
+https://uazo.github.io/cromite/filters/abp-filters-anti-cv.txt
+which is activated by this setting.
+ </message>
+ <message name="IDS_ADBLOCK_SETTINGS_OPEN_REPO_URL_TEXT" desc="">
@@ -1289,7 +1289,7 @@ new file mode 100644
+ <div class="cr-secondary-text">
+ Snippets are pieces of JavaScript code, injected by the Adblock Plus, that execute within the context of a website and combat advanced ads that circumvent ordinary blocking.
+ The functionality is ONLY allowed for the list
+ <a href="https://www.cromite.org/filters/abp-filters-anti-cv.txt">abp-filters-anti-cv.txt</a>
+ <a href="https://uazo.github.io/cromite/filters/abp-filters-anti-cv.txt">abp-filters-anti-cv.txt</a>
+ which is activated by this setting.
+ <br><a href="https://gitlab.com/eyeo/anti-cv/abp-filters-anti-cv">Open ABP anti-circumvention filter list repo</a>
+ <br><a href="https://developers.eyeo.com/snippets/snippets-overview">Open ABP Snippets Overview</a>
@@ -12415,7 +12415,7 @@ diff --git a/components/adblock/core/subscription/subscription_config.cc b/compo
std::string GetHost() {
- GURL url("https://easylist-downloads.adblockplus.org");
+ GURL url("https://www.cromite.org/filters/");
+ GURL url("https://uazo.github.io/cromite/filters/");
if (!g_port_for_testing) {
return url.spec();
}
@@ -12478,7 +12478,7 @@ diff --git a/components/adblock/core/subscription/subscription_config.cc b/compo
+ SubscriptionUiVisibility::Visible,
+ SubscriptionFirstRunBehavior::SubscribeAtFirstRun,
+ SubscriptionPrivilegedFilterStatus::Forbidden},
+ {GURL(GetHost() + "badmojr-1Hosts-master-Pro-adblock.txt"),
+ {GURL(GetHost() + "badmojr-1Hosts-master-Lite-adblock.txt"),
+ "badmojr/1Hosts",
+ {"en"},
+ SubscriptionUiVisibility::Visible,
@@ -12486,7 +12486,7 @@ diff --git a/components/adblock/core/subscription/subscription_config.cc b/compo
SubscriptionPrivilegedFilterStatus::Forbidden},
{GURL(GetHost() + "abpindo.txt"),
"ABPindo",
@@ -262,17 +276,23 @@ const std::vector<KnownSubscriptionInfo>& config::GetKnownSubscriptions() {
@@ -262,23 +276,23 @@ const std::vector<KnownSubscriptionInfo>& config::GetKnownSubscriptions() {
SubscriptionFirstRunBehavior::SubscribeIfLocaleMatch,
SubscriptionPrivilegedFilterStatus::Forbidden},
{AcceptableAdsUrl(),
@@ -12503,18 +12503,22 @@ diff --git a/components/adblock/core/subscription/subscription_config.cc b/compo
SubscriptionUiVisibility::Visible,
- SubscriptionFirstRunBehavior::Subscribe,
- SubscriptionPrivilegedFilterStatus::Allowed},
- {GURL(GetHost() + "i_dont_care_about_cookies.txt"),
- "I don't care about cookies",
+ SubscriptionFirstRunBehavior::SubscribeAtFirstRun,
+ SubscriptionPrivilegedFilterStatus::AllowedAndChecked},
+ {GURL("https://raw.githubusercontent.com/uazo/cromite/master/tools/filters/experimental-cromite-filters.txt"),
+ "Cromite experimental filters",
+ {},
+ SubscriptionUiVisibility::Visible,
{},
SubscriptionUiVisibility::Visible,
- SubscriptionFirstRunBehavior::Ignore,
- SubscriptionPrivilegedFilterStatus::Forbidden},
+ SubscriptionFirstRunBehavior::SubscribeAtFirstRun,
+ SubscriptionPrivilegedFilterStatus::AllowedAndChecked},
{GURL(GetHost() + "i_dont_care_about_cookies.txt"),
"I don't care about cookies",
{},
@@ -303,13 +323,13 @@ const std::vector<KnownSubscriptionInfo>& config::GetKnownSubscriptions() {
{GURL(GetHost() + ""
"fanboy-notifications.txt"),
"Fanboy's Notifications Blocking List",
@@ -303,13 +317,13 @@ const std::vector<KnownSubscriptionInfo>& config::GetKnownSubscriptions() {
{},
SubscriptionUiVisibility::Invisible,
SubscriptionFirstRunBehavior::Ignore,
@@ -12530,7 +12534,7 @@ diff --git a/components/adblock/core/subscription/subscription_config.cc b/compo
// You can customize subscriptions available on first run and in settings
// here. Items are displayed in settings in order declared here. See
@@ -329,9 +349,9 @@ const std::vector<KnownSubscriptionInfo>& config::GetKnownSubscriptions() {
@@ -329,9 +343,9 @@ const std::vector<KnownSubscriptionInfo>& config::GetKnownSubscriptions() {
*/
// clang-format on
@@ -12542,7 +12546,7 @@ diff --git a/components/adblock/core/subscription/subscription_config.cc b/compo
}
bool config::AllowPrivilegedFilters(const GURL& url) {
@@ -346,7 +366,7 @@ bool config::AllowPrivilegedFilters(const GURL& url) {
@@ -346,7 +360,7 @@ bool config::AllowPrivilegedFilters(const GURL& url) {
for (const auto& cur : GetKnownSubscriptions()) {
if (cur.url == url) {
return cur.privileged_status ==
@@ -12551,7 +12555,7 @@ diff --git a/components/adblock/core/subscription/subscription_config.cc b/compo
}
}
@@ -356,9 +376,7 @@ bool config::AllowPrivilegedFilters(const GURL& url) {
@@ -356,9 +370,7 @@ bool config::AllowPrivilegedFilters(const GURL& url) {
const std::vector<PreloadedSubscriptionInfo>&
config::GetPreloadedSubscriptionConfiguration() {
static const std::vector<PreloadedSubscriptionInfo> preloaded_subscriptions =
@@ -12562,7 +12566,7 @@ diff --git a/components/adblock/core/subscription/subscription_config.cc b/compo
return preloaded_subscriptions;
}
@@ -368,10 +386,11 @@ void SetFilterListServerPortForTesting(int port_for_testing) {
@@ -368,10 +380,11 @@ void SetFilterListServerPortForTesting(int port_for_testing) {
const std::vector<std::string_view>& config::MaybeSplitCombinedAdblockList(
const GURL& filter_list) {
@@ -12578,7 +12582,7 @@ diff --git a/components/adblock/core/subscription/subscription_config.cc b/compo
{"abpindo+easylist.txt", {"abpindo.txt", VALUE_EASYLIST_EN}},
{"abpvn+easylist", {"abpvn.txt", VALUE_EASYLIST_EN}},
{"bulgarian_list+easylist.",
@@ -410,11 +429,11 @@ const std::vector<std::string_view>& config::MaybeSplitCombinedAdblockList(
@@ -410,11 +423,11 @@ const std::vector<std::string_view>& config::MaybeSplitCombinedAdblockList(
{"rolist+easylist.txt", {"rolist.txt", VALUE_EASYLIST_EN}},
{"ruadlist+easylist.txt", {"ruadlist.txt", VALUE_EASYLIST_EN}},
{"turkish+easylist.txt", {"turkish.txt", VALUE_EASYLIST_EN}},
@@ -12593,7 +12597,7 @@ diff --git a/components/adblock/core/subscription/subscription_config.cc b/compo
auto path =
base::TrimString(filter_list.path(), "/", base::TRIM_LEADING);
@@ -422,7 +441,8 @@ const std::vector<std::string_view>& config::MaybeSplitCombinedAdblockList(
@@ -422,7 +435,8 @@ const std::vector<std::string_view>& config::MaybeSplitCombinedAdblockList(
if (it == filter_lists_map->end()) {
return *EMPTY_VALUE;
}
@@ -33,7 +33,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html
.../ChromeAccessibilitySettingsDelegate.java | 70 +++++++++
.../HeadlessBrowserControlsStateProvider.java | 5 +
.../BottomBarContainerCoordinator.java | 7 +-
.../compositor/CompositorViewHolder.java | 7 +
.../compositor/CompositorViewHolder.java | 8 +
.../layouts/LayoutManagerChrome.java | 12 +-
.../layouts/LayoutManagerChromeTablet.java | 7 +-
.../layouts/ToolbarSwipeLayout.java | 14 +-
@@ -110,7 +110,7 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html
.../render_widget_host_view_android.cc | 3 +
.../Move-navigation-bar-to-bottom.inc | 17 ++
.../renderer/core/frame/viewport_data.cc | 1 +
97 files changed, 1111 insertions(+), 107 deletions(-)
97 files changed, 1112 insertions(+), 107 deletions(-)
create mode 100644 chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/ReversedLinearLayout.java
create mode 100644 cromite_flags/chrome/browser/about_flags_cc/Move-navigation-bar-to-bottom.inc
@@ -962,11 +962,12 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/Comp
if (forwarder != null) {
forwarder.setCurrentTouchOffsetX(left);
forwarder.setCurrentTouchOffsetY(top);
@@ -1043,6 +1047,9 @@ public class CompositorViewHolder extends FrameLayout
@@ -1043,6 +1047,10 @@ public class CompositorViewHolder extends FrameLayout
mApplicationBottomInsetSupplier != null
? mApplicationBottomInsetSupplier.getInsets().webContentsHeightInset
: 0;
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()) {
+ if (ChromeFeatureList.sMoveTopToolbarToBottom.isEnabled()
+ && mVirtualKeyboardMode != VirtualKeyboardMode.OVERLAYS_CONTENT) {
+ keyboardInset = 0;
+ }
@@ -32,21 +32,21 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html
.../blink/renderer/core/dom/document.cc | 19 +++
.../blink/renderer/core/dom/document.h | 7 +
.../html/canvas/canvas_async_blob_creator.cc | 4 +
.../renderer/core/html/canvas/text_metrics.cc | 18 ++
.../renderer/core/html/canvas/text_metrics.cc | 18 +++
.../renderer/core/html/canvas/text_metrics.h | 2 +
.../core/svg/svg_text_content_element.cc | 28 +++-
.../canvas2d/base_rendering_context_2d.cc | 24 ++-
.../canvas2d/base_rendering_context_2d.cc | 24 +++-
third_party/blink/renderer/platform/BUILD.gn | 5 +-
.../platform/exported/web_runtime_features.cc | 8 +
.../platform/graphics/image_data_buffer.cc | 8 +
.../platform/graphics/static_bitmap_image.cc | 154 ++++++++++++++++++
.../platform/exported/web_runtime_features.cc | 8 ++
.../platform/graphics/image_data_buffer.cc | 8 ++
.../platform/graphics/static_bitmap_image.cc | 134 ++++++++++++++++++
.../platform/graphics/static_bitmap_image.h | 2 +
.../platform/runtime_enabled_features.json5 | 6 +
third_party/skia/include/core/SkPixmap.h | 16 +-
third_party/skia/include/core/SkPixmap.h | 16 +--
third_party/ungoogled/BUILD.gn | 10 ++
third_party/ungoogled/ungoogled_switches.cc | 15 ++
third_party/ungoogled/ungoogled_switches.h | 17 ++
25 files changed, 355 insertions(+), 16 deletions(-)
third_party/ungoogled/ungoogled_switches.h | 17 +++
25 files changed, 335 insertions(+), 16 deletions(-)
create mode 100755 cromite_flags/chrome/browser/about_flags_cc/Multiple-fingerprinting-mitigations.inc
create mode 100644 third_party/ungoogled/BUILD.gn
create mode 100644 third_party/ungoogled/ungoogled_switches.cc
@@ -512,7 +512,7 @@ diff --git a/third_party/blink/renderer/platform/graphics/static_bitmap_image.cc
namespace blink {
scoped_refptr<StaticBitmapImage> StaticBitmapImage::Create(
@@ -114,4 +119,153 @@ void StaticBitmapImage::DrawHelper(cc::PaintCanvas* canvas,
@@ -114,4 +119,133 @@ void StaticBitmapImage::DrawHelper(cc::PaintCanvas* canvas,
ToSkiaRectConstraint(draw_options.clamping_mode));
}
@@ -524,20 +524,16 @@ diff --git a/third_party/blink/renderer/platform/graphics/static_bitmap_image.cc
+ const SkImageInfo& info = src_data.info();
+ auto w = info.width() - srcX, h = info.height() - srcY;
+
+ // skip tiny images; info.width()/height() can also be 0
+ if ((w < 8) || (h < 8)) {
+ if (w <= 0 || h <= 0) {
+ return;
+ }
+
+ // generate the first random number here
+ double shuffleX = base::RandDouble();
+
+ // cap maximum pixels to change
+ auto pixels = (w + h) / 8;
+ if (pixels > 100) {
+ pixels = 100;
+ } else if (pixels < 2) {
+ pixels = 2;
+ } else if (pixels < 1) {
+ pixels = 1;
+ }
+
+ auto colorType = info.colorType();
@@ -545,13 +541,9 @@ diff --git a/third_party/blink/renderer/platform/graphics/static_bitmap_image.cc
+
+ DLOG(INFO) << "BRM: ShuffleSubchannelColorData() w=" << w << " h=" << h << " colorType=" << colorType << " fRowBytes=" << fRowBytes;
+
+ // second random number (for y/height)
+ double shuffleY = base::RandDouble();
+
+ // calculate random coordinates using bisection
+ auto currentW = w, currentH = h;
+ for(;pixels >= 0; pixels--) {
+ int x = currentW * shuffleX, y = currentH * shuffleY;
+ for (; pixels > 0; pixels--) {
+ int x = base::RandInt(0, w - 1);
+ int y = base::RandInt(0, h - 1);
+
+ // calculate randomisation amounts for each RGB component
+ uint8_t shuffleR = base::RandInt(0, 4);
@@ -648,18 +640,6 @@ diff --git a/third_party/blink/renderer/platform/graphics/static_bitmap_image.cc
+ LOG(WARNING) << "BRM: ShuffleSubchannelColorData(): Ignoring pixel format";
+ return;
+ }
+
+ // keep bisecting or reset current width/height as needed
+ if (x == 0) {
+ currentW = w;
+ } else {
+ currentW = x;
+ }
+ if (y == 0) {
+ currentH = h;
+ } else {
+ currentH = y;
+ }
+ }
+}
+
@@ -2,8 +2,45 @@ From: uazo <uazo@users.noreply.github.com>
Date: Tue, 20 Sep 2022 07:20:01 +0000
Subject: Partition blobs by top frame URL
Verifies that the blob was created with the same top frame URL
or, if not defined, by the same agent cluster.
Introduce a global site-isolation mechanism in Cromite that strictly
partitions the registration, resolution, and token exchange of Blob
URLs based on the top-level frame's site identity. This enforces
robust W3C Storage Partitioning guarantees and neutralizes cross-
partition data exfiltration vectors.
Global Architecture
By default, standard Chromium allows cross-site contexts and identical
third-party iframes to share or guess Blob URL references. This patch
seals these privacy leaks by modifying the entire public URL pipeline
across Blink and the Browser Process:
1. Renderer-Side Context Resolution (Blink): Restructures
PublicURLManager and introduces a centralized helper
(GetInsecureTopLevelSite) to safely compute and propagate the
caller's active top-level site partition. It cleanly differentiates
between graphical windows/iframes and asynchronous background
environments (Dedicated Workers and Service Workers). Service
Workers derive their boundary directly from their browser-validated
StorageKey to maintain first-party compliance while eliminating
historical null-pointer crash surfaces.
2. Intentional Scope Restrictions: To guarantee absolute isolation,
Blob URL support is deliberately dropped for Shared Workers, cutting
off unpartitioned cross-context communication channels.
3. Mojo IPC and Browser Validation (Storage): Extends the BlobURLStore
IPC interface (Register, ResolveAsURLLoaderFactory,
ResolveAsBlobURLToken) to mandate top-level site wire parameters.
The storage backend enforces a strict, deterministic
IsSamePartition() validation check, dropping unauthorized
cross-partition requests on the floor downstream of vanilla
Chromium's native defenses.
This global framework ensures that a Blob URL remains rigidly confined
and sandboxed within the specific top-level site partition that
originally spawned it, drastically enhancing Cromite's privacy profile
without impacting standard web platform compatibility.
Original License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html
License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html
@@ -12,12 +49,12 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html
.../Partition-blobs-by-top-frame-URL.inc | 1 +
storage/browser/blob/blob_url_registry.cc | 31 +++++++++-
storage/browser/blob/blob_url_registry.h | 11 +++-
storage/browser/blob/blob_url_store_impl.cc | 62 +++++++++++++++++--
storage/browser/blob/blob_url_store_impl.cc | 58 +++++++++++++++++--
storage/browser/blob/blob_url_store_impl.h | 15 ++++-
storage/browser/blob/features.cc | 1 +
.../public/mojom/blob/blob_url_store.mojom | 13 +++-
.../core/fileapi/public_url_manager.cc | 37 ++++++++++-
9 files changed, 158 insertions(+), 15 deletions(-)
.../public/mojom/blob/blob_url_store.mojom | 13 ++++-
.../core/fileapi/public_url_manager.cc | 57 +++++++++++++++++-
9 files changed, 174 insertions(+), 15 deletions(-)
create mode 100644 cromite_flags/third_party/blink/common/features_cc/Partition-blobs-by-top-frame-URL.inc
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -137,7 +174,7 @@ diff --git a/storage/browser/blob/blob_url_registry.h b/storage/browser/blob/blo
diff --git a/storage/browser/blob/blob_url_store_impl.cc b/storage/browser/blob/blob_url_store_impl.cc
--- a/storage/browser/blob/blob_url_store_impl.cc
+++ b/storage/browser/blob/blob_url_store_impl.cc
@@ -115,9 +115,35 @@ BlobURLStoreImpl::~BlobURLStoreImpl() {
@@ -115,9 +115,33 @@ BlobURLStoreImpl::~BlobURLStoreImpl() {
}
}
@@ -148,13 +185,11 @@ diff --git a/storage/browser/blob/blob_url_store_impl.cc b/storage/browser/blob/
+ bool is_same_partition = false;
+ const std::optional<net::SchemefulSite>& top_level_site =
+ registry_->GetUnsafeTopLevelSite(blob_url);
+ const std::optional<base::UnguessableToken> agent_cluster_id =
+ registry_->GetUnsafeAgentClusterID(blob_url);
+ if (top_level_site.has_value()) {
+ is_same_partition = (top_level_site == unsafe_top_level_site);
+ } else {
+ is_same_partition = (agent_cluster_id == unsafe_agent_cluster_id);
+ }
+ // const std::optional<base::UnguessableToken> agent_cluster_id =
+ // registry_->GetUnsafeAgentClusterID(blob_url);
+ // LOG(INFO) << "---BlobURLStoreImpl "
+ // << " is_same_partition=" << is_same_partition
+ // << " blob_url=" << blob_url
@@ -173,7 +208,7 @@ diff --git a/storage/browser/blob/blob_url_store_impl.cc b/storage/browser/blob/
RegisterCallback callback) {
// TODO(crbug.com/40061399): Generate blob URLs here, rather than
// validating the URLs the renderer process generated.
@@ -125,10 +151,18 @@ void BlobURLStoreImpl::Register(
@@ -125,10 +149,18 @@ void BlobURLStoreImpl::Register(
std::move(callback).Run();
return;
}
@@ -193,7 +228,7 @@ diff --git a/storage/browser/blob/blob_url_store_impl.cc b/storage/browser/blob/
urls_.insert(url);
std::move(callback).Run();
}
@@ -150,7 +184,7 @@ bool BlobURLStoreImpl::ShouldPartitionBlobUrlAccess(
@@ -150,7 +182,7 @@ bool BlobURLStoreImpl::ShouldPartitionBlobUrlAccess(
features::kBlockCrossPartitionBlobUrlFetching) &&
!partitioning_disabled_by_policy_;
@@ -202,7 +237,7 @@ diff --git a/storage/browser/blob/blob_url_store_impl.cc b/storage/browser/blob/
has_storage_access_handle &&
mapping_status ==
BlobUrlRegistry::MappingStatus::
@@ -160,7 +194,9 @@ bool BlobURLStoreImpl::ShouldPartitionBlobUrlAccess(
@@ -160,7 +192,9 @@ bool BlobURLStoreImpl::ShouldPartitionBlobUrlAccess(
void BlobURLStoreImpl::ResolveAsURLLoaderFactory(
const GURL& url,
@@ -213,7 +248,7 @@ diff --git a/storage/browser/blob/blob_url_store_impl.cc b/storage/browser/blob/
if (!registry_) {
BlobURLLoaderFactory::Create(mojo::NullRemote(), url, std::move(receiver));
return;
@@ -183,6 +219,7 @@ void BlobURLStoreImpl::ResolveAsURLLoaderFactory(
@@ -183,6 +217,7 @@ void BlobURLStoreImpl::ResolveAsURLLoaderFactory(
if (IsBlobUrlAccessCrossPartitionSameOrigin(mapping_status)) {
if (ShouldPartitionBlobUrlAccess(has_storage_access_handle,
mapping_status)) {
@@ -221,21 +256,20 @@ diff --git a/storage/browser/blob/blob_url_store_impl.cc b/storage/browser/blob/
partitioning_blob_url_closure_.Run(
url, blink::mojom::PartitioningBlobURLInfo::
kBlockedCrossPartitionFetching);
@@ -194,6 +231,13 @@ void BlobURLStoreImpl::ResolveAsURLLoaderFactory(
@@ -194,6 +229,12 @@ void BlobURLStoreImpl::ResolveAsURLLoaderFactory(
}
}
+ if (!IsSamePartition(url, unsafe_agent_cluster_id, unsafe_top_level_site)) {
+ // LOG(INFO) << "---ResolveAsURLLoaderFactory blocked by IsSamePartition" << url;
+ BlobURLLoaderFactory::Create(mojo::NullRemote(), url, std::move(receiver));
+ //std::move(callback).Run(std::nullopt, std::nullopt);
+ return;
+ }
+ // LOG(INFO) << "---ResolveAsURLLoaderFactory allowed " << url;
BlobURLLoaderFactory::Create(registry_->GetBlobFromUrl(url), url,
std::move(receiver));
}
@@ -201,7 +245,9 @@ void BlobURLStoreImpl::ResolveAsURLLoaderFactory(
@@ -201,7 +242,9 @@ void BlobURLStoreImpl::ResolveAsURLLoaderFactory(
void BlobURLStoreImpl::ResolveAsBlobURLToken(
const GURL& url,
mojo::PendingReceiver<blink::mojom::BlobURLToken> token,
@@ -246,7 +280,7 @@ diff --git a/storage/browser/blob/blob_url_store_impl.cc b/storage/browser/blob/
// This function is known to be heap allocation heavy and performance
// critical. Extra memory safety checks can introduce regression
// (https://crbug.com/414710225) and these are disabled here.
@@ -218,6 +264,7 @@ void BlobURLStoreImpl::ResolveAsBlobURLToken(
@@ -218,6 +261,7 @@ void BlobURLStoreImpl::ResolveAsBlobURLToken(
registry_->IsUrlMapped(BlobUrlUtils::ClearUrlFragment(url),
storage_key_);
if (IsBlobUrlAccessCrossPartitionSameOrigin(mapping_status)) {
@@ -254,13 +288,12 @@ diff --git a/storage/browser/blob/blob_url_store_impl.cc b/storage/browser/blob/
if (ShouldPartitionBlobUrlAccess(has_storage_access_handle,
mapping_status)) {
partitioning_blob_url_closure_.Run(
@@ -228,12 +275,17 @@ void BlobURLStoreImpl::ResolveAsBlobURLToken(
@@ -228,12 +272,16 @@ void BlobURLStoreImpl::ResolveAsBlobURLToken(
partitioning_blob_url_closure_.Run(url, std::nullopt);
}
}
+ if (!IsSamePartition(url, unsafe_agent_cluster_id, unsafe_top_level_site)) {
+ // LOG(INFO) << "---ResolveAsBlobURLToken blocked by IsSamePartition" << url;
+ //std::move(callback).Run(std::nullopt);
+ return;
+ }
@@ -371,68 +404,97 @@ diff --git a/third_party/blink/public/mojom/blob/blob_url_store.mojom b/third_pa
diff --git a/third_party/blink/renderer/core/fileapi/public_url_manager.cc b/third_party/blink/renderer/core/fileapi/public_url_manager.cc
--- a/third_party/blink/renderer/core/fileapi/public_url_manager.cc
+++ b/third_party/blink/renderer/core/fileapi/public_url_manager.cc
@@ -61,6 +61,25 @@ static void RemoveFromNullOriginMapIfNecessary(const KURL& blob_url) {
@@ -39,8 +39,10 @@
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/fileapi/url_registry.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/workers/dedicated_worker_global_scope.h"
#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
#include "third_party/blink/renderer/core/workers/worklet_global_scope.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h"
#include "third_party/blink/renderer/platform/blob/blob_data.h"
#include "third_party/blink/renderer/platform/blob/blob_url.h"
#include "third_party/blink/renderer/platform/blob/blob_url_null_origin_map.h"
@@ -61,6 +63,49 @@ static void RemoveFromNullOriginMapIfNecessary(const KURL& blob_url) {
BlobURLNullOriginMap::GetInstance()->Remove(blob_url);
}
+static std::optional<BlinkSchemefulSite> GetInsecureTopLevelSite(
+ ExecutionContext* execution_context) {
+ std::optional<BlinkSchemefulSite> top_level_site;
+ if (execution_context->IsWindow()) {
+ auto* window = To<LocalDOMWindow>(execution_context);
+ if (window->top() && window->top()->GetFrame()) {
+ top_level_site = BlinkSchemefulSite(window->top()
+ ->GetFrame()
+ ->GetSecurityContext()
+ ->GetSecurityOrigin());
+ if (!execution_context) {
+ return std::nullopt;
+ }
+ } else if (auto* worker_global_scope =
+ DynamicTo<WorkerGlobalScope>(execution_context)) {
+ top_level_site = BlinkSchemefulSite(
+ worker_global_scope->top_level_frame_security_origin());
+
+ // Window / Iframe (Secure and partitionable context)
+ if (auto* window = DynamicTo<LocalDOMWindow>(execution_context)) {
+ // LOG(INFO) << "--is window";
+ return window->GetStorageKey().GetTopLevelSite();
+ }
+ return top_level_site;
+
+ // Workers
+ if (auto* worker = DynamicTo<WorkerGlobalScope>(execution_context)) {
+ // We explicitly exclude Shared Workers from Blob support
+ if (execution_context->IsSharedWorkerGlobalScope()) {
+ // LOG(INFO) << "--is shared worker";
+ return std::nullopt;
+ }
+
+ // Service Workers and Dedicated Workers continue to use the 3PSP secure flow if set
+ if (worker->top_level_frame_security_origin()) {
+ // LOG(INFO) << "--is worker with top level frame";
+ return BlinkSchemefulSite(worker->top_level_frame_security_origin());
+ }
+
+ // Dedicated Workers are allowed to continue using their own origin.
+ if (auto* dedicated = DynamicTo<DedicatedWorkerGlobalScope>(worker)) {
+ // LOG(INFO) << "--is dedicated";
+ return BlinkSchemefulSite(dedicated->GetSecurityOrigin());
+ }
+
+ if (auto* service_worker = DynamicTo<ServiceWorkerGlobalScope>(worker)) {
+ // LOG(INFO) << "--is service worker";
+ const blink::StorageKey& storage_key = service_worker->storage_key();
+ return BlinkSchemefulSite(storage_key.top_level_site());
+ }
+ }
+
+ // LOG(INFO) << "--is other";
+ return std::nullopt;
+}
+
} // namespace
PublicURLManager::PublicURLManager(ExecutionContext* execution_context)
@@ -158,7 +177,17 @@ String PublicURLManager::RegisterURL(URLRegistrable* registrable) {
@@ -158,7 +203,9 @@ String PublicURLManager::RegisterURL(URLRegistrable* registrable) {
mojo::PendingReceiver<mojom::blink::Blob> blob_receiver =
blob_remote.InitWithNewPipeAndPassReceiver();
- GetBlobURLStore().Register(std::move(blob_remote), url);
+ std::optional<BlinkSchemefulSite> top_level_site;
+ if (GetExecutionContext()->IsWindow()) {
+ auto* window = To<LocalDOMWindow>(GetExecutionContext());
+ if (window->top() && window->top()->GetFrame()) {
+ top_level_site = BlinkSchemefulSite(window->top()
+ ->GetFrame()
+ ->GetSecurityContext()
+ ->GetSecurityOrigin());
+ }
+ }
+ GetBlobURLStore().Register(std::move(blob_remote), url, GetExecutionContext()->GetAgentClusterID(), top_level_site);
+ GetBlobURLStore().Register(std::move(blob_remote), url,
+ GetExecutionContext()->GetAgentClusterID(),
+ GetInsecureTopLevelSite(GetExecutionContext()));
mojo_urls_.insert(url_string);
registrable->CloneMojoBlob(std::move(blob_receiver));
@@ -208,7 +237,8 @@ void PublicURLManager::Resolve(
@@ -208,7 +255,9 @@ void PublicURLManager::Resolve(
DCHECK(url.ProtocolIs("blob"));
- GetBlobURLStore().ResolveAsURLLoaderFactory(url, std::move(factory_receiver));
+ GetBlobURLStore().ResolveAsURLLoaderFactory(url, std::move(factory_receiver),
+ GetExecutionContext()->GetAgentClusterID(), GetInsecureTopLevelSite(GetExecutionContext()));
+ GetExecutionContext()->GetAgentClusterID(),
+ GetInsecureTopLevelSite(GetExecutionContext()));
}
void PublicURLManager::ResolveAsBlobURLToken(
@@ -221,7 +251,8 @@ void PublicURLManager::ResolveAsBlobURLToken(
@@ -221,7 +270,9 @@ void PublicURLManager::ResolveAsBlobURLToken(
DCHECK(url.ProtocolIs("blob"));
GetBlobURLStore().ResolveAsBlobURLToken(url, std::move(token_receiver),
- is_top_level_navigation);
+ is_top_level_navigation,
+ GetExecutionContext()->GetAgentClusterID(), GetInsecureTopLevelSite(GetExecutionContext()));
+ GetExecutionContext()->GetAgentClusterID(),
+ GetInsecureTopLevelSite(GetExecutionContext()));
}
void PublicURLManager::ContextDestroyed() {
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,115 @@
From: uazo <uazo@users.noreply.github.com>
Date: Fri, 10 Jul 2026 06:28:01 +0000
Subject: Reduce input capability fingerprinting through normalization
Reduce the amount of hardware-specific information exposed through pointer and
touch capability APIs.
Normalize pointer type, hover capability, and maximum touch points to common
profiles instead of exposing the exact input hardware configuration.
This avoids exposing differences between devices with similar usage patterns,
such as desktop systems with optional touchscreen hardware.
License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html
---
.../java/src/org/chromium/ui/base/TouchDevice.java | 10 +++++-----
ui/base/pointer/pointer_device_linux.cc | 4 ++++
ui/base/pointer/pointer_device_win.cc | 3 +++
3 files changed, 12 insertions(+), 5 deletions(-)
diff --git a/ui/android/java/src/org/chromium/ui/base/TouchDevice.java b/ui/android/java/src/org/chromium/ui/base/TouchDevice.java
--- a/ui/android/java/src/org/chromium/ui/base/TouchDevice.java
+++ b/ui/android/java/src/org/chromium/ui/base/TouchDevice.java
@@ -37,18 +37,17 @@ public class TouchDevice {
} else if (ContextUtils.getApplicationContext()
.getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT)) {
- return 2;
+ return 5;
} else if (ContextUtils.getApplicationContext()
.getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH)) {
- return 2;
+ return 5;
} else if (ContextUtils.getApplicationContext()
.getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN)) {
- return 1;
- } else {
- return 0;
+ return 5;
}
+ return 0;
}
/**
@@ -58,6 +57,7 @@ public class TouchDevice {
*/
@CalledByNative
private static int[] availablePointerAndHoverTypes() {
+ if ((true)) return new int[] {PointerType.COARSE, HoverType.NONE};
int pointerTypes = 0;
int hoverTypes = 0;
diff --git a/ui/base/pointer/pointer_device_linux.cc b/ui/base/pointer/pointer_device_linux.cc
--- a/ui/base/pointer/pointer_device_linux.cc
+++ b/ui/base/pointer/pointer_device_linux.cc
@@ -15,6 +15,7 @@ namespace ui {
namespace {
bool IsTouchDevicePresent() {
+ if ((true)) return false;
return !DeviceDataManager::GetInstance()->GetTouchscreenDevices().empty();
}
@@ -31,6 +32,7 @@ bool IsMouseOrTouchpadPresent() {
} // namespace
std::pair<int, int> GetAvailablePointerAndHoverTypesImpl() {
+ if ((true)) return {POINTER_TYPE_FINE, HOVER_TYPE_HOVER};
int pointer_types = IsTouchDevicePresent() ? POINTER_TYPE_COARSE : 0;
int hover_types = HOVER_TYPE_NONE;
if (IsMouseOrTouchpadPresent()) {
@@ -41,6 +43,7 @@ std::pair<int, int> GetAvailablePointerAndHoverTypesImpl() {
}
TouchScreensAvailability GetTouchScreensAvailability() {
+ if ((true)) return TouchScreensAvailability::NONE;
if (!IsTouchDevicePresent()) {
return TouchScreensAvailability::NONE;
}
@@ -51,6 +54,7 @@ TouchScreensAvailability GetTouchScreensAvailability() {
}
int MaxTouchPoints() {
+ if ((true)) return 0;
const std::vector<TouchscreenDevice>& touchscreen_devices =
DeviceDataManager::GetInstance()->GetTouchscreenDevices();
const auto& it = std::ranges::max_element(touchscreen_devices, {},
diff --git a/ui/base/pointer/pointer_device_win.cc b/ui/base/pointer/pointer_device_win.cc
--- a/ui/base/pointer/pointer_device_win.cc
+++ b/ui/base/pointer/pointer_device_win.cc
@@ -18,6 +18,7 @@ namespace ui {
namespace {
bool IsTouchDevicePresent() {
+ if ((true)) return false;
const int value = GetSystemMetrics(SM_DIGITIZER);
return (value & NID_READY) &&
((value & NID_INTEGRATED_TOUCH) || (value & NID_EXTERNAL_TOUCH));
@@ -48,6 +49,7 @@ PointerDevice ToPointerDevice(const POINTER_DEVICE_INFO& device) {
} // namespace
std::pair<int, int> GetAvailablePointerAndHoverTypesImpl() {
+ if ((true)) return {POINTER_TYPE_FINE, HOVER_TYPE_HOVER};
// `IsDeviceUsedAsATablet()` guarantees that the device has a touch screen and
// has no keyboard connected. On Windows 10 it means that it has verified with
// `GetSystemMetrics(SM_CONVERTIBLESLATEMODE)`.
@@ -73,6 +75,7 @@ TouchScreensAvailability GetTouchScreensAvailability() {
}
int MaxTouchPoints() {
+ if ((true)) return 0;
return IsTouchDevicePresent() ? GetSystemMetrics(SM_MAXIMUMTOUCHES) : 0;
}
--
@@ -15,6 +15,7 @@ License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html
chrome/browser/about_flags.cc | 6 +++---
.../browser/chrome_content_browser_client.cc | 11 +++++++++++
.../Set-the-screen-frame-rate-to-60-Hz.grdp | 9 +++++++++
components/viz/common/features.cc | 3 +++
.../common/frame_sinks/begin_frame_source.cc | 14 +++++++++++++-
.../common/frame_sinks/begin_frame_source.h | 1 +
.../frame_sinks/delay_based_time_source.cc | 2 +-
@@ -25,7 +26,7 @@ License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html
.../Set-the-screen-frame-rate-to-60-Hz.inc | 7 +++++++
.../core/animation/animation_clock.cc | 11 ++++++++---
.../core/view_transition/view_transition.cc | 2 ++
16 files changed, 120 insertions(+), 20 deletions(-)
17 files changed, 123 insertions(+), 20 deletions(-)
create mode 100644 chrome/browser/ui/android/strings/cromite_android_chrome_strings_grd/Set-the-screen-frame-rate-to-60-Hz.grdp
create mode 100644 cromite_flags/chrome/browser/about_flags_cc/Set-the-screen-frame-rate-to-60-Hz.inc
@@ -179,6 +180,26 @@ new file mode 100644
+ Throttle compositor frame rate to 60fps, even when VSync rate is higher.
+ </message>
+</grit-part>
diff --git a/components/viz/common/features.cc b/components/viz/common/features.cc
--- a/components/viz/common/features.cc
+++ b/components/viz/common/features.cc
@@ -22,6 +22,7 @@
#include "gpu/config/gpu_switches.h"
#include "media/media_buildflags.h"
#include "ui/gl/gl_switches.h"
+#include "cc/base/features.h"
#if BUILDFLAG(IS_ANDROID)
#include "base/android/device_info.h"
@@ -468,6 +469,8 @@ int MaxOverlaysConsidered() {
}
bool ShouldOnBeginFrameThrottleVideo() {
+ if (base::FeatureList::IsEnabled(features::kThrottleMainFrameTo60Hz))
+ return false;
return base::FeatureList::IsEnabled(features::kOnBeginFrameThrottleVideo);
}
diff --git a/components/viz/common/frame_sinks/begin_frame_source.cc b/components/viz/common/frame_sinks/begin_frame_source.cc
--- a/components/viz/common/frame_sinks/begin_frame_source.cc
+++ b/components/viz/common/frame_sinks/begin_frame_source.cc
@@ -23,9 +23,10 @@ License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html
.../compositor/CompositorViewHolder.java | 2 +-
.../layouts/LayoutManagerChromeTablet.java | 12 ++++----
...ngling-Ptr-Detection-via-BackupRefPtr.grdp | 9 ++++++
.../webapps/AddToHomescreenMediator.java | 4 +--
.../Enable-Partition-Alloc-BRP-Checks.inc | 11 +++++++
.../platform/wtf/allocator/partitions.cc | 10 +------
11 files changed, 76 insertions(+), 28 deletions(-)
12 files changed, 78 insertions(+), 30 deletions(-)
create mode 100644 chrome/browser/ui/android/strings/cromite_android_chrome_strings_grd/Supporting-Dangling-Ptr-Detection-via-BackupRefPtr.grdp
create mode 100644 cromite_flags/chrome/browser/about_flags_cc/Enable-Partition-Alloc-BRP-Checks.inc
@@ -210,7 +211,7 @@ diff --git a/chrome/android/java/res/xml/privacy_preferences.xml b/chrome/androi
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
@@ -722,8 +722,8 @@ public class CompositorViewHolder extends FrameLayout
@@ -721,8 +721,8 @@ public class CompositorViewHolder extends FrameLayout
mApplicationBottomInsetSupplier.getSupplier().removeObserver(mOnViewportInsetsChanged);
}
@@ -262,6 +263,24 @@ new file mode 100644
+ Enable checking raw pointer do not become dangling during their lifetime to prevent UAF and write a fixed cookie pattern at the end of each allocation to ensure there is no OOB write.
+ </message>
+</grit-part>
diff --git a/components/webapps/browser/android/java/src/org/chromium/components/webapps/AddToHomescreenMediator.java b/components/webapps/browser/android/java/src/org/chromium/components/webapps/AddToHomescreenMediator.java
--- a/components/webapps/browser/android/java/src/org/chromium/components/webapps/AddToHomescreenMediator.java
+++ b/components/webapps/browser/android/java/src/org/chromium/components/webapps/AddToHomescreenMediator.java
@@ -114,12 +114,12 @@ class AddToHomescreenMediator implements AddToHomescreenViewDelegate {
}
private void onFlowCompleted() {
+ mOnFlowCompleted.run();
+
if (mNativeAddToHomescreenMediator != 0) {
AddToHomescreenMediatorJni.get().destroy(mNativeAddToHomescreenMediator);
mNativeAddToHomescreenMediator = 0;
}
-
- mOnFlowCompleted.run();
}
@NativeMethods
diff --git a/cromite_flags/chrome/browser/about_flags_cc/Enable-Partition-Alloc-BRP-Checks.inc b/cromite_flags/chrome/browser/about_flags_cc/Enable-Partition-Alloc-BRP-Checks.inc
new file mode 100644
--- /dev/null
@@ -7,7 +7,6 @@ Pulling the edge to the right will go backwards, pulling it further forwards.
License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html
---
.../compositor/CompositorViewHolder.java | 1 +
.../GestureNavigationProperties.java | 4 +--
.../GestureNavigationViewBinder.java | 6 ++--
.../HistoryNavigationCoordinator.java | 4 +++
@@ -22,24 +21,13 @@ License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html
.../Use-browser-navigation-handler.inc | 12 +++++++
.../Use-browser-navigation-handler.inc | 3 ++
.../Use-browser-navigation-handler.inc | 1 +
15 files changed, 135 insertions(+), 17 deletions(-)
14 files changed, 134 insertions(+), 17 deletions(-)
create mode 100644 chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/cromite/sUseBrowserNavigationHandler.java
create mode 100644 chrome/browser/ui/android/strings/cromite_android_chrome_strings_grd/Use-browser-navigation-handler.grdp
create mode 100644 cromite_flags/chrome/browser/about_flags_cc/Use-browser-navigation-handler.inc
create mode 100644 cromite_flags/chrome/browser/flags/android/chrome_feature_list_cc/Use-browser-navigation-handler.inc
create mode 100644 cromite_flags/chrome/browser/flags/android/chrome_feature_list_h/Use-browser-navigation-handler.inc
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
@@ -113,6 +113,7 @@ import org.chromium.ui.util.MotionEventUtils;
import org.chromium.url.GURL;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/GestureNavigationProperties.java b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/GestureNavigationProperties.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/GestureNavigationProperties.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/GestureNavigationProperties.java
+82 -25
View File
@@ -9,9 +9,9 @@ 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 +++++
.../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 ++
@@ -19,23 +19,24 @@ Require: Content-settings-infrastructure.patch
.../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 +-
.../blink/renderer/core/css/media_values.cc | 9 +-
.../core/css/resolver/style_resolver.cc | 7 +-
.../blink/renderer/core/events/mouse_event.h | 19 +++-
.../renderer/core/events/pointer_event.h | 11 +++
.../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 +++-
.../renderer/core/frame/local_dom_window.cc | 52 +++++++-
.../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/local_frame_mojo_handler.cc | 5 +-
.../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(-)
.../blink/renderer/core/input/touch.cc | 17 ++-
third_party/blink/renderer/core/page/page.cc | 117 ++++++++++++++++++
third_party/blink/renderer/core/page/page.h | 11 ++
.../renderer/core/style/computed_style.h | 6 +
27 files changed, 476 insertions(+), 22 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
@@ -301,12 +302,19 @@ diff --git a/third_party/blink/renderer/core/css/css_properties.json5 b/third_pa
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) {
@@ -193,7 +193,14 @@ bool MediaValues::CalculateStrictMode(LocalFrame* frame) {
}
float MediaValues::CalculateDevicePixelRatio(LocalFrame* frame) {
- return frame->DevicePixelRatio();
+ return frame->DevicePixelRatio(false);
+ const double original_dpr =
+ frame->DevicePixelRatio(/*with_zoom_factor=*/false);
+
+ Page* page = frame->GetPage();
+ if (!page)
+ return 0;
+
+ return page->DevicePixelRatioForWeb(original_dpr);
}
bool MediaValues::CalculateDeviceSupportsHDR(LocalFrame* frame) {
@@ -439,17 +447,28 @@ diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_p
Page* page = frame->GetPage();
if (!page)
return 0;
@@ -1802,7 +1812,8 @@ double LocalDOMWindow::devicePixelRatio() const {
if (!GetFrame())
@@ -1799,10 +1809,18 @@ CSSStyleDeclaration* LocalDOMWindow::getComputedStyle(
}
double LocalDOMWindow::devicePixelRatio() const {
- if (!GetFrame())
+ LocalFrame* frame = GetFrame();
+ if (!frame)
return 0.0;
- return GetFrame()->DevicePixelRatio();
+ // never send the zoom factor override value
+ return GetFrame()->DevicePixelRatio(/*with_zoom_factor*/false);
+ const double original_dpr =
+ frame->DevicePixelRatio(/*with_zoom_factor=*/false);
+
+ Page* page = frame->GetPage();
+ if (!page)
+ return 0.0;
+
+ return page->DevicePixelRatioForWeb(original_dpr);
}
ScriptPromise<ScrollResult> LocalDOMWindow::scrollBy(ScriptState* script_state,
@@ -2439,6 +2450,23 @@ DOMWindow* LocalDOMWindow::open(v8::Isolate* isolate,
@@ -2439,6 +2457,23 @@ DOMWindow* LocalDOMWindow::open(v8::Isolate* isolate,
if (!completed_url.IsEmpty() || result.new_window)
result.frame->Navigate(frame_request, WebFrameLoadType::kStandard);
@@ -473,7 +492,7 @@ diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_p
// 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(
@@ -2490,6 +2525,15 @@ DOMWindow* LocalDOMWindow::openPictureInPictureWindow(
DCHECK(result.new_window);
result.frame->Navigate(frame_request, WebFrameLoadType::kStandard);
@@ -564,6 +583,21 @@ diff --git a/third_party/blink/renderer/core/frame/local_frame.h b/third_party/b
float text_zoom_factor_;
float css_zoom_factor_;
diff --git a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
--- a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
+++ b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
@@ -576,7 +576,10 @@ void LocalFrameMojoHandler::NotifyVirtualKeyboardOverlayRect(
const float window_to_viewport_factor =
page->GetChromeClient().WindowToViewportScalar(&local_frame_root, 1.0f);
const float zoom_factor = local_frame_root.LayoutZoomFactor();
- const float scale_factor = zoom_factor / window_to_viewport_factor;
+ float emulator_scale = WebLocalFrameImpl::FromFrame(local_frame_root)
+ ->LocalRootFrameWidget()
+ ->GetEmulatorScale();
+ const float scale_factor = zoom_factor / window_to_viewport_factor * emulator_scale;
gfx::Rect scaled_rect(keyboard_rect.x() / scale_factor,
keyboard_rect.y() / scale_factor,
keyboard_rect.width() / scale_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
@@ -749,7 +783,7 @@ diff --git a/third_party/blink/renderer/core/page/page.cc b/third_party/blink/re
namespace blink {
namespace {
@@ -1280,7 +1287,96 @@ void Page::UpdateAcceleratedCompositingSettings() {
@@ -1280,7 +1287,117 @@ void Page::UpdateAcceleratedCompositingSettings() {
}
}
@@ -765,6 +799,10 @@ diff --git a/third_party/blink/renderer/core/page/page.cc b/third_party/blink/re
+ || disable_screen_emulated_) {
+ isEnabled = false;
+ }
+ if (GetChromeClient().GetWebView()->AutoResizeMode()) {
+ isEnabled = false;
+ force = false;
+ }
+ if (isEnabled || force) {
+ // this is the maximum (and minimum) value which in percentage
+ // corresponds to +- 0.03%
@@ -802,6 +840,16 @@ diff --git a/third_party/blink/renderer/core/page/page.cc b/third_party/blink/re
+ // scale the widget size (and the screen size) by half_random scale factor
+ params.scale = 1 / (1.0 + half_random);
+
+ const double original_dpr =
+ frame->DevicePixelRatio(/*with_zoom_factor=*/false);
+
+ if (override_device_pixel_ratio_ == 0) {
+ constexpr double kDprBucketSize = 0.5;
+
+ override_device_pixel_ratio_ =
+ std::round(original_dpr / kDprBucketSize) * kDprBucketSize;
+ }
+
+ GetChromeClient().GetWebView()->EnableDeviceEmulation(params);
+
+ // set zoom factor
@@ -834,6 +882,13 @@ diff --git a/third_party/blink/renderer/core/page/page.cc b/third_party/blink/re
+ }
+}
+
+double Page::DevicePixelRatioForWeb(double original_dpr) const {
+ if (!is_screen_emulated_ || override_device_pixel_ratio_ == 0)
+ return original_dpr;
+
+ return override_device_pixel_ratio_;
+}
+
+void Page::DisableScreenEmulated() {
+ disable_screen_emulated_ = true;
+ GetChromeClient().GetWebView()->DisableDeviceEmulation();
@@ -849,18 +904,19 @@ diff --git a/third_party/blink/renderer/core/page/page.cc b/third_party/blink/re
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>,
@@ -536,6 +536,11 @@ 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();
+ double DevicePixelRatioForWeb(double original_dpr) const;
+
private:
friend class ScopedPagePauser;
class CloseTaskHandler;
@@ -708,6 +712,11 @@ class CORE_EXPORT Page final : public GarbageCollected<Page>,
@@ -708,6 +713,12 @@ class CORE_EXPORT Page final : public GarbageCollected<Page>,
// browser side FrameTree has the FrameTree::Type of kFencedFrame.
bool is_fenced_frame_tree_ = false;
@@ -868,6 +924,7 @@ diff --git a/third_party/blink/renderer/core/page/page.h b/third_party/blink/ren
+ bool disable_screen_emulated_ = false;
+ double override_window_scale_factor_ = 0;
+ double override_zoom_factor_ = 0;
+ double override_device_pixel_ratio_ = 0;
+
// This tracks the mode that the fenced frame is set to.
blink::FencedFrame::DeprecatedFencedFrameMode fenced_frame_mode_ =
+378
View File
@@ -0,0 +1,378 @@
# Android protected keyboard geometry
This document describes the architecture of Cromite's **Android Protected
Keyboard Geometry** patch. The patch prevents the on-screen keyboard from
changing page-observable geometry while keeping the editable element that
requested the IME usable.
The protection does not attempt to hide the fact that the user is typing. A
page can still observe focus, keyboard events, and changes produced by its own
application logic. The objective is narrower: do not disclose keyboard size
and geometry through viewport measurements, CSS, or the Virtual Keyboard API.
## Problem
Under the standard Android behavior, the IME can:
- shrink the native view containing Chromium;
- change the layout viewport and visual viewport;
- alter dynamic CSS viewport units and browser-controls dimensions;
- expose `navigator.virtualKeyboard.boundingRect`;
- populate the CSS `keyboard-inset-*` environment variables;
- produce measurable differences between keyboards, configurations, and
devices.
Using `overlays-content` alone avoids part of the resize, but does not solve
the problem: keyboard geometry remains available to the page and the IME can
cover the focused input.
The patch therefore separates two geometries:
- the **logical viewport**, kept stable and observed by Blink;
- the **physical viewport**, resized by Android and panned natively to keep the
input visible.
## View hierarchy
When the global kill switch is enabled, `CompositorViewHolder` creates this
hierarchy:
```text
CompositorViewHolder
└── ProtectedViewportScrollView
└── mScrollContent
└── mContent
├── CompositorView
└── tab ContentView
```
`ProtectedViewportScrollView` is a specialized `ScrollView`; it is not a
normal page scrolling area. `mContent` retains the neutral height observed
before the IME opens, while the outer `ScrollView` may shrink with the Android
window.
This creates physical pan range around Chromium content that has not been
resized. Moving the `ScrollView` does not directly change `window.scrollY` or
Blink's logical viewport dimensions.
When the global kill switch is disabled, the wrapper is not created and
`CompositorViewHolder` retains Chromium's original hierarchy. Changing the
kill switch therefore requires recreating the UI, normally by restarting the
browser.
## Policy and content setting
The Blink feature `AndroidProtectedKeyboardGeometry` is enabled by default and
acts as the global kill switch. Cromite's
`sAndroidProtectedKeyboardGeometry` Java class reads the same feature without
adding a new entry to `ChromeFeatureList.java`.
The effective decision is also controlled by the
`PROTECTED_KEYBOARD_GEOMETRY` content setting:
- `ALLOW`, the default: protection enabled;
- `BLOCK`: standard Chromium behavior;
- WebUI and extension pages: protection disabled;
- Android only;
- per-site exceptions supported.
Java stores the decision in `TabWebContentsObserver` for the current document.
The cache is invalidated when a new `WebContents` is initialized and after
every committed primary-main-frame navigation. `CompositorViewHolder` then
re-evaluates policy, resets transient state from the previous document, and
realigns the virtual-keyboard mode.
The renderer obtains the same decision through
`Page::IsAndroidProtectedKeyboardGeometryEnabled()`, which checks the feature,
the renderer content setting, and the current scheme. This avoids transporting
a second policy value through `VisualProperties`.
A content-setting change should be followed by a reload. This lets Java and
Blink start the new document with the same decision instead of changing the
geometry model in the middle of an active page.
## Geometry exposed to the page
While protection is enabled:
1. `ViewportData::GetVirtualKeyboardOverlaysContent()` forces
`overlays-content`, regardless of the page's request.
2. `CompositorViewHolder` uses `VirtualKeyboardMode.OVERLAYS_CONTENT` as its
default mode.
3. `LocalFrameMojoHandler::NotifyVirtualKeyboardOverlayRect()` sends an empty
rectangle to Blink observers instead of the real IME geometry.
4. `ProtectedViewportScrollView` keeps `mContent` at the largest neutral height
observed for the current width.
5. During an IME transition, browser-controls dimensions and insets returned
to Blink come from a protected snapshot.
Values that should remain invariant between the closed- and open-keyboard
states include at least:
- `window.innerHeight`;
- `document.documentElement.clientHeight`;
- `visualViewport.height`;
- `dvh`, `svh`, and `lvh` units;
- screen geometry;
- `navigator.virtualKeyboard.boundingRect`;
- `env(keyboard-inset-*)`.
The Virtual Keyboard API rectangle should be empty and its CSS insets should
be zero.
## Positioning the editable
Keeping Blink at its neutral dimensions prevents Android's normal resize path
from automatically moving the input above the keyboard. The patch therefore
reconstructs a physical target.
`ImeAdapterImpl` retains:
- the focused editable bounds received from Blink;
- the more precise caret bounds, when available through `CursorAnchorInfo`.
When Android confirms that the keyboard is visible, `ImeAdapterImpl` calls
`requestRectangleOnScreen()`. The caret is preferred and the editable
rectangle is used as a fallback. A collapsed caret is preserved as a
one-pixel-wide rectangle because `Rect.isEmpty()` considers zero-width
geometry empty.
`ProtectedViewportScrollView.requestChildRectangleOnScreen()`:
1. accepts the first request of the IME session;
2. converts the rectangle into container coordinates;
3. compensates for top controls shown for the editable;
4. brings coordinates that already include Chromium's content offset back
inside `mContent`;
5. retains the neutral space originally present below the target;
6. applies the pan after Android has delivered the new view size.
Later requests are acknowledged without replacing the target. A site cannot
repeatedly reposition the physical viewport during the same IME session. The
target is cleared when the keyboard closes, the document changes, or
protection is disabled.
The minimum pan brings the target's bottom edge into the visible area. When
neutral space exists below the input, the patch also attempts to preserve it
above the keyboard. The physically hidden portion of the bottom controls is
subtracted from that space, avoiding a visual tail that does not belong to the
page.
## Browser controls
Opening the keyboard can show the top controls, hide the bottom controls, and
change the insets sent to the renderer. Without protection, those transitions
would expose IME geometry through Blink again.
The patch captures a snapshot containing:
- full and minimum top- and bottom-controls heights;
- the inset used to size `WebContents`;
- the visible bottom-controls height;
- the viewport width for which the snapshot is valid;
- the inset tracking mode.
The snapshot can be captured synchronously before the IME animation when an
editable forces controls visibility. Callbacks before and after layout keep
the geometry exposed to Blink separate from the physically visible geometry.
`ActivityTabWebContentsDelegateAndroid` returns protected controls dimensions
during the transition. `CompositorViewHolder.updateWebContentsSize()` also
uses the protected inset when calculating the `WebContents` size.
The patch requires `BrowserControlsEarlyResize`. Cromite enables it in both
the C++ default and the Java safe default, and asserts the invariant when the
controls are about to be shown.
When a browser-controls transition changes editable geometry without changing
focus, `WebContents.updateFocusedElementBounds()` crosses JNI and Mojo to
`WebFrameWidgetImpl`. The renderer sends the focus geometry again, allowing
`ImeAdapterImpl` to refresh its target without simulating a new focus event.
## Scrolling and cc handoff
Native pan must not terminate normal page scrolling. A vertical gesture may
cross:
1. the physical range of `ProtectedViewportScrollView`;
2. an inner page scroller;
3. the root viewport managed by cc;
4. the physical range again when cc has no more content to consume.
### Android to cc
When the `ScrollView` reaches one of its limits, `overScrollBy()` separates
the consumed delta from the remaining delta. The remainder is sent through
`CompositorScrollDelegate` and `EventForwarder` as a compositor
`begin/update/end` sequence.
The sequence:
- uses the real gesture location for normal cc hit testing;
- does not force the root viewport;
- does not create a new DOM touch-event sequence;
- may end with a fling when the finger leaves the boundary with sufficient
velocity.
Axis selection is latched after touch slop. Horizontal gestures are not
consumed by the protected viewport; they remain available to Chromium
content and parent gesture handlers.
### cc to Android
An inner scroller may return `unused_scroll_delta` without setting
`did_overscroll_root`. Here, a *protected-viewport-generated sequence* means a
gesture sequence injected programmatically through `EventForwarder`, rather
than one originating from Android pointer dispatch. It is deliberately sent
with Chromium's `synthetic_scroll` field set to `false`, so it is not a Blink
synthetic-scroll event. `InputHandlerProxy` recognizes this sequence from
`target_viewport == false` and `pointer_count == 0`, then forwards the unused
delta and maintains its accumulated value.
`OverscrollControllerAndroid` recognizes a candidate sequence but does not
call Java reentrantly during `GestureScrollBegin`. The first overscroll
notification asks the Java view whether physical range remains available. If
Java accepts:
```text
InputHandlerProxy
→ OverscrollControllerAndroid
→ OverscrollRefresh
→ OverscrollRefreshHandler
→ SwipeRefreshHandler
→ ProtectedViewportScrollView
```
`SwipeRefreshHandler` locates the protected viewport by walking up from the
tab's `ContentView`. The cumulative value received from cc is applied relative
to the physical origin retained when the handoff began.
The path reuses the overscroll-refresh bridge, but it does not trigger pull to
refresh and does not transfer touch ownership back from Viz. A replacement
scroll begin, scroll end, fling, or `OverscrollControllerAndroid::Disable()`
explicitly ends the handoff.
## Internal state
`ProtectedViewportScrollView` separates state by responsibility:
| State | Responsibility |
| --- | --- |
| `BrowserControlsProtectionState` | Browser-controls snapshot, baselines, and latches |
| `ViewportPanState` | Requested rectangle, clearance, and unlocked physical range |
| `CompositorHandoffState` | Open synthetic protocol, forwarded delta, and pull origin |
| `GestureRoutingState` | Horizontal, vertical, and parent-deferred routing |
| IME flags | Running animation and closing direction |
These states have different lifecycles. Resetting a document is not the same
as ending a compositor gesture; similarly, enabling or disabling policy is not
equivalent to receiving the end of an IME animation.
## Diagnostics
`ProtectedViewportScrollView` contains diagnostics disabled by
`DEBUG_DIAGNOSTICS`. They cover:
- browser-controls snapshots and transitions;
- IME animation;
- pan requests and calculations;
- axis selection;
- handoff between the `ScrollView` and cc.
In assert-enabled builds, the protected viewport has a magenta background.
Visible magenta pixels indicate exposure of the native container rather than
Chromium content or browser UI.
Geometry logs in `ImeAdapterImpl` use the existing `DEBUG_LOGS` switch. They
must not be enabled normally. Global logs temporarily added to
`GestureEventStreamValidator`, `InputHandlerProxy`, and
`OverscrollControllerAndroid` were investigation tools and are not part of
the final implementation.
## Limitations and non-goals
### Keyboard presence
The patch hides geometry, not every possible bit related to IME presence.
Focus, input, and keyboard events are required for page functionality.
Keyboard-layout normalization belongs to other Cromite protections.
### Fixed and sticky elements
The current physical pan moves Chromium's entire Android output. A CSS
`position: fixed` element therefore moves with the rest of the surface during
physical pan instead of remaining attached to the logical viewport.
A complete solution requires a protected cc offset that remains distinct from
logical scroll and is applied through the property trees. The problem,
including sticky positioning, clamping, and hit testing, is described in
[PIXEL_PERFECT.md](PIXEL_PERFECT.md).
### Internal pages
WebUI and extension pages are explicitly excluded by both the Java and Blink
policy checks. They retain Chromium's standard virtual-keyboard behavior and
are outside the protection and its testing contract.
### Live content-setting changes
Changing the geometry model in the middle of a document is not an objective.
A reload is required after changing the content setting.
## Verification
Chromium's automated test targets are not yet available in the Cromite build;
the patch has primarily been validated with the Android emulator and
BrowserStack campaigns. Automated coverage for the main lifecycles must be
added before final stabilization.
The minimum manual verification matrix should include:
1. keyboard closed → open → closed without losing focus;
2. browser controls visible and hidden when the IME opens;
3. configurations with and without bottom controls;
4. normal input, nested editable, and an editor with an inner scroller;
5. scroll and fling in both directions;
6. horizontal gestures;
7. closing the keyboard without blur;
8. switching tabs between sites with different policy;
9. reload, navigation, and history restoration;
10. rotation and system-inset changes;
11. Android gesture navigation and three-button navigation;
12. global feature and content setting disabled.
For each keyboard state, the JavaScript probe should collect at least:
```text
window.innerWidth / innerHeight / outerWidth / outerHeight
documentElement.clientWidth / clientHeight
visualViewport dimensions, offsets, and scale
screen and devicePixelRatio
100vh / 100dvh / 100svh / 100lvh
navigator.virtualKeyboard.overlaysContent
navigator.virtualKeyboard.boundingRect
env(keyboard-inset-top/right/bottom/left/width/height)
```
With protection enabled, opening and closing the IME must not produce
persistent geometry attributable to its size. The focused content must remain
reachable and scrolling must continue without jumps, accidental long-touch
menus, or invalid gesture sequences.
## Rebase-sensitive areas
The following areas require manual review after each Chromium update:
- construction and ownership of `CompositorView` and `ContentView` in
`CompositorViewHolder`;
- `keyboardInset`, controls-inset, and `WebContents` size calculation;
- `VirtualKeyboardMode` policy and lifecycle;
- top- and bottom-browser-controls callbacks;
- focus geometry and `CursorAnchorInfo` in `ImeAdapterImpl`;
- the `FrameWidgetInputHandler` and `WebFrameWidgetImpl` protocol;
- synthetic gesture creation in `EventForwarder`;
- `unused_scroll_delta` handling in `InputHandlerProxy`;
- overscroll state in `OverscrollControllerAndroid`;
- the `OverscrollRefreshHandler` bridge and `SwipeRefreshHandler` integration;
- renderer content-setting application in `Page` and `ViewportData`;
- Virtual Keyboard API notification in `LocalFrameMojoHandler`.
@@ -0,0 +1,55 @@
https://badblock.celenity.dev/abp/badblock_lite.txt = badblock_lite.txt
https://easylist-downloads.adblockplus.org/abp-filters-anti-cv.txt = abp-filters-anti-cv.txt
https://easylist-downloads.adblockplus.org/abpindo+easylist.txt = abpindo+easylist.txt
https://easylist-downloads.adblockplus.org/abpindo.txt = abpindo.txt
https://easylist-downloads.adblockplus.org/abpvn+easylist.txt = abpvn+easylist.txt
https://easylist-downloads.adblockplus.org/abpvn.txt = abpvn.txt
https://easylist-downloads.adblockplus.org/bulgarian_list+easylist.txt = bulgarian_list+easylist.txt
https://easylist-downloads.adblockplus.org/bulgarian_list.txt = bulgarian_list.txt
https://easylist-downloads.adblockplus.org/dandelion_sprouts_nordic_filters+easylist.txt = dandelion_sprouts_nordic_filters+easylist.txt
https://easylist-downloads.adblockplus.org/dandelion_sprouts_nordic_filters.txt = dandelion_sprouts_nordic_filters.txt
https://easylist-downloads.adblockplus.org/easylist.txt = easylist.txt
https://easylist-downloads.adblockplus.org/easylistchina+easylist.txt = easylistchina+easylist.txt
https://easylist-downloads.adblockplus.org/easylistchina.txt = easylistchina.txt
https://easylist-downloads.adblockplus.org/easylistczechslovak+easylist.txt = easylistczechslovak+easylist.txt
https://easylist-downloads.adblockplus.org/easylistczechslovak.txt = easylistczechslovak.txt
https://easylist-downloads.adblockplus.org/easylistdutch+easylist.txt = easylistdutch+easylist.txt
https://easylist-downloads.adblockplus.org/easylistdutch.txt = easylistdutch.txt
https://easylist-downloads.adblockplus.org/easylistgermany+easylist.txt = easylistgermany+easylist.txt
https://easylist-downloads.adblockplus.org/easylistgermany.txt = easylistgermany.txt
https://easylist-downloads.adblockplus.org/easylistitaly+easylist.txt = easylistitaly+easylist.txt
https://easylist-downloads.adblockplus.org/easylistitaly.txt = easylistitaly.txt
https://easylist-downloads.adblockplus.org/easylistlithuania+easylist.txt = easylistlithuania+easylist.txt
https://easylist-downloads.adblockplus.org/easylistlithuania.txt = easylistlithuania.txt
https://easylist-downloads.adblockplus.org/easylistpolish+easylist.txt = easylistpolish+easylist.txt
https://easylist-downloads.adblockplus.org/easylistpolish.txt = easylistpolish.txt
https://easylist-downloads.adblockplus.org/easylistportuguese+easylist.txt = easylistportuguese+easylist.txt
https://easylist-downloads.adblockplus.org/easylistportuguese.txt = easylistportuguese.txt
https://easylist-downloads.adblockplus.org/easylistspanish+easylist.txt = easylistspanish+easylist.txt
https://easylist-downloads.adblockplus.org/easylistspanish.txt = easylistspanish.txt
https://easylist-downloads.adblockplus.org/fanboy-notifications.txt = fanboy-notifications.txt
https://easylist-downloads.adblockplus.org/fanboy-social.txt = fanboy-social.txt
https://easylist-downloads.adblockplus.org/global-filters+easylist.txt = global-filters+easylist.txt
https://easylist-downloads.adblockplus.org/global-filters.txt = global-filters.txt
https://easylist-downloads.adblockplus.org/hufilter.txt = hufilter.txt
https://easylist-downloads.adblockplus.org/indianlist+easylist.txt = indianlist+easylist.txt
https://easylist-downloads.adblockplus.org/indianlist.txt = indianlist.txt
https://easylist-downloads.adblockplus.org/israellist+easylist.txt = israellist+easylist.txt
https://easylist-downloads.adblockplus.org/israellist.txt = israellist.txt
https://easylist-downloads.adblockplus.org/japanese-filters+easylist.txt = japanese-filters+easylist.txt
https://easylist-downloads.adblockplus.org/japanese-filters.txt = japanese-filters.txt
https://easylist-downloads.adblockplus.org/koreanlist+easylist.txt = koreanlist+easylist.txt
https://easylist-downloads.adblockplus.org/koreanlist.txt = koreanlist.txt
https://easylist-downloads.adblockplus.org/latvianlist+easylist.txt = latvianlist+easylist.txt
https://easylist-downloads.adblockplus.org/latvianlist.txt = latvianlist.txt
https://easylist-downloads.adblockplus.org/liste_ar+liste_fr+easylist.txt = liste_ar+liste_fr+easylist.txt
https://easylist-downloads.adblockplus.org/liste_ar.txt = liste_ar.txt
https://easylist-downloads.adblockplus.org/liste_fr+easylist.txt = liste_fr+easylist.txt
https://easylist-downloads.adblockplus.org/liste_fr.txt = liste_fr.txt
https://easylist-downloads.adblockplus.org/rolist+easylist.txt = rolist+easylist.txt
https://easylist-downloads.adblockplus.org/rolist.txt = rolist.txt
https://easylist-downloads.adblockplus.org/ruadlist+easylist.txt = ruadlist+easylist.txt
https://easylist-downloads.adblockplus.org/ruadlist.txt = ruadlist.txt
https://easylist-downloads.adblockplus.org/turkish-filters+easylist.txt = turkish-filters+easylist.txt
https://easylist-downloads.adblockplus.org/turkish-filters.txt = turkish-filters.txt
https://raw.githubusercontent.com/badmojr/1Hosts/master/Lite/adblock.txt = badmojr-1Hosts-master-Lite-adblock.txt