diff --git a/AUTHORS b/AUTHORS index f1773d0..251be5a 100644 --- a/AUTHORS +++ b/AUTHORS
@@ -138,6 +138,7 @@ Arnaud Renevier <a.renevier@samsung.com> Arpita Bahuguna <a.bah@samsung.com> Arthur Lussos <developer0420@gmail.com> +Artin Lindqvist <artin.lindqvist.chromium@gmail.com> Artur Akerberg <artur.aker@gmail.com> Arun Kulkarni <kulkarni.a@samsung.com> Arun Kumar <arun87.kumar@samsung.com> @@ -764,7 +765,7 @@ Lukas Lihotzki <lukas@lihotzki.de> Lukasz Krakowiak <lukasz.krakowiak@mobica.com> Luke Inman-Semerau <luke.semerau@gmail.com> -Luke Seunghoe Gu <gulukesh@gmail.com> +Luke Gu <gulukesh@gmail.com> Luke Zarko <lukezarko@gmail.com> Luoxi Pan <l.panpax@gmail.com> Lu Yahan <yahan@iscas.ac.cn>
diff --git a/DEPS b/DEPS index 6d66a596..97c34429 100644 --- a/DEPS +++ b/DEPS
@@ -299,15 +299,15 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': 'e09e7abe45968482bcb1a1fa4460e84252a675e3', + 'skia_revision': '2e7bee153d7841be4da26b30dc878221671408c5', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': '692feefd89543e0f199fd28b2edb736ada3bbde4', + 'v8_revision': 'fe24d473144bbc62073f1f0e544e5e69a29e554b', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': 'f524e4b8a2448ec919d3a1c4d64396fc5b56a1bc', + 'angle_revision': '8875ba4e4cd28a8a08d51f60ea8bc967cb26659d', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -374,7 +374,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling CrossBench # and whatever else without interference from each other. - 'crossbench_revision': '27639d495e1cec411073bc82ba1fe368ce0ca89a', + 'crossbench_revision': '0941f19d9b1bab30137d9fcad6ee2ee44d338913', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -426,7 +426,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': '9efc12d4af06a27468640a54dbe2a121667dad11', + 'dawn_revision': '35df626efa2ac803d9a578594914d26dc4f27ab6', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -462,7 +462,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'cros_components_revision': 'e4973afdd5c3715ae56cfcf94c07f61f40ddcca7', + 'cros_components_revision': '28731ebe744897c527854c2acdcd2f89f1496384', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -764,7 +764,7 @@ 'src/clank': { 'url': 'https://chrome-internal.googlesource.com/clank/internal/apps.git' + '@' + - 'bb1015626a34c0c28351beceb09fd9996485b835', + 'fb4c24b186737efcb3eefadd72ca483fa7c83e45', 'condition': 'checkout_android and checkout_src_internal', }, @@ -773,7 +773,7 @@ }, 'src/ios/third_party/earl_grey2/src': { - 'url': Var('chromium_git') + '/external/github.com/google/EarlGrey.git' + '@' + 'dc932298481308087b192deca693e210bd11cd01', + 'url': Var('chromium_git') + '/external/github.com/google/EarlGrey.git' + '@' + 'dbea0d824daabf9ab39bdf5c33b80f8dc1bcccf5', 'condition': 'checkout_ios', }, @@ -863,7 +863,7 @@ 'packages': [ { 'package': 'chromium/rts/model/linux-amd64', - 'version': '5WbUil4KanfX4HN2rMFZwLHg0y6GiUTM3F3g6zGqMaAC', + 'version': 'hSJK7BIhg134I-atbtbh1PeQb36ZHLoJaBpw63atjqcC', }, ], 'dep_type': 'cipd', @@ -874,7 +874,7 @@ 'packages': [ { 'package': 'chromium/rts/model/mac-amd64', - 'version': 'HK8Sx9zMLY0YK0i3TaCoIVYKzqCmEsUuQvJDkoV10KYC', + 'version': 'MyjKKm3_Eu20R_JPzWADp2nhjBMSfR1LqE22nnklfGoC', }, ], 'dep_type': 'cipd', @@ -885,7 +885,7 @@ 'packages': [ { 'package': 'chromium/rts/model/windows-amd64', - 'version': 'GoOkuqQKE1qa6a0uZ5xURpZuf9_VVCxC7brsZY5IwlgC', + 'version': 'n3nZKPUmtU03AFVClGwDuUutlEgjEiYzq8BuPt9wVE0C', }, ], 'dep_type': 'cipd', @@ -1024,7 +1024,7 @@ 'packages': [ { 'package': 'chromium/third_party/android_build_tools/lint', - 'version': 'MSpv-kFDDSPO0SY0dLdHegUJcJT1Yy8cL9r3vlAZ9vkC', + 'version': 'NrP_GizJsQ_kr9O0WQlncRx1xdicjU4BFHi9pLPeTSIC', }, ], 'condition': 'checkout_android', @@ -1035,7 +1035,7 @@ 'packages': [ { 'package': 'chromium/third_party/android_build_tools/manifest_merger', - 'version': 'EbRaK62t9grqlZqL-JTd_zwM4t1u9fm1x4c2rLE0cqQC', + 'version': 'saMCpz15quEEWToMloh-A_rMqC0WSdJlyYTFvwAd840C', }, ], 'condition': 'checkout_android', @@ -1174,7 +1174,7 @@ # Tools used when building Chrome for Chrome OS. This affects both the Simple # Chrome workflow, as well as the chromeos-chrome ebuild. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '11fe1b6bc0051aacc08c9833c81e18e1bb25d876', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '4038ac8bd8f5b9fca8e0d344cf93216b36d36f3e', 'condition': 'checkout_chromeos', }, @@ -1206,13 +1206,13 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '9144b67c7f037577516ebdfe220997560bd01e14', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '03b4ba83f3be6bf61d87f13ce4b73eaa8d1e2c0f', 'src/third_party/devtools-frontend/src': Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), 'src/third_party/devtools-frontend-internal': { - 'url': 'https://chrome-internal.googlesource.com/devtools/devtools-internal.git' + '@' + '7142b2c0cc3092a21934cf9465ca43edb5b2ae4c', + 'url': 'https://chrome-internal.googlesource.com/devtools/devtools-internal.git' + '@' + '121754bf3a97650be9bc188355ed80b667bc4bad', 'condition': 'checkout_src_internal', }, @@ -1684,7 +1684,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + 'a92aaa264399b0a4dc2d8744d98edcc3d7438331', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '7c5fe42e47b51d5f745aa543a76b091bf3e0daa6', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1869,7 +1869,7 @@ Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '6c8361e98f1daba65902f5e2fc1297893ac14b67', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + 'ba3a1e2c26a81f2df683b43284447f5905416a41', + Var('webrtc_git') + '/src.git' + '@' + '419b6fcd080a7c6d50180c892f8a30581ccf9d34', # Wuffs' canonical repository is at github.com/google/wuffs, but we use # Skia's mirror of Wuffs, the same as in upstream Skia's DEPS file.
diff --git a/android_webview/BUILD.gn b/android_webview/BUILD.gn index c2abb03..baf14c2 100644 --- a/android_webview/BUILD.gn +++ b/android_webview/BUILD.gn
@@ -661,9 +661,9 @@ "//components/background_task_scheduler:background_task_scheduler_task_ids_java", "//components/component_updater/android:embedded_component_loader_java", "//components/content_capture/android:java", + "//components/content_relationship_verification/android:java", "//components/crash/android:handler_java", "//components/crash/android:java", - "//components/digital_asset_links/android:java", "//components/embedder_support/android:util_java", "//components/embedder_support/android:web_contents_delegate_java", "//components/embedder_support/android/metrics:java",
diff --git a/android_webview/browser/BUILD.gn b/android_webview/browser/BUILD.gn index b688485..a8a4fab 100644 --- a/android_webview/browser/BUILD.gn +++ b/android_webview/browser/BUILD.gn
@@ -237,10 +237,10 @@ "//components/url_matcher", # Called via JNI in CrashpadMain + "//components/content_relationship_verification", "//components/crash/android:crashpad_main", "//components/crash/content/browser", "//components/crash/core/app", - "//components/digital_asset_links", "//components/embedder_support/android:web_contents_delegate", "//components/embedder_support/android/metrics", "//components/google/core/common",
diff --git a/android_webview/browser/DEPS b/android_webview/browser/DEPS index e9da0d8..cd87e45 100644 --- a/android_webview/browser/DEPS +++ b/android_webview/browser/DEPS
@@ -15,9 +15,9 @@ "+components/cdm/browser", "+components/component_updater/android", "+components/component_updater/installer_policies", + "+components/content_relationship_verification", "+components/crash/content/browser", "+components/crash/core", - "+components/digital_asset_links", "+components/download/public/common", "+components/embedder_support", "+components/favicon_base",
diff --git a/android_webview/browser/aw_content_browser_client.cc b/android_webview/browser/aw_content_browser_client.cc index bc4b7ff..bb25951 100644 --- a/android_webview/browser/aw_content_browser_client.cc +++ b/android_webview/browser/aw_content_browser_client.cc
@@ -601,8 +601,9 @@ features::kWebViewRestrictSensitiveContent))) { auto* origin_verification_bridge = AwOriginVerificationSchedulerBridge::GetInstance(); - result.push_back(digital_asset_links::BrowserURLLoaderThrottle::Create( - origin_verification_bridge)); + result.push_back( + content_relationship_verification::BrowserURLLoaderThrottle::Create( + origin_verification_bridge)); } result.push_back(safe_browsing::BrowserURLLoaderThrottle::Create(
diff --git a/android_webview/browser/aw_origin_verification_scheduler_bridge.h b/android_webview/browser/aw_origin_verification_scheduler_bridge.h index 26a2d5d..e1b74bb 100644 --- a/android_webview/browser/aw_origin_verification_scheduler_bridge.h +++ b/android_webview/browser/aw_origin_verification_scheduler_bridge.h
@@ -8,13 +8,13 @@ #include "base/functional/callback.h" #include "base/no_destructor.h" -#include "components/digital_asset_links/browser_url_loader_throttle.h" +#include "components/content_relationship_verification/browser_url_loader_throttle.h" namespace android_webview { using OriginVerifierCallback = base::OnceCallback<void(bool /*verified*/)>; class AwOriginVerificationSchedulerBridge - : public digital_asset_links::BrowserURLLoaderThrottle:: + : public content_relationship_verification::BrowserURLLoaderThrottle:: OriginVerificationSchedulerBridge { public: static AwOriginVerificationSchedulerBridge* GetInstance();
diff --git a/android_webview/java/DEPS b/android_webview/java/DEPS index d756283..bf57d2f 100644 --- a/android_webview/java/DEPS +++ b/android_webview/java/DEPS
@@ -1,6 +1,6 @@ include_rules = [ "+components/autofill/android/java", - "+components/digital_asset_links/android/java", + "+components/content_relationship_verification/android/java", "+components/embedder_support/android/java", "+components/embedder_support/android/metrics/java", "+components/navigation_interception/android/java",
diff --git a/android_webview/java/src/org/chromium/android_webview/AwOriginVerificationScheduler.java b/android_webview/java/src/org/chromium/android_webview/AwOriginVerificationScheduler.java index 95533ebf..cdb5de2 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwOriginVerificationScheduler.java +++ b/android_webview/java/src/org/chromium/android_webview/AwOriginVerificationScheduler.java
@@ -11,9 +11,9 @@ import org.chromium.base.Callback; import org.chromium.base.ContextUtils; import org.chromium.base.ThreadUtils; -import org.chromium.components.digital_asset_links.OriginVerificationScheduler; -import org.chromium.components.digital_asset_links.OriginVerifier; -import org.chromium.components.digital_asset_links.OriginVerifierHelper; +import org.chromium.components.content_relationship_verification.OriginVerificationScheduler; +import org.chromium.components.content_relationship_verification.OriginVerifier; +import org.chromium.components.content_relationship_verification.OriginVerifierHelper; import org.chromium.components.embedder_support.util.Origin; import java.util.Set;
diff --git a/android_webview/java/src/org/chromium/android_webview/AwOriginVerifier.java b/android_webview/java/src/org/chromium/android_webview/AwOriginVerifier.java index 64a68dc..031f4ab 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwOriginVerifier.java +++ b/android_webview/java/src/org/chromium/android_webview/AwOriginVerifier.java
@@ -6,8 +6,8 @@ import androidx.annotation.Nullable; -import org.chromium.components.digital_asset_links.OriginVerifier; -import org.chromium.components.digital_asset_links.Relationship; +import org.chromium.components.content_relationship_verification.OriginVerifier; +import org.chromium.components.content_relationship_verification.Relationship; import org.chromium.components.embedder_support.util.Origin; import java.util.List;
diff --git a/android_webview/java/src/org/chromium/android_webview/AwVerificationResultStore.java b/android_webview/java/src/org/chromium/android_webview/AwVerificationResultStore.java index c0480e8..26aef7f 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwVerificationResultStore.java +++ b/android_webview/java/src/org/chromium/android_webview/AwVerificationResultStore.java
@@ -4,7 +4,7 @@ package org.chromium.android_webview; -import org.chromium.components.digital_asset_links.VerificationResultStore; +import org.chromium.components.content_relationship_verification.VerificationResultStore; import java.util.Collections; import java.util.HashSet;
diff --git a/android_webview/junit/DEPS b/android_webview/junit/DEPS index 8c66cdd2..800c5ab 100644 --- a/android_webview/junit/DEPS +++ b/android_webview/junit/DEPS
@@ -1,4 +1,4 @@ include_rules = [ - "+components/digital_asset_links/android/java", + "+components/content_relationship_verification/android/java", "+content/public/test/android/javatests/src/org/chromium/content_public/browser/test/util/TestThreadUtils.java", ] \ No newline at end of file
diff --git a/android_webview/junit/src/org/chromium/android_webview/robolectric/AwOriginVerifierTest.java b/android_webview/junit/src/org/chromium/android_webview/robolectric/AwOriginVerifierTest.java index 3f2b824..df189b1 100644 --- a/android_webview/junit/src/org/chromium/android_webview/robolectric/AwOriginVerifierTest.java +++ b/android_webview/junit/src/org/chromium/android_webview/robolectric/AwOriginVerifierTest.java
@@ -28,11 +28,11 @@ import org.chromium.android_webview.AwVerificationResultStore; import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.base.test.util.JniMocker; -import org.chromium.components.digital_asset_links.OriginVerifier; -import org.chromium.components.digital_asset_links.OriginVerifier.OriginVerificationListener; -import org.chromium.components.digital_asset_links.OriginVerifierJni; -import org.chromium.components.digital_asset_links.OriginVerifierUnitTestSupport; -import org.chromium.components.digital_asset_links.RelationshipCheckResult; +import org.chromium.components.content_relationship_verification.OriginVerifier; +import org.chromium.components.content_relationship_verification.OriginVerifier.OriginVerificationListener; +import org.chromium.components.content_relationship_verification.OriginVerifierJni; +import org.chromium.components.content_relationship_verification.OriginVerifierUnitTestSupport; +import org.chromium.components.content_relationship_verification.RelationshipCheckResult; import org.chromium.components.embedder_support.util.Origin; import org.chromium.content_public.browser.test.util.TestThreadUtils;
diff --git a/android_webview/test/BUILD.gn b/android_webview/test/BUILD.gn index 05e5fdb0..6f2510b 100644 --- a/android_webview/test/BUILD.gn +++ b/android_webview/test/BUILD.gn
@@ -264,7 +264,7 @@ "//components/component_updater/android:embedded_component_loader_java", "//components/content_capture/android:java", "//components/content_capture/android/test_support:java", - "//components/digital_asset_links/android:java", + "//components/content_relationship_verification/android:java", "//components/embedder_support/android:util_java", "//components/embedder_support/android:web_contents_delegate_java", "//components/embedder_support/android/metrics:java", @@ -704,9 +704,9 @@ "//base:base_java_test_support", "//base:base_junit_test_support", "//components/component_updater/android:embedded_component_loader_java", - "//components/digital_asset_links:java", - "//components/digital_asset_links/android:java", - "//components/digital_asset_links/android:junit_test_support", + "//components/content_relationship_verification:java", + "//components/content_relationship_verification/android:java", + "//components/content_relationship_verification/android:junit_test_support", "//components/embedder_support/android:util_java", "//content/public/android:content_full_java", "//content/public/test/android:content_java_test_support",
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index 9c8853f..82a3558e 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -769,8 +769,6 @@ "login/ui/scrollable_users_list_view.h", "login/ui/smart_lock_auth_factor_model.cc", "login/ui/smart_lock_auth_factor_model.h", - "login/ui/system_label_button.cc", - "login/ui/system_label_button.h", "login/ui/user_switch_flip_animation.cc", "login/ui/user_switch_flip_animation.h", "login/ui/views_utils.cc",
diff --git a/ash/accelerators/accelerator_controller_unittest.cc b/ash/accelerators/accelerator_controller_unittest.cc index adff1c0..5341705 100644 --- a/ash/accelerators/accelerator_controller_unittest.cc +++ b/ash/accelerators/accelerator_controller_unittest.cc
@@ -427,12 +427,8 @@ if (!base::DirectoryExists(file_path.DirName())) base::CreateDirectory(file_path.DirName()); - int data_size = static_cast<int>(json_string.size()); - int bytes_written = - base::WriteFile(file_path, json_string.data(), data_size); - if (bytes_written != data_size) { - LOG(ERROR) << " Wrote " << bytes_written << " byte(s) instead of " - << data_size << " to " << file_path.value(); + if (!base::WriteFile(file_path, json_string)) { + LOG(ERROR) << "Writing to " << file_path.value() << " failed."; return false; } return true;
diff --git a/ash/ambient/ambient_controller.cc b/ash/ambient/ambient_controller.cc index 116e2c2..a00c37be 100644 --- a/ash/ambient/ambient_controller.cc +++ b/ash/ambient/ambient_controller.cc
@@ -577,7 +577,9 @@ close_widgets_immediately_ = immediately; ambient_ui_model_.SetUiVisibility(AmbientUiVisibility::kClosed); - Shell::Get()->cursor_manager()->ShowCursor(); + if (!Shell::Get()->IsInTabletMode()) { + Shell::Get()->cursor_manager()->ShowCursor(); + } } void AmbientController::ToggleInSessionUi() {
diff --git a/ash/capture_mode/capture_mode_controller.cc b/ash/capture_mode/capture_mode_controller.cc index 5437a6af..54facc8 100644 --- a/ash/capture_mode/capture_mode_controller.cc +++ b/ash/capture_mode/capture_mode_controller.cc
@@ -375,6 +375,10 @@ case RecordingStatus::kLowDriveFsQuota: RecordEndRecordingReason(EndRecordingReason::kLowDriveFsQuota); break; + case RecordingStatus::kVideoEncoderReconfigurationFailure: + RecordEndRecordingReason( + EndRecordingReason::kVideoEncoderReconfigurationFailure); + break; } }
diff --git a/ash/capture_mode/capture_mode_metrics.h b/ash/capture_mode/capture_mode_metrics.h index a342f44..3052dbb 100644 --- a/ash/capture_mode/capture_mode_metrics.h +++ b/ash/capture_mode/capture_mode_metrics.h
@@ -36,7 +36,8 @@ kVideoEncodingError, kProjectorTranscriptionError, kLowDriveFsQuota, - kMaxValue = kLowDriveFsQuota, + kVideoEncoderReconfigurationFailure, + kMaxValue = kVideoEncoderReconfigurationFailure, }; // Enumeration of capture bar buttons that can be pressed while in capture mode.
diff --git a/ash/components/arc/net/arc_net_host_impl.cc b/ash/components/arc/net/arc_net_host_impl.cc index 39a49c3c..dc63b424 100644 --- a/ash/components/arc/net/arc_net_host_impl.cc +++ b/ash/components/arc/net/arc_net_host_impl.cc
@@ -1169,8 +1169,7 @@ return; } - shill_network_properties_[service_path] = - base::Value(std::move(*shill_properties)); + shill_network_properties_[service_path] = std::move(*shill_properties); // Get patchpanel devices and update active networks. ash::PatchPanelClient::Get()->GetDevices(base::BindOnce( @@ -1209,15 +1208,14 @@ void ArcNetHostImpl::StartLohs(mojom::LohsConfigPtr config, StartLohsCallback callback) { NET_LOG(USER) << "Starting LOHS"; - base::Value dict(base::Value::Type::DICT); + base::Value::Dict dict; if (config->hexssid.empty()) { NET_LOG(ERROR) << "Cannot create local only hotspot without hex ssid"; std::move(callback).Run(arc::mojom::LohsStatus::kErrorInvalidArgument); return; } - dict.GetDict().Set(shill::kTetheringConfSSIDProperty, - base::Value(config->hexssid)); + dict.Set(shill::kTetheringConfSSIDProperty, config->hexssid); if (config->band != arc::mojom::WifiBand::k2Ghz) { // TODO(b/257880335): Support 5Ghz band as well @@ -1226,8 +1224,7 @@ std::move(callback).Run(arc::mojom::LohsStatus::kErrorInvalidArgument); return; } - dict.GetDict().Set(shill::kTetheringConfBandProperty, - base::Value(shill::kBand2GHz)); + dict.Set(shill::kTetheringConfBandProperty, shill::kBand2GHz); if (config->security_type != arc::mojom::SecurityType::WPA_PSK) { NET_LOG(ERROR) << "Unsupported security for LOHS: " << config->security_type @@ -1240,16 +1237,14 @@ std::move(callback).Run(arc::mojom::LohsStatus::kErrorInvalidArgument); return; } - dict.GetDict().Set(shill::kTetheringConfSecurityProperty, - base::Value(shill::kSecurityWpa2)); - dict.GetDict().Set(shill::kTetheringConfPassphraseProperty, - base::Value(config->passphrase.value())); + dict.Set(shill::kTetheringConfSecurityProperty, shill::kSecurityWpa2); + dict.Set(shill::kTetheringConfPassphraseProperty, config->passphrase.value()); NET_LOG(USER) << "Set Shill Manager property: " << shill::kLOHSConfigProperty << ": " << dict; auto callback_split = base::SplitOnceCallback(std::move(callback)); ash::ShillManagerClient::Get()->SetProperty( - shill::kLOHSConfigProperty, dict, + shill::kLOHSConfigProperty, base::Value(std::move(dict)), base::BindOnce(&SetLohsConfigPropertySuccessCallback, std::move(callback_split.first)), base::BindOnce(&SetLohsConfigPropertyFailureCallback,
diff --git a/ash/components/arc/net/arc_net_host_impl.h b/ash/components/arc/net/arc_net_host_impl.h index 7040838c..e8e12af 100644 --- a/ash/components/arc/net/arc_net_host_impl.h +++ b/ash/components/arc/net/arc_net_host_impl.h
@@ -141,15 +141,15 @@ // ARC VPN connection. std::string LookupArcVpnServicePath(); - // Convert a vector of strings, |string_list|, to a base::Value - // that can be added to an ONC dictionary. This is used for fields - // like NameServers, SearchDomains, etc. + // Convert a vector of strings, |string_list|, to a base::Value::List that can + // be added to an ONC dictionary. This is used for fields like NameServers, + // SearchDomains, etc. base::Value::List TranslateStringListToValue( const std::vector<std::string>& string_list); - // Convert a vector of uint64_t, |long_list|, to a base::Value of type list - // that can be passed to shill. This is because 64-bit integer values are not - // supported for base::Value. + // Convert a vector of uint64_t, |long_list|, to a base::Value::List that can + // be passed to shill. This is because 64-bit integer values are not supported + // for base::Value. // The translated values will be a list of decimal string and not a single // string. base::Value::List TranslateLongListToStringValue( @@ -165,14 +165,14 @@ // Ask Android to disconnect any VPN app that is currently connected. void DisconnectArcVpn(); - // Translate EAP credentials to base::Value dictionary and run |callback|. + // Translate EAP credentials to base::Value::Dict and run |callback|. // If it is necessary to import certificates this method will asynchronously // import them and run |callback| afterwards. void TranslateEapCredentialsToDict( mojom::EapCredentialsPtr cred, base::OnceCallback<void(base::Value::Dict)> callback); - // Synchronously translate EAP credentials to base::Value dictionary with + // Synchronously translate EAP credentials to base::Value::Dict with // empty or imported certificate and slot ID. |callback| is then run with // the translated values. void TranslateEapCredentialsToDictWithCertID( @@ -181,14 +181,14 @@ const absl::optional<std::string>& cert_id, const absl::optional<int>& slot_id); - // Translate passpoint credentials to base::Value dictionary and run + // Translate passpoint credentials to base::Value::Dict and run // |callback|. If it is necessary to import certificates this method will // asynchronously import them and run |callback| afterwards. void TranslatePasspointCredentialsToDict( mojom::PasspointCredentialsPtr cred, base::OnceCallback<void(base::Value::Dict)> callback); - // Synchronously translate passpoint credentials to base::Value dictionary + // Synchronously translate passpoint credentials to base::Value::Dict // with EAP fields translated inside |dict|. |callback| is then run with // the translated values. void TranslatePasspointCredentialsToDictWithEapTranslated( @@ -229,7 +229,7 @@ // state changes. bool observing_network_state_ = false; // Cached shill properties for all active networks, keyed by Service path. - std::map<std::string, base::Value> shill_network_properties_; + std::map<std::string, base::Value::Dict> shill_network_properties_; std::string cached_service_path_; std::string cached_guid_;
diff --git a/ash/components/arc/net/arc_net_utils.cc b/ash/components/arc/net/arc_net_utils.cc index fd9a81020..61a136b 100644 --- a/ash/components/arc/net/arc_net_utils.cc +++ b/ash/components/arc/net/arc_net_utils.cc
@@ -41,19 +41,12 @@ // Parses a shill IPConfig dictionary and adds the relevant fields to // the given |network| NetworkConfiguration object. void AddIpConfiguration(arc::mojom::NetworkConfiguration* network, - const base::Value* shill_ipconfig) { - const base::Value::Dict* shill_ipconfig_dict = shill_ipconfig->GetIfDict(); - if (!shill_ipconfig_dict) { - return; - } - + const base::Value::Dict* shill_ipconfig) { // Only set the IP address and gateway if both are defined and non empty. - const auto* address = - shill_ipconfig_dict->FindString(shill::kAddressProperty); - const auto* gateway = - shill_ipconfig_dict->FindString(shill::kGatewayProperty); + const auto* address = shill_ipconfig->FindString(shill::kAddressProperty); + const auto* gateway = shill_ipconfig->FindString(shill::kGatewayProperty); const int prefixlen = - shill_ipconfig_dict->FindInt(shill::kPrefixlenProperty).value_or(0); + shill_ipconfig->FindInt(shill::kPrefixlenProperty).value_or(0); if (address && !address->empty() && gateway && !gateway->empty()) { if (prefixlen < 64) { network->host_ipv4_prefix_length = prefixlen; @@ -69,7 +62,7 @@ // If the user has overridden DNS with the "Google nameservers" UI options, // the kStaticIPConfigProperty object will be empty except for DNS addresses. if (const auto* dns_list = - shill_ipconfig_dict->FindList(shill::kNameServersProperty)) { + shill_ipconfig->FindList(shill::kNameServersProperty)) { for (const auto& dns_value : *dns_list) { const std::string& dns = dns_value.GetString(); if (dns.empty()) { @@ -87,19 +80,19 @@ } if (const auto* domains = - shill_ipconfig_dict->FindList(shill::kSearchDomainsProperty)) { + shill_ipconfig->FindList(shill::kSearchDomainsProperty)) { for (const auto& domain : *domains) { network->host_search_domains->push_back(domain.GetString()); } } - const int mtu = shill_ipconfig_dict->FindInt(shill::kMtuProperty).value_or(0); + const int mtu = shill_ipconfig->FindInt(shill::kMtuProperty).value_or(0); if (mtu > 0) { network->host_mtu = mtu; } if (const auto* include_routes_list = - shill_ipconfig_dict->FindList(shill::kIncludedRoutesProperty)) { + shill_ipconfig->FindList(shill::kIncludedRoutesProperty)) { for (const auto& include_routes_value : *include_routes_list) { const std::string& include_route = include_routes_value.GetString(); if (!include_route.empty()) { @@ -109,7 +102,7 @@ } if (const auto* exclude_routes_list = - shill_ipconfig_dict->FindList(shill::kExcludedRoutesProperty)) { + shill_ipconfig->FindList(shill::kExcludedRoutesProperty)) { for (const auto& exclude_routes_value : *exclude_routes_list) { const std::string& exclude_route = exclude_routes_value.GetString(); if (!exclude_route.empty()) { @@ -154,7 +147,7 @@ arc::mojom::NetworkConfigurationPtr TranslateNetworkProperties( const ash::NetworkState* network_state, - const base::Value* shill_dict) { + const base::Value::Dict* shill_dict) { auto mojo = arc::mojom::NetworkConfiguration::New(); // Initialize optional array fields to avoid null guards both here and in ARC. mojo->host_ipv6_global_addresses = std::vector<std::string>(); @@ -172,7 +165,7 @@ mojo->type = TranslateNetworkType(network_state->type()); mojo->is_metered = shill_dict && - shill_dict->FindBoolPath(shill::kMeteredProperty).value_or(false); + shill_dict->FindBool(shill::kMeteredProperty).value_or(false); // IP configuration data is added from the properties of the underlying shill // Device and shill Service attached to the Device. Device properties are @@ -192,15 +185,20 @@ if (const auto* device = GetStateHandler()->GetDeviceState(network_state->device_path())) { mojo->network_interface = device->interface(); - for (const auto kv : device->ip_configs()) { - AddIpConfiguration(mojo.get(), &kv.second); + for (const auto [key, value] : device->ip_configs()) { + if (value.is_dict()) { + AddIpConfiguration(mojo.get(), &value.GetDict()); + } } } if (shill_dict) { for (const auto* property : {shill::kStaticIPConfigProperty, shill::kSavedIPConfigProperty}) { - AddIpConfiguration(mojo.get(), shill_dict->GetDict().Find(property)); + const base::Value::Dict* config = shill_dict->FindDict(property); + if (config) { + AddIpConfiguration(mojo.get(), config); + } } } @@ -215,9 +213,10 @@ mojo->wifi->rssi = network_state->rssi(); if (shill_dict) { mojo->wifi->hidden_ssid = - shill_dict->FindBoolPath(shill::kWifiHiddenSsid).value_or(false); + shill_dict->FindBoolByDottedPath(shill::kWifiHiddenSsid) + .value_or(false); const auto* fqdn = - shill_dict->FindStringPath(shill::kPasspointFQDNProperty); + shill_dict->FindStringByDottedPath(shill::kPasspointFQDNProperty); if (fqdn && !fqdn->empty()) { mojo->wifi->fqdn = *fqdn; } @@ -360,7 +359,7 @@ std::vector<arc::mojom::NetworkConfigurationPtr> TranslateNetworkStates( const std::string& arc_vpn_path, const ash::NetworkStateHandler::NetworkStateList& network_states, - const std::map<std::string, base::Value>& shill_network_properties, + const std::map<std::string, base::Value::Dict>& shill_network_properties, const std::vector<patchpanel::NetworkDevice>& devices) { // Move the devices vector to a map keyed by its physical interface name in // order to avoid multiple loops. The map also filters non-ARC devices. @@ -391,7 +390,7 @@ } const auto it = shill_network_properties.find(network_path); - const auto* shill_dict = + const base::Value::Dict* shill_dict = (it != shill_network_properties.end()) ? &it->second : nullptr; auto network = TranslateNetworkProperties(state, shill_dict); network->is_default_network = state == GetStateHandler()->DefaultNetwork();
diff --git a/ash/components/arc/net/arc_net_utils.h b/ash/components/arc/net/arc_net_utils.h index 2896fe2..12c376f 100644 --- a/ash/components/arc/net/arc_net_utils.h +++ b/ash/components/arc/net/arc_net_utils.h
@@ -22,10 +22,10 @@ // Translates a shill network state into a mojo NetworkConfigurationPtr. // This get network properties from NetworkState and populating the -// corresponding fields defined in NetworkConiguration in mojo. +// corresponding fields defined in NetworkConfiguration in mojo. arc::mojom::NetworkConfigurationPtr TranslateNetworkProperties( const ash::NetworkState* network_state, - const base::Value* shill_dict); + const base::Value::Dict* shill_dict); // Translates a mojo EapMethod into a shill EAP method. std::string TranslateEapMethod(arc::mojom::EapMethod method); @@ -55,7 +55,7 @@ std::vector<arc::mojom::NetworkConfigurationPtr> TranslateNetworkStates( const std::string& arc_vpn_path, const ash::NetworkStateHandler::NetworkStateList& network_states, - const std::map<std::string, base::Value>& shill_network_properties, + const std::map<std::string, base::Value::Dict>& shill_network_properties, const std::vector<patchpanel::NetworkDevice>& devices); } // namespace arc::net_utils
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc index 16c5417..62f9a63 100644 --- a/ash/constants/ash_features.cc +++ b/ash/constants/ash_features.cc
@@ -99,6 +99,11 @@ "ChromeOSAmbientModeThrottleAnimation", base::FEATURE_DISABLED_BY_DEFAULT); +// Controls whether the logic for managed screensaver is enabled or not. +BASE_FEATURE(kAmbientModeManagedScreensaver, + "ChromeOSAmbientModeManagedScreensaver", + base::FEATURE_DISABLED_BY_DEFAULT); + BASE_FEATURE(kApnRevamp, "ApnRevamp", base::FEATURE_DISABLED_BY_DEFAULT); BASE_FEATURE(kAppCollectionFolderRefresh, @@ -1013,6 +1018,11 @@ // Enable glanceables on login. BASE_FEATURE(kGlanceables, "Glanceables", base::FEATURE_DISABLED_BY_DEFAULT); +// Enables glanceables on time management surface. +BASE_FEATURE(kGlanceablesV2, + "GlanceablesV2", + base::FEATURE_DISABLED_BY_DEFAULT); + // Enables the Gaia reauth endpoint. BASE_FEATURE(kGaiaReauthEndpoint, "GaiaReauthEndpoint", @@ -2309,6 +2319,10 @@ return base::FeatureList::IsEnabled(kAmbientModeDevUseProdFeature); } +bool IsAmbientModeManagedScreensaverEnabled() { + return base::FeatureList::IsEnabled(kAmbientModeManagedScreensaver); +} + bool IsAmbientModePhotoPreviewEnabled() { return base::FeatureList::IsEnabled(kAmbientModePhotoPreviewFeature); } @@ -2641,6 +2655,10 @@ return base::FeatureList::IsEnabled(kGlanceables); } +bool AreGlanceablesV2Enabled() { + return base::FeatureList::IsEnabled(kGlanceablesV2); +} + bool IsHibernateEnabled() { return base::FeatureList::IsEnabled(kHibernate); }
diff --git a/ash/constants/ash_features.h b/ash/constants/ash_features.h index e0364b4..27d9c63 100644 --- a/ash/constants/ash_features.h +++ b/ash/constants/ash_features.h
@@ -32,6 +32,8 @@ BASE_DECLARE_FEATURE(kAmbientModePhotoPreviewFeature); COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kAmbientModeThrottleAnimation); +COMPONENT_EXPORT(ASH_CONSTANTS) +BASE_DECLARE_FEATURE(kAmbientModeManagedScreensaver); COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kApnRevamp); COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kAppCollectionFolderRefresh); @@ -302,7 +304,9 @@ BASE_DECLARE_FEATURE(kGalleryAppPdfEditNotification); COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::FeatureParam<std::string> kGalleryAppPdfEditNotificationText; +// TODO(b/270948434): Remove `kGlanceables`. COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kGlanceables); +COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kGlanceablesV2); COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kGaiaReauthEndpoint); COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kGameDashboard); COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kGamepadVibration); @@ -629,6 +633,7 @@ COMPONENT_EXPORT(ASH_CONSTANTS) bool IsEapDefaultCasWithoutSubjectVerificationAllowed(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsAmbientModeDevUseProdEnabled(); +COMPONENT_EXPORT(ASH_CONSTANTS) bool IsAmbientModeManagedScreensaverEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsAmbientModePhotoPreviewEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsAmbientModeThrottleAnimationEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsApnRevampEnabled(); @@ -720,6 +725,7 @@ COMPONENT_EXPORT(ASH_CONSTANTS) bool IsGifRecordingEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsGifRenderingEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool AreGlanceablesEnabled(); +COMPONENT_EXPORT(ASH_CONSTANTS) bool AreGlanceablesV2Enabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsHibernateEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsHideArcMediaNotificationsEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsHideShelfControlsInTabletModeEnabled();
diff --git a/ash/constants/ash_pref_names.cc b/ash/constants/ash_pref_names.cc index e861cb6..b0a75eb 100644 --- a/ash/constants/ash_pref_names.cc +++ b/ash/constants/ash_pref_names.cc
@@ -130,6 +130,20 @@ const char kInputNoiseCancellationEnabled[] = "ash.input_noise_cancellation_enabled"; +// The name of an integer pref that counts the number of times we have shown +// the multitask menu education nudge. +const char kMultitaskMenuNudgeClamshellShownCount[] = + "ash.wm_nudge.multitask_nudge_count"; +const char kMultitaskMenuNudgeTabletShownCount[] = + "cros.wm_nudge.tablet_multitask_nudge_count"; + +// The name of a time pref that stores the time we last showed the multitask +// menu education nudge. +const char kMultitaskMenuNudgeClamshellLastShown[] = + "ash.wm_nudge.multitask_menu_nudge_last_shown"; +const char kMultitaskMenuNudgeTabletLastShown[] = + "cros.wm_nudge.tablet_multitask_nudge_last_shown"; + // The following SAML-related prefs are not settings that the domain admin can // set, but information that the SAML Identity Provider can send us:
diff --git a/ash/constants/ash_pref_names.h b/ash/constants/ash_pref_names.h index 95ffa7ea..fdedb7be 100644 --- a/ash/constants/ash_pref_names.h +++ b/ash/constants/ash_pref_names.h
@@ -57,6 +57,14 @@ COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kInputNoiseCancellationEnabled[]; COMPONENT_EXPORT(ASH_CONSTANTS) +extern const char kMultitaskMenuNudgeClamshellShownCount[]; +COMPONENT_EXPORT(ASH_CONSTANTS) +extern const char kMultitaskMenuNudgeTabletShownCount[]; +COMPONENT_EXPORT(ASH_CONSTANTS) +extern const char kMultitaskMenuNudgeClamshellLastShown[]; +COMPONENT_EXPORT(ASH_CONSTANTS) +extern const char kMultitaskMenuNudgeTabletLastShown[]; +COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kSamlPasswordModifiedTime[]; COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kSamlPasswordExpirationTime[];
diff --git a/ash/login/ui/lock_contents_view.cc b/ash/login/ui/lock_contents_view.cc index c4222ef..aad1cf5 100644 --- a/ash/login/ui/lock_contents_view.cc +++ b/ash/login/ui/lock_contents_view.cc
@@ -30,7 +30,6 @@ #include "ash/login/ui/non_accessible_view.h" #include "ash/login/ui/note_action_launch_button.h" #include "ash/login/ui/scrollable_users_list_view.h" -#include "ash/login/ui/system_label_button.h" #include "ash/login/ui/views_utils.h" #include "ash/media/media_controller_impl.h" #include "ash/metrics/user_metrics_recorder.h" @@ -49,6 +48,7 @@ #include "ash/strings/grit/ash_strings.h" #include "ash/style/ash_color_id.h" #include "ash/style/ash_color_provider.h" +#include "ash/style/pill_button.h" #include "ash/system/model/enterprise_domain_model.h" #include "ash/system/model/system_tray_model.h" #include "ash/system/power/power_button_controller.h" @@ -2454,10 +2454,10 @@ MakeSectionBold(label.get(), error_text, bold_start, bold_length); label->SetAutoColorReadabilityEnabled(false); - auto learn_more_button = std::make_unique<SystemLabelButton>( + auto learn_more_button = std::make_unique<PillButton>( base::BindRepeating(&LockContentsView::LearnMoreButtonPressed, base::Unretained(this)), - l10n_util::GetStringUTF16(IDS_ASH_LEARN_MORE), /*multiline=*/true); + l10n_util::GetStringUTF16(IDS_ASH_LEARN_MORE)); auto container = std::make_unique<NonAccessibleView>(kAuthErrorContainerName); auto* container_layout = @@ -2475,11 +2475,10 @@ if (screen_type_ == LockScreen::ScreenType::kLogin && Shell::Get()->session_controller()->GetSessionState() != session_manager::SessionState::LOGIN_SECONDARY) { - auto recover_user_button = std::make_unique<SystemLabelButton>( + auto recover_user_button = std::make_unique<PillButton>( base::BindRepeating(&LockContentsView::RecoverUserButtonPressed, base::Unretained(this)), - l10n_util::GetStringUTF16(IDS_ASH_LOGIN_RECOVER_USER_BUTTON), - /*multiline=*/true); + l10n_util::GetStringUTF16(IDS_ASH_LOGIN_RECOVER_USER_BUTTON)); container->AddChildView(std::move(recover_user_button)); }
diff --git a/ash/login/ui/login_auth_user_view.cc b/ash/login/ui/login_auth_user_view.cc index c260793..b4259a4 100644 --- a/ash/login/ui/login_auth_user_view.cc +++ b/ash/login/ui/login_auth_user_view.cc
@@ -26,7 +26,6 @@ #include "ash/login/ui/pin_keyboard_animation.h" #include "ash/login/ui/pin_request_view.h" #include "ash/login/ui/smart_lock_auth_factor_model.h" -#include "ash/login/ui/system_label_button.h" #include "ash/login/ui/views_utils.h" #include "ash/public/cpp/smartlock_state.h" #include "ash/resources/vector_icons/vector_icons.h" @@ -36,6 +35,7 @@ #include "ash/style/ash_color_id.h" #include "ash/style/ash_color_provider.h" #include "ash/style/color_util.h" +#include "ash/style/pill_button.h" #include "ash/system/model/clock_model.h" #include "ash/system/model/system_tray_model.h" #include "ash/system/time/time_of_day.h" @@ -1094,7 +1094,7 @@ gfx::Insets::TLBR(kPinPasswordToggleButtonPaddingTop, 0, kPinPasswordToggleButtonPaddingBottom, 0))); pin_password_toggle_ = - toggle_container->AddChildView(std::make_unique<SystemLabelButton>( + toggle_container->AddChildView(std::make_unique<PillButton>( base::BindRepeating(&LoginAuthUserView::OnSwitchButtonClicked, base::Unretained(this)), GetPinPasswordToggleText())); @@ -1127,7 +1127,7 @@ l10n_util::GetStringUTF16(IDS_ASH_LOCK_SCREEN_VERIFY_ACCOUNT_MESSAGE); } - auto online_sign_in_button = std::make_unique<SystemLabelButton>( + auto online_sign_in_button = std::make_unique<PillButton>( base::BindRepeating(&LoginAuthUserView::OnOnlineSignInMessageTap, base::Unretained(this)), button_message);
diff --git a/ash/login/ui/login_remove_account_dialog.cc b/ash/login/ui/login_remove_account_dialog.cc index 7f3df9e..3f70526 100644 --- a/ash/login/ui/login_remove_account_dialog.cc +++ b/ash/login/ui/login_remove_account_dialog.cc
@@ -4,12 +4,12 @@ #include "ash/login/ui/login_remove_account_dialog.h" #include "ash/login/ui/non_accessible_view.h" -#include "ash/login/ui/system_label_button.h" #include "ash/login/ui/views_utils.h" #include "ash/public/cpp/login_types.h" #include "ash/public/cpp/shelf_config.h" #include "ash/strings/grit/ash_strings.h" #include "ash/style/ash_color_id.h" +#include "ash/style/pill_button.h" #include "base/functional/bind.h" #include "base/strings/strcat.h" #include "base/strings/utf_string_conversions.h" @@ -71,19 +71,23 @@ } // namespace // A system label button that dismisses its bubble dialog parent on key event. -class RemoveUserButton : public SystemLabelButton { +class RemoveUserButton : public PillButton { public: RemoveUserButton(PressedCallback callback, LoginRemoveAccountDialog* bubble) - : SystemLabelButton(std::move(callback), - l10n_util::GetStringUTF16( - IDS_ASH_LOGIN_POD_REMOVE_ACCOUNT_ACCESSIBLE_NAME), - /*multiline=*/true), + : PillButton(std::move(callback), + l10n_util::GetStringUTF16( + IDS_ASH_LOGIN_POD_REMOVE_ACCOUNT_ACCESSIBLE_NAME)), bubble_(bubble) {} RemoveUserButton(const RemoveUserButton&) = delete; RemoveUserButton& operator=(const RemoveUserButton&) = delete; ~RemoveUserButton() override = default; + void SetAlert(bool alert) { + SetPillButtonType(alert ? PillButton::Type::kAlertWithoutIcon + : PillButton::Type::kDefaultWithoutIcon); + } + private: void OnKeyEvent(ui::KeyEvent* event) override { if (event->type() != ui::ET_KEY_PRESSED || @@ -233,7 +237,7 @@ } if (remove_user_confirm_data_) { remove_user_confirm_data_->SetVisible(false); - remove_user_button_->SetBackgroundAndFont(/*alert_mode=*/false); + remove_user_button_->SetAlert(false); // Reset button's description to none. remove_user_button_->GetViewAccessibility().OverrideDescription( std::u16string(), @@ -306,7 +310,7 @@ if (management_disclosure_label_) { management_disclosure_label_->SetVisible(false); } - remove_user_button_->SetBackgroundAndFont(/*alert_mode=*/true); + remove_user_button_->SetAlert(true); Layout();
diff --git a/ash/login/ui/system_label_button.cc b/ash/login/ui/system_label_button.cc deleted file mode 100644 index f42578b..0000000 --- a/ash/login/ui/system_label_button.cc +++ /dev/null
@@ -1,123 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ash/login/ui/system_label_button.h" - -#include "ash/resources/vector_icons/vector_icons.h" -#include "ash/style/ash_color_provider.h" -#include "ash/style/style_util.h" -#include "ui/color/color_id.h" -#include "ui/compositor/layer.h" -#include "ui/gfx/canvas.h" -#include "ui/gfx/color_palette.h" -#include "ui/gfx/color_utils.h" -#include "ui/gfx/paint_vector_icon.h" -#include "ui/views/animation/ink_drop.h" -#include "ui/views/controls/focus_ring.h" -#include "ui/views/controls/highlight_path_generator.h" - -namespace ash { - -namespace { -constexpr int kUserInfoBubbleWidth = 192; -constexpr int kUserInfoBubbleExternalPadding = 8; -constexpr int kSystemButtonHeight = 32; -constexpr int kSystemButtonIconSize = 20; -constexpr int kSystemButtonMarginTopBottomDp = 6; -constexpr int kSystemButtonMarginLeftRightDp = 16; -constexpr int kSystemButtonBorderRadius = 16; -constexpr int kSystemButtonImageLabelSpacing = 8; -constexpr int kSystemButtonMaxLabelWidthDp = - kUserInfoBubbleWidth - 2 * kUserInfoBubbleExternalPadding - - kSystemButtonIconSize - kSystemButtonImageLabelSpacing - - 2 * kSystemButtonBorderRadius; - -// Default base layer used for the bubble background, above which the system -// label button lives. -constexpr const AshColorProvider::BaseLayerType kBubbleLayerType = - AshColorProvider::BaseLayerType::kTransparent80; - -SkPath GetSystemButtonHighlightPath(const views::View* view) { - gfx::Rect rect(view->GetLocalBounds()); - return SkPath().addRoundRect(gfx::RectToSkRect(rect), - kSystemButtonBorderRadius, - kSystemButtonBorderRadius); -} - -} // namespace - -SystemLabelButton::SystemLabelButton(PressedCallback callback, - const std::u16string& text, - bool multiline) - : LabelButton(std::move(callback), text) { - SetImageLabelSpacing(kSystemButtonImageLabelSpacing); - if (multiline) { - label()->SetMultiLine(true); - label()->SetMaximumWidth(kSystemButtonMaxLabelWidthDp); - } - SetMinSize(gfx::Size(0, kSystemButtonHeight)); - SetPaintToLayer(); - layer()->SetFillsBoundsOpaquely(false); - SetTextSubpixelRenderingEnabled(false); - views::InkDrop::Get(this)->SetMode(views::InkDropHost::InkDropMode::ON); - - SetFocusBehavior(FocusBehavior::ALWAYS); - SetInstallFocusRingOnFocus(true); - views::FocusRing::Get(this)->SetColorId(ui::kColorAshFocusRing); - views::InstallRoundRectHighlightPathGenerator(this, gfx::Insets(), - kSystemButtonBorderRadius); -} - -void SystemLabelButton::PaintButtonContents(gfx::Canvas* canvas) { - cc::PaintFlags flags; - flags.setAntiAlias(true); - flags.setColor(background_color_); - flags.setStyle(cc::PaintFlags::kFill_Style); - canvas->DrawPath(GetSystemButtonHighlightPath(this), flags); -} - -gfx::Insets SystemLabelButton::GetInsets() const { - return gfx::Insets::TLBR( - kSystemButtonMarginTopBottomDp, kSystemButtonMarginLeftRightDp, - kSystemButtonMarginTopBottomDp, kSystemButtonMarginLeftRightDp); -} - -void SystemLabelButton::OnThemeChanged() { - views::LabelButton::OnThemeChanged(); - SetBackgroundAndFont(alert_mode_); -} - -void SystemLabelButton::SetBackgroundAndFont(bool alert_mode) { - // Do not check if alert mode has already been set since the variable might - // have been initialized by default while the colors have not been set yet. - alert_mode_ = alert_mode; - - background_color_ = AshColorProvider::Get()->GetControlsLayerColor( - alert_mode - ? AshColorProvider::ControlsLayerType::kControlBackgroundColorAlert - : AshColorProvider::ControlsLayerType:: - kControlBackgroundColorInactive); - - label()->SetFontList(gfx::FontList().DeriveWithWeight( - alert_mode ? gfx::Font::Weight::BOLD : gfx::Font::Weight::MEDIUM)); - - SetEnabledTextColors(AshColorProvider::Get()->GetContentLayerColor( - alert_mode ? AshColorProvider::ContentLayerType::kButtonLabelColorPrimary - : AshColorProvider::ContentLayerType::kButtonLabelColor)); - - // In default mode, this won't be the exact resulting color of the button as - // neither |background_color_| nor the color bubble below are fully opaque. - // Nevertheless, the result is visually satisfying and better than without - // applying any background color. - SkColor effective_background_color = color_utils::GetResultingPaintColor( - background_color_, - AshColorProvider::Get()->GetBaseLayerColor(kBubbleLayerType)); - StyleUtil::ConfigureInkDropAttributes(this, - StyleUtil::kBaseColor | - StyleUtil::kInkDropOpacity | - StyleUtil::kHighlightOpacity, - effective_background_color); -} - -} // namespace ash
diff --git a/ash/login/ui/system_label_button.h b/ash/login/ui/system_label_button.h deleted file mode 100644 index 5774dabf..0000000 --- a/ash/login/ui/system_label_button.h +++ /dev/null
@@ -1,40 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_LOGIN_UI_SYSTEM_LABEL_BUTTON_H_ -#define ASH_LOGIN_UI_SYSTEM_LABEL_BUTTON_H_ - -#include "ash/ash_export.h" -#include "ui/views/controls/button/label_button.h" - -namespace ash { - -// SystemLabelButton provides styled buttons with label for the login screen. -class ASH_EXPORT SystemLabelButton : public views::LabelButton { - public: - SystemLabelButton(PressedCallback callback, - const std::u16string& text, - bool multiline = false); - SystemLabelButton(const SystemLabelButton&) = delete; - SystemLabelButton& operator=(const SystemLabelButton&) = delete; - ~SystemLabelButton() override = default; - - // views::LabelButton: - void PaintButtonContents(gfx::Canvas* canvas) override; - gfx::Insets GetInsets() const override; - void OnThemeChanged() override; - - void SetBackgroundAndFont(bool alert_mode); - - private: - bool alert_mode_ = false; - - // Absurd color to show the developer that background color has not been - // initialized properly. - SkColor background_color_ = SK_ColorGREEN; -}; - -} // namespace ash - -#endif // ASH_LOGIN_UI_SYSTEM_LABEL_BUTTON_H_
diff --git a/ash/public/cpp/input_device_settings_controller.h b/ash/public/cpp/input_device_settings_controller.h index 66a8a5e..8d17541 100644 --- a/ash/public/cpp/input_device_settings_controller.h +++ b/ash/public/cpp/input_device_settings_controller.h
@@ -52,6 +52,20 @@ // Returns a list of currently connected pointing sticks and their settings. virtual std::vector<mojom::PointingStickPtr> GetConnectedPointingSticks() = 0; + // Returns the settings of the keyboard with a device id of `id` or nullptr if + // no such device exists. + virtual const mojom::KeyboardSettings* GetKeyboardSettings(DeviceId id) = 0; + // Returns the settings of the touchpad with a device id of `id` or nullptr if + // no such device exists. + virtual const mojom::TouchpadSettings* GetTouchpadSettings(DeviceId id) = 0; + // Returns the settings of the mouse with a device id of `id` or nullptr if + // no such device exists. + virtual const mojom::MouseSettings* GetMouseSettings(DeviceId id) = 0; + // Returns the settings of the pointing stick with a device id of `id` or + // nullptr if no such device exists. + virtual const mojom::PointingStickSettings* GetPointingStickSettings( + DeviceId id) = 0; + // Configure the settings for keyboard of |id| with the provided |settings|. virtual void SetKeyboardSettings(DeviceId id, const mojom::KeyboardSettings& settings) = 0;
diff --git a/ash/public/cpp/projector/annotator_tool.cc b/ash/public/cpp/projector/annotator_tool.cc index 31bc0a2..5aefbdbe 100644 --- a/ash/public/cpp/projector/annotator_tool.cc +++ b/ash/public/cpp/projector/annotator_tool.cc
@@ -8,19 +8,10 @@ #include "base/notreached.h" #include "base/strings/string_number_conversions.h" -#include "base/values.h" namespace ash { -namespace { - -const char kToolColor[] = "color"; -const char kToolSize[] = "size"; -const char kToolType[] = "tool"; - -// Returns the hex value in RGBA format. -// For example, SK_ColorGREEN -> "00FF00FF". -std::string ConvertColorToHexString(SkColor color) { +std::string AnnotatorTool::GetColorHexString() const { uint8_t alpha = SkColorGetA(color); uint8_t red = SkColorGetR(color); uint8_t green = SkColorGetG(color); @@ -29,24 +20,7 @@ return base::HexEncode(bytes); } -// Converts the RGBA hex string to ARGB, then to an SkColor. -// For example, "000000FF" -> "SK_ColorBLACK". -// Returns red if conversion fails. -SkColor ConvertHexStringToColor(const std::string& rgba_hex) { - const size_t kHexColorLength = 8; - const size_t kRgbaLength = 6; - if (rgba_hex.length() < kHexColorLength) { - return SK_ColorRED; - } - uint32_t argb_color; - // Shift the alpha value to the front of the hex string. - const bool success = base::HexStringToUInt( - rgba_hex.substr(kRgbaLength) + rgba_hex.substr(0, kRgbaLength), - &argb_color); - return success ? argb_color : SK_ColorRED; -} - -std::string ConvertToolTypeToString(AnnotatorToolType type) { +std::string AnnotatorTool::GetToolString() const { switch (type) { case AnnotatorToolType::kMarker: return "marker"; @@ -59,46 +33,6 @@ } } -AnnotatorToolType ConvertStringToToolType(const std::string& type) { - if (type == "marker") - return AnnotatorToolType::kMarker; - if (type == "pen") - return AnnotatorToolType::kPen; - if (type == "highlighter") - return AnnotatorToolType::kHighlighter; - if (type == "eraser") - return AnnotatorToolType::kEraser; - NOTREACHED(); - return AnnotatorToolType::kMarker; -} - -} // namespace - -// static -AnnotatorTool AnnotatorTool::FromValue(const base::Value& value) { - const base::Value::Dict* dict = value.GetIfDict(); - DCHECK(dict); - DCHECK(dict->Find(kToolColor)); - DCHECK(dict->FindString(kToolColor)); - DCHECK(dict->Find(kToolSize)); - DCHECK(dict->FindInt(kToolSize)); - DCHECK(dict->Find(kToolType)); - DCHECK(dict->FindString(kToolType)); - AnnotatorTool t; - t.color = ConvertHexStringToColor(*(dict->FindString(kToolColor))); - t.size = *(dict->FindInt(kToolSize)); - t.type = ConvertStringToToolType(*(dict->FindString(kToolType))); - return t; -} - -base::Value AnnotatorTool::ToValue() const { - base::Value::Dict val; - val.Set(kToolColor, ConvertColorToHexString(color)); - val.Set(kToolSize, size); - val.Set(kToolType, ConvertToolTypeToString(type)); - return base::Value(std::move(val)); -} - bool AnnotatorTool::operator==(const AnnotatorTool& rhs) const { return rhs.color == color && rhs.size == size && rhs.type == type; }
diff --git a/ash/public/cpp/projector/annotator_tool.h b/ash/public/cpp/projector/annotator_tool.h index 1b09039f..cc443c30 100644 --- a/ash/public/cpp/projector/annotator_tool.h +++ b/ash/public/cpp/projector/annotator_tool.h
@@ -8,10 +8,6 @@ #include "ash/public/cpp/ash_public_export.h" #include "third_party/skia/include/core/SkColor.h" -namespace base { -class Value; -} // namespace base - namespace ash { // The annotator tool type. @@ -26,8 +22,12 @@ // The tool that the annotator will use. struct ASH_PUBLIC_EXPORT AnnotatorTool { - static AnnotatorTool FromValue(const base::Value& value); - base::Value ToValue() const; + // Returns the hex value in RGBA format. + // For example, SK_ColorGREEN -> "00FF00FF". + std::string GetColorHexString() const; + + // Returns the tool chosen as a string. + std::string GetToolString() const; bool operator==(const AnnotatorTool& rhs) const;
diff --git a/ash/shell.h b/ash/shell.h index 3eb57fe1..6519c2d8 100644 --- a/ash/shell.h +++ b/ash/shell.h
@@ -16,9 +16,6 @@ #include "ash/public/cpp/session/session_observer.h" #include "ash/public/cpp/shelf_types.h" #include "ash/public/cpp/system_sounds_delegate.h" -#include "ash/system/input_device_settings/input_device_settings_controller_impl.h" -#include "ash/system/input_device_settings/input_device_tracker.h" -#include "ash/system/input_device_settings/keyboard_modifier_metrics_recorder.h" #include "ash/wm/system_modal_container_event_filter_delegate.h" #include "base/gtest_prod_util.h" #include "base/memory/weak_ptr.h" @@ -150,11 +147,14 @@ class HoldingSpaceController; class HumanPresenceOrientationController; class ImeControllerImpl; +class InputDeviceSettingsControllerImpl; +class InputDeviceTracker; class WebAuthNDialogControllerImpl; class KeyAccessibilityEnabler; class KeyboardBacklightColorController; class KeyboardBrightnessControlDelegate; class KeyboardControllerImpl; +class KeyboardModifierMetricsRecorder; class LaserPointerController; class LocaleUpdateControllerImpl; class LockStateController;
diff --git a/ash/style/ash_color_mixer.cc b/ash/style/ash_color_mixer.cc index 757f653..2a745d85 100644 --- a/ash/style/ash_color_mixer.cc +++ b/ash/style/ash_color_mixer.cc
@@ -557,7 +557,10 @@ mixer[ui::kColorAshOnboardingFocusRing] = {cros_tokens::kColorProminentDark}; - mixer[ui::kColorAshSystemUIMenuBackground] = {kColorAshShieldAndBase80}; + mixer[ui::kColorAshSystemUIMenuBackground] = { + features::IsJellyEnabled() + ? static_cast<ui::ColorId>(cros_tokens::kCrosSysAppBaseElevated) + : kColorAshShieldAndBase80}; mixer[ui::kColorAshSystemUIMenuIcon] = {kColorAshIconColorPrimary}; mixer[ui::kColorAshSystemUIMenuItemBackgroundSelected] = {kColorAshInkDrop}; mixer[ui::kColorAshSystemUIMenuSeparator] = {kColorAshSeparatorColor};
diff --git a/ash/system/input_device_settings/input_device_settings_controller_impl.cc b/ash/system/input_device_settings/input_device_settings_controller_impl.cc index 4d05636c..e94bf15 100644 --- a/ash/system/input_device_settings/input_device_settings_controller_impl.cc +++ b/ash/system/input_device_settings/input_device_settings_controller_impl.cc
@@ -8,6 +8,7 @@ #include <memory> #include <vector> +#include "ash/constants/ash_features.h" #include "ash/public/cpp/input_device_settings_controller.h" #include "ash/public/mojom/input_device_settings.mojom.h" #include "ash/session/session_controller_impl.h" @@ -21,6 +22,7 @@ #include "base/functional/bind.h" #include "base/notreached.h" #include "components/prefs/pref_registry_simple.h" +#include "components/prefs/pref_service.h" #include "ui/events/devices/input_device.h" namespace ash { @@ -76,9 +78,7 @@ } void InputDeviceSettingsControllerImpl::Init() { - if (features::IsInputDeviceSettingsSplitEnabled()) { - Shell::Get()->session_controller()->AddObserver(this); - } + Shell::Get()->session_controller()->AddObserver(this); keyboard_notifier_ = std::make_unique<InputDeviceNotifier<mojom::KeyboardPtr>>( &keyboards_, @@ -104,9 +104,7 @@ } InputDeviceSettingsControllerImpl::~InputDeviceSettingsControllerImpl() { - if (features::IsInputDeviceSettingsSplitEnabled()) { - Shell::Get()->session_controller()->RemoveObserver(this); - } + Shell::Get()->session_controller()->RemoveObserver(this); } void InputDeviceSettingsControllerImpl::RegisterProfilePrefs( @@ -120,10 +118,55 @@ void InputDeviceSettingsControllerImpl::OnActiveUserPrefServiceChanged( PrefService* pref_service) { + // If the flag is disabled, clear all the settings dictionaries. + if (!features::IsInputDeviceSettingsSplitEnabled()) { + active_pref_service_ = nullptr; + pref_service->SetDict(prefs::kKeyboardDeviceSettingsDictPref, {}); + pref_service->SetDict(prefs::kMouseDeviceSettingsDictPref, {}); + pref_service->SetDict(prefs::kPointingStickDeviceSettingsDictPref, {}); + pref_service->SetDict(prefs::kTouchpadDeviceSettingsDictPref, {}); + return; + } active_pref_service_ = pref_service; // TODO(michaelcheco): Initialize settings and notify observers. } +const mojom::KeyboardSettings* +InputDeviceSettingsControllerImpl::GetKeyboardSettings(DeviceId id) { + auto iter = keyboards_.find(id); + if (iter == keyboards_.end()) { + return nullptr; + } + return iter->second->settings.get(); +} + +const mojom::MouseSettings* InputDeviceSettingsControllerImpl::GetMouseSettings( + DeviceId id) { + auto iter = mice_.find(id); + if (iter == mice_.end()) { + return nullptr; + } + return iter->second->settings.get(); +} + +const mojom::TouchpadSettings* +InputDeviceSettingsControllerImpl::GetTouchpadSettings(DeviceId id) { + auto iter = touchpads_.find(id); + if (iter == touchpads_.end()) { + return nullptr; + } + return iter->second->settings.get(); +} + +const mojom::PointingStickSettings* +InputDeviceSettingsControllerImpl::GetPointingStickSettings(DeviceId id) { + auto iter = pointing_sticks_.find(id); + if (iter == pointing_sticks_.end()) { + return nullptr; + } + return iter->second->settings.get(); +} + std::vector<mojom::KeyboardPtr> InputDeviceSettingsControllerImpl::GetConnectedKeyboards() { std::vector<mojom::KeyboardPtr> keyboard_vector;
diff --git a/ash/system/input_device_settings/input_device_settings_controller_impl.h b/ash/system/input_device_settings/input_device_settings_controller_impl.h index ef616a7..21cbbad 100644 --- a/ash/system/input_device_settings/input_device_settings_controller_impl.h +++ b/ash/system/input_device_settings/input_device_settings_controller_impl.h
@@ -43,6 +43,11 @@ std::vector<mojom::TouchpadPtr> GetConnectedTouchpads() override; std::vector<mojom::MousePtr> GetConnectedMice() override; std::vector<mojom::PointingStickPtr> GetConnectedPointingSticks() override; + const mojom::KeyboardSettings* GetKeyboardSettings(DeviceId id) override; + const mojom::MouseSettings* GetMouseSettings(DeviceId id) override; + const mojom::TouchpadSettings* GetTouchpadSettings(DeviceId id) override; + const mojom::PointingStickSettings* GetPointingStickSettings( + DeviceId id) override; void SetKeyboardSettings(DeviceId id, const mojom::KeyboardSettings& settings) override; void AddObserver(Observer* observer) override;
diff --git a/ash/system/input_device_settings/input_device_settings_controller_unittest.cc b/ash/system/input_device_settings/input_device_settings_controller_unittest.cc index 7a205966..18b1dc8fe 100644 --- a/ash/system/input_device_settings/input_device_settings_controller_unittest.cc +++ b/ash/system/input_device_settings/input_device_settings_controller_unittest.cc
@@ -7,15 +7,19 @@ #include <memory> #include "ash/constants/ash_features.h" +#include "ash/public/cpp/ash_prefs.h" #include "ash/public/cpp/input_device_settings_controller.h" #include "ash/public/mojom/input_device_settings.mojom.h" +#include "ash/session/session_controller_impl.h" #include "ash/shell.h" +#include "ash/system/input_device_settings/input_device_settings_pref_names.h" #include "ash/system/input_device_settings/pref_handlers/keyboard_pref_handler.h" #include "ash/test/ash_test_base.h" #include "base/ranges/algorithm.h" #include "base/ranges/functional.h" #include "base/test/scoped_feature_list.h" #include "components/prefs/pref_service.h" +#include "components/prefs/testing_pref_service.h" #include "ui/events/devices/input_device.h" namespace ash { @@ -29,6 +33,8 @@ 10, ui::INPUT_DEVICE_BLUETOOTH, "kSampleKeyboardBluetooth"}; const ui::InputDevice kSampleKeyboardUsb = {15, ui::INPUT_DEVICE_USB, "kSampleKeyboardUsb"}; + +constexpr char kUserEmail[] = "example1@abc.com"; } // namespace class FakeKeyboardPrefHandler : public KeyboardPrefHandler { @@ -166,4 +172,42 @@ EXPECT_EQ(keyboard_pref_handler_->num_keyboard_settings_initialized(), 2u); } +TEST_F(InputDeviceSettingsControllerTest, DeletesPrefsWhenFlagDisabled) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndDisableFeature(features::kInputDeviceSettingsSplit); + + const AccountId account_id = AccountId::FromUserEmail(kUserEmail); + + std::unique_ptr<TestingPrefServiceSimple> pref_service = + std::make_unique<TestingPrefServiceSimple>(); + ash::RegisterUserProfilePrefs(pref_service->registry(), /*for_test=*/true); + + base::Value::Dict test_pref_value; + test_pref_value.Set("Fake Key", base::Value::Dict()); + pref_service->SetDict(prefs::kKeyboardDeviceSettingsDictPref, + test_pref_value.Clone()); + pref_service->SetDict(prefs::kMouseDeviceSettingsDictPref, + test_pref_value.Clone()); + pref_service->SetDict(prefs::kPointingStickDeviceSettingsDictPref, + test_pref_value.Clone()); + pref_service->SetDict(prefs::kTouchpadDeviceSettingsDictPref, + test_pref_value.Clone()); + + GetSessionControllerClient()->SetUserPrefService(account_id, + std::move(pref_service)); + SimulateUserLogin(account_id); + + PrefService* active_pref_service = + Shell::Get()->session_controller()->GetActivePrefService(); + EXPECT_EQ(base::Value::Dict(), active_pref_service->GetDict( + prefs::kKeyboardDeviceSettingsDictPref)); + EXPECT_EQ(base::Value::Dict(), + active_pref_service->GetDict(prefs::kMouseDeviceSettingsDictPref)); + EXPECT_EQ(base::Value::Dict(), + active_pref_service->GetDict( + prefs::kPointingStickDeviceSettingsDictPref)); + EXPECT_EQ(base::Value::Dict(), active_pref_service->GetDict( + prefs::kTouchpadDeviceSettingsDictPref)); +} + } // namespace ash
diff --git a/ash/webui/projector_app/BUILD.gn b/ash/webui/projector_app/BUILD.gn index ce2dc7bb..7b2aa84 100644 --- a/ash/webui/projector_app/BUILD.gn +++ b/ash/webui/projector_app/BUILD.gn
@@ -10,8 +10,8 @@ static_library("projector_app") { sources = [ - "annotator_message_handler.cc", - "annotator_message_handler.h", + "annotator_page_handler_impl.cc", + "annotator_page_handler_impl.h", "projector_app_client.cc", "projector_app_client.h", "projector_message_handler.cc", @@ -36,6 +36,8 @@ "//ash/public/cpp", "//ash/strings", "//ash/webui/media_app_ui:buildflags", + "//ash/webui/projector_app/mojom:annotator_mojo_bindings", + "//ash/webui/projector_app/public/mojom:annotator_mojo_bindings", "//ash/webui/resources:media_app_bundle_resources", "//ash/webui/resources:projector_annotator_trusted_resources", "//ash/webui/resources:projector_annotator_untrusted_resources", @@ -47,6 +49,7 @@ "//components/prefs", "//components/signin/public/identity_manager", "//content/public/browser", + "//mojo/public/cpp/bindings", "//third_party/re2:re2", "//ui/resources", "//ui/webui", @@ -79,7 +82,7 @@ source_set("unit_tests") { testonly = true sources = [ - "test/annotator_message_handler_unittest.cc", + "test/annotator_page_handler_impl_unittest.cc", "test/projector_message_handler_unittest.cc", "test/projector_oauth_token_fetcher_unittest.cc", "test/projector_xhr_sender_unittest.cc", @@ -87,9 +90,12 @@ deps = [ ":test_support", + "//ash/webui/projector_app/mojom:annotator_mojo_bindings", + "//ash/webui/projector_app/public/mojom:annotator_mojo_bindings", "//base", "//components/prefs:test_support", "//content/test:test_support", + "//mojo/public/cpp/bindings", "//testing/gtest", ] }
diff --git a/ash/webui/projector_app/annotator_message_handler.cc b/ash/webui/projector_app/annotator_message_handler.cc deleted file mode 100644 index 5375fae..0000000 --- a/ash/webui/projector_app/annotator_message_handler.cc +++ /dev/null
@@ -1,76 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ash/webui/projector_app/annotator_message_handler.h" - -#include <memory> - -#include "ash/public/cpp/projector/annotator_tool.h" -#include "ash/public/cpp/projector/projector_controller.h" -#include "ash/webui/projector_app/projector_app_client.h" -#include "base/check.h" -#include "base/json/values_util.h" -#include "base/values.h" -#include "content/public/browser/web_ui.h" - -namespace ash { - -AnnotatorMessageHandler::AnnotatorMessageHandler() { - ProjectorAppClient::Get()->SetAnnotatorMessageHandler(this); -} - -AnnotatorMessageHandler::~AnnotatorMessageHandler() { - ProjectorAppClient::Get()->ResetAnnotatorMessageHandler(this); -} - -void AnnotatorMessageHandler::RegisterMessages() { - web_ui()->RegisterMessageCallback( - "onUndoRedoAvailabilityChanged", - base::BindRepeating( - &AnnotatorMessageHandler::OnUndoRedoAvailabilityChanged, - base::Unretained(this))); - - web_ui()->RegisterMessageCallback( - "onCanvasInitialized", - base::BindRepeating(&AnnotatorMessageHandler::OnCanvasInitialized, - base::Unretained(this))); -} - -void AnnotatorMessageHandler::SetTool(const AnnotatorTool& tool) { - AllowJavascript(); - FireWebUIListener("setTool", tool.ToValue()); -} - -void AnnotatorMessageHandler::Undo() { - AllowJavascript(); - FireWebUIListener("undo"); -} - -void AnnotatorMessageHandler::Redo() { - AllowJavascript(); - FireWebUIListener("redo"); -} - -void AnnotatorMessageHandler::Clear() { - AllowJavascript(); - FireWebUIListener("clear"); -} - -void AnnotatorMessageHandler::OnUndoRedoAvailabilityChanged( - const base::Value::List& args) { - DCHECK_EQ(args.size(), 2u); - DCHECK(args[0].is_bool()); - DCHECK(args[1].is_bool()); - ProjectorController::Get()->OnUndoRedoAvailabilityChanged(args[0].GetBool(), - args[1].GetBool()); -} - -void AnnotatorMessageHandler::OnCanvasInitialized( - const base::Value::List& args) { - DCHECK_EQ(args.size(), 1u); - DCHECK(args[0].is_bool()); - ProjectorController::Get()->OnCanvasInitialized(args[0].GetBool()); -} - -} // namespace ash
diff --git a/ash/webui/projector_app/annotator_message_handler.h b/ash/webui/projector_app/annotator_message_handler.h deleted file mode 100644 index 8b382f9f..0000000 --- a/ash/webui/projector_app/annotator_message_handler.h +++ /dev/null
@@ -1,49 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_WEBUI_PROJECTOR_APP_ANNOTATOR_MESSAGE_HANDLER_H_ -#define ASH_WEBUI_PROJECTOR_APP_ANNOTATOR_MESSAGE_HANDLER_H_ - -#include "ash/public/cpp/projector/projector_annotator_controller.h" -#include "base/functional/callback.h" -#include "base/values.h" -#include "content/public/browser/web_ui_message_handler.h" - -namespace content { -class WebUI; -} // namespace content - -namespace ash { - -struct AnnotatorTool; - -// Handles communication with the Annotator WebUI (i.e. -// chrome://projector/annotator/annotator_embedder.html) -class AnnotatorMessageHandler : public content::WebUIMessageHandler { - public: - AnnotatorMessageHandler(); - AnnotatorMessageHandler(const AnnotatorMessageHandler&) = delete; - AnnotatorMessageHandler& operator=(const AnnotatorMessageHandler&) = delete; - ~AnnotatorMessageHandler() override; - - // content::WebUIMessageHandler: - void RegisterMessages() override; - - void SetTool(const AnnotatorTool& tool); - void Undo(); - void Redo(); - void Clear(); - void set_web_ui_for_test(content::WebUI* web_ui) { set_web_ui(web_ui); } - content::WebUI* get_web_ui_for_test() { return web_ui(); } - - private: - void OnToolSet(const base::Value::List& args); - void OnUndoRedoAvailabilityChanged(const base::Value::List& args); - void OnCanvasInitialized(const base::Value::List& args); - void OnError(const base::Value::List& args); -}; - -} // namespace ash - -#endif // ASH_WEBUI_PROJECTOR_APP_ANNOTATOR_MESSAGE_HANDLER_H_
diff --git a/ash/webui/projector_app/annotator_page_handler_impl.cc b/ash/webui/projector_app/annotator_page_handler_impl.cc new file mode 100644 index 0000000..4beb9ec3 --- /dev/null +++ b/ash/webui/projector_app/annotator_page_handler_impl.cc
@@ -0,0 +1,82 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/webui/projector_app/annotator_page_handler_impl.h" + +#include <memory> + +#include "ash/public/cpp/projector/annotator_tool.h" +#include "ash/public/cpp/projector/projector_controller.h" +#include "ash/webui/projector_app/mojom/annotator.mojom.h" +#include "ash/webui/projector_app/projector_app_client.h" +#include "ash/webui/projector_app/public/mojom/annotator_structs.mojom.h" +#include "base/check.h" +#include "base/json/values_util.h" +#include "base/values.h" +#include "content/public/browser/web_ui.h" + +namespace ash { + +AnnotatorPageHandlerImpl::AnnotatorPageHandlerImpl( + mojo::PendingReceiver<annotator::mojom::AnnotatorPageHandler> + annotator_handler, + mojo::PendingRemote<annotator::mojom::AnnotatorPage> annotator, + content::WebUI* web_ui) + : annotator_remote_(std::move(annotator)), + annotator_handler_receiver_(this, std::move(annotator_handler)), + web_ui_(web_ui) { + ProjectorAppClient::Get()->SetAnnotatorPageHandler(this); +} + +AnnotatorPageHandlerImpl::~AnnotatorPageHandlerImpl() { + ProjectorAppClient::Get()->ResetAnnotatorPageHandler(this); +} + +void AnnotatorPageHandlerImpl::SetTool(const AnnotatorTool& tool) { + auto mojo_tool = annotator::mojom::AnnotatorTool::New(); + mojo_tool->color = tool.GetColorHexString(); + mojo_tool->tool = tool.GetToolString(); + mojo_tool->size = tool.size; + annotator_remote_->SetTool(std::move(mojo_tool)); +} + +void AnnotatorPageHandlerImpl::Undo() { + annotator_remote_->Undo(); +} + +void AnnotatorPageHandlerImpl::Redo() { + annotator_remote_->Redo(); +} + +void AnnotatorPageHandlerImpl::Clear() { + annotator_remote_->Clear(); +} + +void AnnotatorPageHandlerImpl::OnUndoRedoAvailabilityChanged( + bool undo_available, + bool redo_available) { + // ProjectorController is created when ash::Shell::Init is called and is + // destroyed when ash::Shell is destroyed. Therefore, ProjectorController + // is available when this WebUI is showing. + ProjectorController::Get()->OnUndoRedoAvailabilityChanged(undo_available, + redo_available); +} + +void AnnotatorPageHandlerImpl::OnCanvasInitialized(bool success) { + // ProjectorController is created when ash::Shell::Init is called and is + // destroyed when ash::Shell is destroyed. Therefore, ProjectorController + // is available when this WebUI is showing. + ProjectorController::Get()->OnCanvasInitialized(success); +} + +void AnnotatorPageHandlerImpl::OnError( + const std::vector<std::string>& messages) { + for (const auto& message : messages) { + LOG(ERROR) << message; + } + + // TODO(b/239979179): Consider reloading the webcontent. +} + +} // namespace ash
diff --git a/ash/webui/projector_app/annotator_page_handler_impl.h b/ash/webui/projector_app/annotator_page_handler_impl.h new file mode 100644 index 0000000..8808cef0 --- /dev/null +++ b/ash/webui/projector_app/annotator_page_handler_impl.h
@@ -0,0 +1,64 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_WEBUI_PROJECTOR_APP_ANNOTATOR_PAGE_HANDLER_IMPL_H_ +#define ASH_WEBUI_PROJECTOR_APP_ANNOTATOR_PAGE_HANDLER_IMPL_H_ + +#include "ash/public/cpp/projector/projector_annotator_controller.h" +#include "ash/webui/projector_app/mojom/annotator.mojom.h" +#include "base/functional/callback.h" +#include "base/values.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/pending_remote.h" +#include "mojo/public/cpp/bindings/receiver.h" +#include "mojo/public/cpp/bindings/remote.h" + +namespace content { +class WebUI; +} // namespace content + +namespace ash { + +struct AnnotatorTool; + +// Handles communication with the Annotator WebUI (i.e. +// chrome://projector/annotator/annotator_embedder.html). +class AnnotatorPageHandlerImpl : public annotator::mojom::AnnotatorPageHandler { + public: + AnnotatorPageHandlerImpl( + mojo::PendingReceiver<annotator::mojom::AnnotatorPageHandler> + annotator_handler, + mojo::PendingRemote<annotator::mojom::AnnotatorPage> annotator, + content::WebUI* web_ui); + AnnotatorPageHandlerImpl(const AnnotatorPageHandlerImpl&) = delete; + AnnotatorPageHandlerImpl& operator=(const AnnotatorPageHandlerImpl&) = delete; + ~AnnotatorPageHandlerImpl() override; + + // Called by ProjectorAppClient. + void SetTool(const AnnotatorTool& tool); + void Undo(); + void Redo(); + void Clear(); + + // annotator::mojom::AnnotatorHandler: + void OnUndoRedoAvailabilityChanged(bool undo_available, + bool redo_available) override; + void OnCanvasInitialized(bool success) override; + void OnError(const std::vector<std::string>& messages) override; + + content::WebUI* get_web_ui_for_test() { return web_ui_; } + + private: + mojo::Remote<annotator::mojom::AnnotatorPage> annotator_remote_; + mojo::Receiver<annotator::mojom::AnnotatorPageHandler> + annotator_handler_receiver_; + + // The WebUI that owns the TrustedProjectorAnnotatorUI that owns this + // instance. + content::WebUI* const web_ui_; +}; + +} // namespace ash + +#endif // ASH_WEBUI_PROJECTOR_APP_ANNOTATOR_PAGE_HANDLER_IMPL_H_
diff --git a/ash/webui/projector_app/mojom/BUILD.gn b/ash/webui/projector_app/mojom/BUILD.gn new file mode 100644 index 0000000..95890cd --- /dev/null +++ b/ash/webui/projector_app/mojom/BUILD.gn
@@ -0,0 +1,16 @@ +# Copyright 2023 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//chrome/common/features.gni") +import("//mojo/public/tools/bindings/mojom.gni") + +assert(is_chromeos_ash, "Projector Annotator is ChromeOS only") + +cur_dir = rebase_path(".", "//") + +mojom("annotator_mojo_bindings") { + sources = [ "annotator.mojom" ] + deps = [ "//ash/webui/projector_app/public/mojom:annotator_mojo_bindings" ] + webui_module_path = "/$cur_dir" +}
diff --git a/ash/webui/projector_app/mojom/OWNERS b/ash/webui/projector_app/mojom/OWNERS new file mode 100644 index 0000000..08850f4 --- /dev/null +++ b/ash/webui/projector_app/mojom/OWNERS
@@ -0,0 +1,2 @@ +per-file *.mojom=set noparent +per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/ash/webui/projector_app/mojom/annotator.mojom b/ash/webui/projector_app/mojom/annotator.mojom new file mode 100644 index 0000000..fca08dc --- /dev/null +++ b/ash/webui/projector_app/mojom/annotator.mojom
@@ -0,0 +1,46 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module ash.annotator.mojom; + +import "ash/webui/projector_app/public/mojom/annotator_structs.mojom"; + +// AnnotatorPage interface implemented in the Javascript. Used by the browser +// process to send events to Javascript. +interface AnnotatorPage { + // Clears the annotations on the annotator canvas. + Clear(); + // Undo the last stroke on the annotator canvas. + Undo(); + // Redo the last stroke on the annotator canvas. + Redo(); + // Sets the tool the user uses to annotate. + SetTool(AnnotatorTool tool); +}; + +// AnnotatoPagerHandler interface implemented in C++ in the browser process. +// Used by Javascript to communicate with the browser process. +interface AnnotatorPageHandler { + // Notifies the browser that that undo/redo availability + // changed for annotator. + OnUndoRedoAvailabilityChanged(bool undo_available, + bool redo_available); + + // Notifies the browser process that the annotation canvas + // has been initialized. + OnCanvasInitialized(bool success); + + // Notifies the browser process that an error has occurred + // in the renderer and sends the error messages to it. + OnError(array<string> errors); +}; + +// Interface used to setup the communication between Javascript and C++ +// in the browser process. +interface AnnotatorPageHandlerFactory { + // Creates the AnnotatorPageHandler in the browser process and binds it + // to receive calls from Javascript. + Create(pending_receiver<AnnotatorPageHandler> handler, + pending_remote<AnnotatorPage> annotator); +};
diff --git a/ash/webui/projector_app/projector_app_client.h b/ash/webui/projector_app/projector_app_client.h index e73ee6f..5c46efe 100644 --- a/ash/webui/projector_app/projector_app_client.h +++ b/ash/webui/projector_app/projector_app_client.h
@@ -28,7 +28,7 @@ namespace ash { -class AnnotatorMessageHandler; +class AnnotatorPageHandlerImpl; struct AnnotatorTool; struct ProjectorScreencastVideo; struct NewScreencastPrecondition; @@ -161,14 +161,13 @@ const std::string& resource_key, OnGetVideoCallback callback) const = 0; - // Registers the AnnotatorMessageHandler that is owned by the WebUI that + // Registers the AnnotatorPageHandlerImpl that is owned by the WebUI that // contains the Projector annotator. - virtual void SetAnnotatorMessageHandler(AnnotatorMessageHandler* handler) = 0; + virtual void SetAnnotatorPageHandler(AnnotatorPageHandlerImpl* handler) = 0; - // Resets the stored AnnotatorMessageHandler if it matches the one that is + // Resets the stored AnnotatorPageHandlerImpl if it matches the one that is // passed in. - virtual void ResetAnnotatorMessageHandler( - AnnotatorMessageHandler* handler) = 0; + virtual void ResetAnnotatorPageHandler(AnnotatorPageHandlerImpl* handler) = 0; // Sets the tool inside the annotator WebUI. virtual void SetTool(const AnnotatorTool& tool) = 0;
diff --git a/ash/webui/projector_app/public/mojom/BUILD.gn b/ash/webui/projector_app/public/mojom/BUILD.gn new file mode 100644 index 0000000..c6da2f9a --- /dev/null +++ b/ash/webui/projector_app/public/mojom/BUILD.gn
@@ -0,0 +1,15 @@ +# Copyright 2023 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//chrome/common/features.gni") +import("//mojo/public/tools/bindings/mojom.gni") + +assert(is_chromeos_ash, "Projector Annotator is ChromeOS only") + +cur_dir = rebase_path(".", "//") + +mojom("annotator_mojo_bindings") { + sources = [ "annotator_structs.mojom" ] + webui_module_path = "/$cur_dir" +}
diff --git a/ash/webui/projector_app/public/mojom/OWNERS b/ash/webui/projector_app/public/mojom/OWNERS new file mode 100644 index 0000000..08850f4 --- /dev/null +++ b/ash/webui/projector_app/public/mojom/OWNERS
@@ -0,0 +1,2 @@ +per-file *.mojom=set noparent +per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/ash/webui/projector_app/public/mojom/annotator_structs.mojom b/ash/webui/projector_app/public/mojom/annotator_structs.mojom new file mode 100644 index 0000000..eda84fd --- /dev/null +++ b/ash/webui/projector_app/public/mojom/annotator_structs.mojom
@@ -0,0 +1,16 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module ash.annotator.mojom; + +// The annotation tool struct sent from the browser process to +// javascript. +struct AnnotatorTool { + // TODO(b/239979179): Consider adding an enum + // to represent the tool instead of just accepting a + // string. + string tool; + string color; + int32 size; +};
diff --git a/ash/webui/projector_app/resources/BUILD.gn b/ash/webui/projector_app/resources/BUILD.gn index 840e423..0cae46dc 100644 --- a/ash/webui/projector_app/resources/BUILD.gn +++ b/ash/webui/projector_app/resources/BUILD.gn
@@ -19,7 +19,11 @@ "//ash/webui/projector_app/resources/mock:mock_app", ] - closure_flags = default_closure_args + [ "browser_resolver_prefix_replacements=\"chrome-untrusted://projector/common/=" + rebase_path( - "//ash/webui/projector_app/resources/common/", - root_build_dir) + "\"" ] + closure_flags = default_closure_args + [ + "browser_resolver_prefix_replacements=\"chrome-untrusted://projector/common/=" + rebase_path( + "//ash/webui/projector_app/resources/common/", + root_build_dir) + "\"", + "hide_warnings_for=ash/webui/projector_app/public/mojom/", + "hide_warnings_for=ash/webui/projector_app/mojom/", + ] }
diff --git a/ash/webui/projector_app/resources/annotator/trusted/BUILD.gn b/ash/webui/projector_app/resources/annotator/trusted/BUILD.gn index 490ceed..88d8fbd 100644 --- a/ash/webui/projector_app/resources/annotator/trusted/BUILD.gn +++ b/ash/webui/projector_app/resources/annotator/trusted/BUILD.gn
@@ -15,18 +15,14 @@ "trusted_annotator_comm_factory.js", ] deps = [ - "//ash/webui/common/resources:cr.m", "//ash/webui/common/resources:cr_deprecated", - "//ash/webui/common/resources:web_ui_listener_behavior", "//ash/webui/common/resources/post_message_api:post_message_api_client", "//ash/webui/common/resources/post_message_api:post_message_api_request_handler", + "//ash/webui/projector_app/mojom:annotator_mojo_bindings_webui_js", + "//ash/webui/projector_app/public/mojom:annotator_mojo_bindings_webui_js", "//ash/webui/projector_app/resources/common:message_types", - "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", ] - externs_list = [ - "$externs_path/chrome_send.js", - "../../common/projector_app.externs.js", - ] + externs_list = [ "../../common/projector_app.externs.js" ] } generate_grd("build_trusted_grd") { @@ -38,7 +34,16 @@ "annotator_embedder_impl.js", ] + manifest_files = [] input_files_base_dir = rebase_path(".", "//") grd_prefix = "ash_projector_annotator_trusted" out_grd = "$target_gen_dir/${grd_prefix}_resources.grd" + deps = [ + "//ash/webui/projector_app/mojom:annotator_mojo_bindings_webui_grdp", + "//ash/webui/projector_app/public/mojom:annotator_mojo_bindings_webui_grdp", + ] + grdp_files = [ + "$target_gen_dir/../../../mojom/annotator_mojo_bindings_webui_resources.grdp", + "$target_gen_dir/../../../public/mojom/annotator_mojo_bindings_webui_resources.grdp", + ] }
diff --git a/ash/webui/projector_app/resources/annotator/trusted/annotator_browser_proxy.js b/ash/webui/projector_app/resources/annotator/trusted/annotator_browser_proxy.js index 2b4a04e..322941c5 100644 --- a/ash/webui/projector_app/resources/annotator/trusted/annotator_browser_proxy.js +++ b/ash/webui/projector_app/resources/annotator/trusted/annotator_browser_proxy.js
@@ -1,10 +1,10 @@ // Copyright 2022 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. - -import {sendWithPromise} from 'chrome://resources/ash/common/cr.m.js'; import {addSingletonGetter} from 'chrome://resources/ash/common/cr_deprecated.js'; +import {AnnotatorPageCallbackRouter, AnnotatorPageHandlerFactory, AnnotatorPageHandlerRemote, AnnotatorPageRemote} from './ash/webui/projector_app/mojom/annotator.mojom-webui.js'; + /** * To use the annotator proxy, please import this module and call * AnnotatorBrowserProxyImpl.getInstance().* @@ -42,21 +42,35 @@ * @implements {AnnotatorBrowserProxy} */ export class AnnotatorBrowserProxyImpl { + constructor() { + this.pageHandlerFactory = AnnotatorPageHandlerFactory.getRemote(); + this.pageHandlerRemote = new AnnotatorPageHandlerRemote(); + this.annotatorCallbackRouter = new AnnotatorPageCallbackRouter(); + + this.pageHandlerFactory.create( + this.pageHandlerRemote.$.bindNewPipeAndPassReceiver(), + this.annotatorCallbackRouter.$.bindNewPipeAndPassRemote()); + } + + getAnnotatorCallbackRouter() { + return this.annotatorCallbackRouter; + } + /** @override */ onUndoRedoAvailabilityChanged(undoAvailable, redoAvailable) { - return chrome.send( - 'onUndoRedoAvailabilityChanged', [undoAvailable, redoAvailable]); + this.pageHandlerRemote.onUndoRedoAvailabilityChanged( + undoAvailable, redoAvailable); } /** @override */ onCanvasInitialized(success) { - return chrome.send('onCanvasInitialized', [success]); + this.pageHandlerRemote.onCanvasInitialized(success); } /** @override */ - onError(msg) { - return chrome.send('onError', msg); + onError(msgs) { + this.pageHandlerRemote.onError(msgs); } } -addSingletonGetter(AnnotatorBrowserProxyImpl); +addSingletonGetter(AnnotatorBrowserProxyImpl); \ No newline at end of file
diff --git a/ash/webui/projector_app/resources/annotator/trusted/annotator_embedder.html b/ash/webui/projector_app/resources/annotator/trusted/annotator_embedder.html index f3b414a..105c6d3 100644 --- a/ash/webui/projector_app/resources/annotator/trusted/annotator_embedder.html +++ b/ash/webui/projector_app/resources/annotator/trusted/annotator_embedder.html
@@ -8,9 +8,6 @@ <html> <head> <link rel="stylesheet" href="annotator_embedder.css"> - <script type="module" src="common/message_types.js"></script> - <script type="module" src="annotator_browser_proxy.js"></script> - <script type="module" src="trusted_annotator_comm_factory.js"></script> <script type="module" src="annotator_embedder_impl.js"></script> </head> <body> @@ -19,6 +16,5 @@ src="chrome-untrusted://projector-annotator" allow="cross-origin-isolated"> </iframe> - <annotator-embedder-impl></annotator-embedder-impl> </body> </html>
diff --git a/ash/webui/projector_app/resources/annotator/trusted/annotator_embedder_impl.js b/ash/webui/projector_app/resources/annotator/trusted/annotator_embedder_impl.js index 3cc6d58..97652a40 100644 --- a/ash/webui/projector_app/resources/annotator/trusted/annotator_embedder_impl.js +++ b/ash/webui/projector_app/resources/annotator/trusted/annotator_embedder_impl.js
@@ -1,12 +1,10 @@ -// Copyright 2021 The Chromium Authors +// Copyright 2021 The Chromium Authors. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {WebUIListenerBehavior} from 'chrome://resources/ash/common/web_ui_listener_behavior.js'; -import {Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; - import {AnnotatorBrowserProxyImpl} from './annotator_browser_proxy.js'; -import {AnnotatorTrustedCommFactory, UntrustedAnnotatorClient} from './trusted_annotator_comm_factory.js'; +import {AnnotatorPageCallbackRouter} from './ash/webui/projector_app/mojom/annotator.mojom-webui.js'; +import {AnnotatorTrustedCommFactory} from './trusted_annotator_comm_factory.js'; /** * Enum for passing annotator error message to the browser process. @@ -19,49 +17,48 @@ SET_TOOL_ERROR: 'SET_TOOL_ERROR', }; -Polymer({ - is: 'annotator-embedder-impl', - behaviors: [WebUIListenerBehavior], +/* @type {UntrustedAnnotatorClient} */ +const client = AnnotatorTrustedCommFactory.getPostMessageAPIClient(); - /** @override */ - ready() { - const client = AnnotatorTrustedCommFactory.getPostMessageAPIClient(); +/* @type {AnnotatorPageCallbackRouter} */ +const annotatorPageRouter = + AnnotatorBrowserProxyImpl.getInstance().getAnnotatorCallbackRouter(); - this.addWebUIListener('undo', () => { - try { - client.undo(); - } catch (error) { - AnnotatorBrowserProxyImpl.getInstance().onError( - [AnnotatorToolErrorType.UNDO_ERROR]); - } - }); - - this.addWebUIListener('redo', () => { - try { - client.redo(); - } catch (error) { - AnnotatorBrowserProxyImpl.getInstance().onError( - [AnnotatorToolErrorType.REDO_ERROR]); - } - }); - - this.addWebUIListener('clear', () => { - try { - client.clear(); - } catch (error) { - AnnotatorBrowserProxyImpl.getInstance().onError( - [AnnotatorToolErrorType.CLEAR_ERROR]); - } - }); - - this.addWebUIListener('setTool', async (tool) => { - try { - client.setTool(tool); - } catch (error) { - AnnotatorBrowserProxyImpl.getInstance().onError( - [AnnotatorToolErrorType.SET_TOOL_ERROR]); - } - }); - }, +annotatorPageRouter.undo.addListener(() => { + try { + client.undo(); + } catch (error) { + AnnotatorBrowserProxyImpl.getInstance().onError( + [AnnotatorToolErrorType.UNDO_ERROR]); + } }); + +annotatorPageRouter.redo.addListener(() => { + try { + client.redo(); + } catch (error) { + AnnotatorBrowserProxyImpl.getInstance().onError( + [AnnotatorToolErrorType.REDO_ERROR]); + } +}); + + +annotatorPageRouter.clear.addListener(() => { + try { + client.clear(); + } catch (error) { + AnnotatorBrowserProxyImpl.getInstance().onError( + [AnnotatorToolErrorType.CLEAR_ERROR]); + } +}); + + +annotatorPageRouter.setTool.addListener((tool) => { + try { + client.setTool(tool); + } catch (error) { + AnnotatorBrowserProxyImpl.getInstance().onError( + [AnnotatorToolErrorType.SET_TOOL_ERROR]); + } +}); \ No newline at end of file
diff --git a/ash/webui/projector_app/resources/app/trusted/BUILD.gn b/ash/webui/projector_app/resources/app/trusted/BUILD.gn index 389eadd9..bb8b80c 100644 --- a/ash/webui/projector_app/resources/app/trusted/BUILD.gn +++ b/ash/webui/projector_app/resources/app/trusted/BUILD.gn
@@ -22,6 +22,7 @@ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", ] externs_list = [ + "$externs_path/chrome_send.js", "../../common/projector_app.externs.js", "//ash/webui/web_applications/externs/file_handling.externs.js", ]
diff --git a/ash/webui/projector_app/test/annotator_message_handler_unittest.cc b/ash/webui/projector_app/test/annotator_message_handler_unittest.cc deleted file mode 100644 index 20df887..0000000 --- a/ash/webui/projector_app/test/annotator_message_handler_unittest.cc +++ /dev/null
@@ -1,125 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ash/webui/projector_app/annotator_message_handler.h" - -#include "ash/public/cpp/projector/annotator_tool.h" -#include "ash/public/cpp/test/mock_projector_controller.h" -#include "ash/webui/projector_app/test/mock_app_client.h" -#include "base/test/task_environment.h" -#include "base/values.h" -#include "content/public/test/test_web_ui.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/skia/include/core/SkColor.h" - -namespace ash { - -namespace { - -const char kWebUIListenerCall[] = "cr.webUIListenerCallback"; - -} // namespace - -class AnnotatorMessageHandlerTest : public testing::Test { - public: - AnnotatorMessageHandlerTest() = default; - AnnotatorMessageHandlerTest(const AnnotatorMessageHandlerTest&) = delete; - AnnotatorMessageHandler& operator=(const AnnotatorMessageHandlerTest&) = - delete; - ~AnnotatorMessageHandlerTest() override = default; - - // testing::Test: - void SetUp() override { - message_handler_ = std::make_unique<AnnotatorMessageHandler>(); - message_handler_->set_web_ui_for_test(&web_ui()); - message_handler_->RegisterMessages(); - } - - void TearDown() override { message_handler_.reset(); } - - void ExpectCallToWebUI(const std::string& type, - const std::string& func_name, - size_t count) { - EXPECT_EQ(web_ui().call_data().size(), count); - const content::TestWebUI::CallData& call_data = *(web_ui().call_data()[0]); - EXPECT_EQ(call_data.function_name(), type); - EXPECT_EQ(call_data.arg1()->GetString(), func_name); - } - - void SendUndoRedoAvailableChanged(bool undo_available, bool redo_available) { - base::Value::List list_args; - list_args.Append(base::Value(undo_available)); - list_args.Append(base::Value(redo_available)); - web_ui().HandleReceivedMessage("onUndoRedoAvailabilityChanged", list_args); - } - - void SendCanvasInitialized(bool success) { - base::Value::List list_args; - list_args.Append(base::Value(success)); - web_ui().HandleReceivedMessage("onCanvasInitialized", list_args); - } - - content::TestWebUI& web_ui() { return web_ui_; } - AnnotatorMessageHandler* handler() { return message_handler_.get(); } - MockProjectorController& controller() { return controller_; } - - private: - base::test::SingleThreadTaskEnvironment task_environment_; - - std::unique_ptr<AnnotatorMessageHandler> message_handler_; - content::TestWebUI web_ui_; - MockProjectorController controller_; - MockAppClient client_; -}; - -TEST_F(AnnotatorMessageHandlerTest, SetTool) { - AnnotatorTool expected_tool; - expected_tool.color = SkColorSetARGB(0xA1, 0xB2, 0xC3, 0xD4); - expected_tool.size = 5; - expected_tool.type = AnnotatorToolType::kPen; - handler()->SetTool(expected_tool); - - // Let's check that the call has been made. - ExpectCallToWebUI(kWebUIListenerCall, "setTool", /* call_count = */ 1u); - const content::TestWebUI::CallData& call_data = *(web_ui().call_data()[0]); - - AnnotatorTool requested_tool = AnnotatorTool::FromValue(*call_data.arg2()); - EXPECT_EQ(requested_tool, expected_tool); -} - -TEST_F(AnnotatorMessageHandlerTest, Undo) { - handler()->Undo(); - ExpectCallToWebUI(kWebUIListenerCall, "undo", /* call_count = */ 1u); -} - -TEST_F(AnnotatorMessageHandlerTest, Redo) { - handler()->Redo(); - ExpectCallToWebUI(kWebUIListenerCall, "redo", /* call_count = */ 1u); -} - -TEST_F(AnnotatorMessageHandlerTest, Clear) { - handler()->Clear(); - ExpectCallToWebUI(kWebUIListenerCall, "clear", /* call_count = */ 1u); -} - -TEST_F(AnnotatorMessageHandlerTest, UndoRedoAvailabilityChanged) { - EXPECT_CALL(controller(), OnUndoRedoAvailabilityChanged(false, false)); - SendUndoRedoAvailableChanged(false, false); - - EXPECT_CALL(controller(), OnUndoRedoAvailabilityChanged(true, true)); - SendUndoRedoAvailableChanged(true, true); - - EXPECT_CALL(controller(), OnUndoRedoAvailabilityChanged(false, true)); - SendUndoRedoAvailableChanged(false, true); -} - -TEST_F(AnnotatorMessageHandlerTest, CanvasInitialized) { - EXPECT_CALL(controller(), OnCanvasInitialized(true)); - SendCanvasInitialized(true); - - EXPECT_CALL(controller(), OnCanvasInitialized(false)); - SendCanvasInitialized(false); -} - -} // namespace ash
diff --git a/ash/webui/projector_app/test/annotator_page_handler_impl_unittest.cc b/ash/webui/projector_app/test/annotator_page_handler_impl_unittest.cc new file mode 100644 index 0000000..c0ecb750 --- /dev/null +++ b/ash/webui/projector_app/test/annotator_page_handler_impl_unittest.cc
@@ -0,0 +1,157 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/webui/projector_app/annotator_page_handler_impl.h" + +#include "ash/public/cpp/projector/annotator_tool.h" +#include "ash/public/cpp/test/mock_projector_controller.h" +#include "ash/webui/projector_app/mojom/annotator.mojom.h" +#include "ash/webui/projector_app/public/mojom/annotator_structs.mojom.h" +#include "ash/webui/projector_app/test/mock_app_client.h" +#include "base/test/task_environment.h" +#include "base/values.h" +#include "content/public/test/test_web_ui.h" +#include "mojo/public/cpp/bindings/receiver.h" +#include "mojo/public/cpp/bindings/remote.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/skia/include/core/SkColor.h" + +namespace ash { + +namespace { + +// MOCK the annotator instance in the WebUI renderer. +class MockAnnotatorPage : public annotator::mojom::AnnotatorPage { + public: + MockAnnotatorPage() = default; + MockAnnotatorPage(const MockAnnotatorPage&) = delete; + MockAnnotatorPage& operator=(const MockAnnotatorPage&) = delete; + ~MockAnnotatorPage() override = default; + + MOCK_METHOD0(Clear, void()); + MOCK_METHOD0(Undo, void()); + MOCK_METHOD0(Redo, void()); + MOCK_METHOD1(SetTool, void(annotator::mojom::AnnotatorToolPtr tool)); + + void FlushReceiverForTesting() { receiver_.FlushForTesting(); } + + void FlushRemoteForTesting() { remote_.FlushForTesting(); } + + void SendUndoRedoAvailableChanged(bool undo_available, bool redo_available) { + remote_->OnUndoRedoAvailabilityChanged(undo_available, redo_available); + } + + void SendCanvasInitialized(bool success) { + remote_->OnCanvasInitialized(success); + } + + mojo::Receiver<annotator::mojom::AnnotatorPage>& receiver() { + return receiver_; + } + mojo::Remote<annotator::mojom::AnnotatorPageHandler>& remote() { + return remote_; + } + + private: + mojo::Receiver<annotator::mojom::AnnotatorPage> receiver_{this}; + mojo::Remote<annotator::mojom::AnnotatorPageHandler> remote_; +}; + +} // namespace + +class AnnotatorPageHandlerImplTest : public testing::Test { + public: + AnnotatorPageHandlerImplTest() = default; + AnnotatorPageHandlerImplTest(const AnnotatorPageHandlerImplTest&) = delete; + AnnotatorPageHandlerImplTest& operator=(const AnnotatorPageHandlerImplTest&) = + delete; + ~AnnotatorPageHandlerImplTest() override = default; + + // testing::Test: + void SetUp() override { + annotator_ = std::make_unique<MockAnnotatorPage>(); + handler_ = std::make_unique<AnnotatorPageHandlerImpl>( + annotator().remote().BindNewPipeAndPassReceiver(), + annotator().receiver().BindNewPipeAndPassRemote(), + /*web_ui=*/nullptr); + } + + void TearDown() override { + annotator_.reset(); + handler_.reset(); + } + + AnnotatorPageHandlerImpl& handler() { return *handler_; } + MockProjectorController& controller() { return controller_; } + MockAnnotatorPage& annotator() { return *annotator_; } + base::test::SingleThreadTaskEnvironment& task_environment() { + return task_environment_; + } + + private: + base::test::SingleThreadTaskEnvironment task_environment_; + + std::unique_ptr<MockAnnotatorPage> annotator_; + std::unique_ptr<AnnotatorPageHandlerImpl> handler_; + MockProjectorController controller_; + MockAppClient client_; +}; + +TEST_F(AnnotatorPageHandlerImplTest, SetTool) { + AnnotatorTool expected_tool; + expected_tool.color = SkColorSetARGB(0xA1, 0xB2, 0xC3, 0xD4); + expected_tool.size = 5; + expected_tool.type = AnnotatorToolType::kPen; + EXPECT_CALL(annotator(), SetTool) + .WillOnce(testing::Invoke([&](annotator::mojom::AnnotatorToolPtr tool) { + EXPECT_EQ(tool->size, expected_tool.size); + EXPECT_EQ(tool->tool, expected_tool.GetToolString()); + EXPECT_EQ(tool->color, expected_tool.GetColorHexString()); + })); + + handler().SetTool(expected_tool); + annotator().FlushReceiverForTesting(); +} + +TEST_F(AnnotatorPageHandlerImplTest, Undo) { + EXPECT_CALL(annotator(), Undo()); + handler().Undo(); + annotator().FlushReceiverForTesting(); +} + +TEST_F(AnnotatorPageHandlerImplTest, Redo) { + EXPECT_CALL(annotator(), Redo()); + handler().Redo(); + annotator().FlushReceiverForTesting(); +} + +TEST_F(AnnotatorPageHandlerImplTest, Clear) { + EXPECT_CALL(annotator(), Clear()); + handler().Clear(); + annotator().FlushReceiverForTesting(); +} + +TEST_F(AnnotatorPageHandlerImplTest, UndoRedoAvailabilityChanged) { + EXPECT_CALL(controller(), OnUndoRedoAvailabilityChanged(false, false)); + annotator().SendUndoRedoAvailableChanged(false, false); + + EXPECT_CALL(controller(), OnUndoRedoAvailabilityChanged(true, true)); + annotator().SendUndoRedoAvailableChanged(true, true); + + EXPECT_CALL(controller(), OnUndoRedoAvailabilityChanged(false, true)); + annotator().SendUndoRedoAvailableChanged(false, true); + annotator().FlushRemoteForTesting(); +} + +TEST_F(AnnotatorPageHandlerImplTest, CanvasInitialized) { + EXPECT_CALL(controller(), OnCanvasInitialized(true)); + annotator().SendCanvasInitialized(true); + + EXPECT_CALL(controller(), OnCanvasInitialized(false)); + annotator().SendCanvasInitialized(false); + annotator().FlushRemoteForTesting(); +} + +} // namespace ash
diff --git a/ash/webui/projector_app/test/mock_app_client.h b/ash/webui/projector_app/test/mock_app_client.h index ab25668a..1a6b57fb 100644 --- a/ash/webui/projector_app/test/mock_app_client.h +++ b/ash/webui/projector_app/test/mock_app_client.h
@@ -55,8 +55,8 @@ void(const std::string&, const std::string&, ProjectorAppClient::OnGetVideoCallback)); - MOCK_METHOD1(SetAnnotatorMessageHandler, void(AnnotatorMessageHandler*)); - MOCK_METHOD1(ResetAnnotatorMessageHandler, void(AnnotatorMessageHandler*)); + MOCK_METHOD1(SetAnnotatorPageHandler, void(AnnotatorPageHandlerImpl*)); + MOCK_METHOD1(ResetAnnotatorPageHandler, void(AnnotatorPageHandlerImpl*)); MOCK_METHOD1(SetTool, void(const AnnotatorTool&)); MOCK_METHOD0(Clear, void()); MOCK_METHOD1(NotifyAppUIActive, void(bool active));
diff --git a/ash/webui/projector_app/trusted_projector_annotator_ui.cc b/ash/webui/projector_app/trusted_projector_annotator_ui.cc index 9650a73..d8c2b3e9 100644 --- a/ash/webui/projector_app/trusted_projector_annotator_ui.cc +++ b/ash/webui/projector_app/trusted_projector_annotator_ui.cc
@@ -9,13 +9,14 @@ #include "ash/webui/grit/ash_projector_annotator_trusted_resources_map.h" #include "ash/webui/grit/ash_projector_common_resources.h" #include "ash/webui/grit/ash_projector_common_resources_map.h" -#include "ash/webui/projector_app/annotator_message_handler.h" +#include "ash/webui/projector_app/annotator_page_handler_impl.h" #include "ash/webui/projector_app/public/cpp/projector_app_constants.h" #include "components/prefs/pref_service.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_data_source.h" #include "content/public/common/url_constants.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" #include "services/network/public/mojom/content_security_policy.mojom.h" #include "url/gurl.h" @@ -59,14 +60,7 @@ content::WebUI* web_ui, const GURL& url, PrefService* pref_service) - : MojoBubbleWebUIController(web_ui, /*enable_chrome_send=*/true) { - // Multiple WebUIs (and therefore TrustedProjectorAnnotatorUIs) are created - // for a single Projector recording session, so a new AnnotatorMessageHandler - // needs to be created each time and attached to the new WebUI. The new - // handler is then referenced in ProjectorClientImpl. - auto handler = std::make_unique<ash::AnnotatorMessageHandler>(); - web_ui->AddMessageHandler(std::move(handler)); - + : MojoBubbleWebUIController(web_ui, /*enable_chrome_send=*/false) { CreateAndAddProjectorAnnotatorHTMLSource(web_ui); // The Annotator and Projector SWA embed contents in a sandboxed @@ -76,6 +70,27 @@ TrustedProjectorAnnotatorUI::~TrustedProjectorAnnotatorUI() = default; +void TrustedProjectorAnnotatorUI::BindInterface( + mojo::PendingReceiver<annotator::mojom::AnnotatorPageHandlerFactory> + receiver) { + if (receiver_.is_bound()) { + receiver_.reset(); + } + receiver_.Bind(std::move(receiver)); +} + +void TrustedProjectorAnnotatorUI::Create( + mojo::PendingReceiver<annotator::mojom::AnnotatorPageHandler> + annotator_handler, + mojo::PendingRemote<annotator::mojom::AnnotatorPage> annotator) { + // Multiple WebUIs (and therefore TrustedProjectorAnnotatorUIs) are created + // for a single Projector recording session, so a new AnnotatorMessageHandler + // needs to be created each time and attached to the new WebUI. The new + // handler is then referenced in ProjectorClientImpl. + handler_ = std::make_unique<AnnotatorPageHandlerImpl>( + std::move(annotator_handler), std::move(annotator), web_ui()); +} + WEB_UI_CONTROLLER_TYPE_IMPL(TrustedProjectorAnnotatorUI) } // namespace ash
diff --git a/ash/webui/projector_app/trusted_projector_annotator_ui.h b/ash/webui/projector_app/trusted_projector_annotator_ui.h index 9c427562..ea79b58 100644 --- a/ash/webui/projector_app/trusted_projector_annotator_ui.h +++ b/ash/webui/projector_app/trusted_projector_annotator_ui.h
@@ -5,7 +5,11 @@ #ifndef ASH_WEBUI_PROJECTOR_APP_TRUSTED_PROJECTOR_ANNOTATOR_UI_H_ #define ASH_WEBUI_PROJECTOR_APP_TRUSTED_PROJECTOR_ANNOTATOR_UI_H_ +#include "ash/webui/projector_app/mojom/annotator.mojom.h" #include "content/public/browser/web_ui_controller.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/pending_remote.h" +#include "mojo/public/cpp/bindings/receiver.h" #include "ui/webui/mojo_bubble_web_ui_controller.h" class GURL; @@ -13,9 +17,13 @@ namespace ash { +class AnnotatorPageHandlerImpl; + // The implementation for the Projector annotator for screen recording // annotations. -class TrustedProjectorAnnotatorUI : public ui::MojoBubbleWebUIController { +class TrustedProjectorAnnotatorUI + : public ui::MojoBubbleWebUIController, + annotator::mojom::AnnotatorPageHandlerFactory { public: TrustedProjectorAnnotatorUI(content::WebUI* web_ui, const GURL& url, @@ -25,8 +33,23 @@ TrustedProjectorAnnotatorUI& operator=(const TrustedProjectorAnnotatorUI&) = delete; + void BindInterface( + mojo::PendingReceiver<annotator::mojom::AnnotatorPageHandlerFactory> + factory); + private: WEB_UI_CONTROLLER_TYPE_DECL(); + + // annotator::mojom::AnnotatorPageHandlerFactory: + void Create( + mojo::PendingReceiver<annotator::mojom::AnnotatorPageHandler> + annotator_handler, + mojo::PendingRemote<annotator::mojom::AnnotatorPage> annotator) override; + + mojo::Receiver<annotator::mojom::AnnotatorPageHandlerFactory> receiver_{this}; + + // Handler for requests coming from the web_ui. + std::unique_ptr<AnnotatorPageHandlerImpl> handler_; }; } // namespace ash
diff --git a/ash/wm/multitask_menu_nudge_delegate_ash.cc b/ash/wm/multitask_menu_nudge_delegate_ash.cc index be4445e..de18787 100644 --- a/ash/wm/multitask_menu_nudge_delegate_ash.cc +++ b/ash/wm/multitask_menu_nudge_delegate_ash.cc
@@ -4,6 +4,7 @@ #include "ash/wm/multitask_menu_nudge_delegate_ash.h" +#include "ash/constants/ash_pref_names.h" #include "ash/session/session_controller_impl.h" #include "ash/shell.h" #include "ash/wm/tablet_mode/tablet_mode_multitask_cue.h" @@ -18,17 +19,13 @@ } std::string GetShowCountPrefName(bool tablet_mode) { - return tablet_mode - ? chromeos::MultitaskMenuNudgeController::kTabletShownCountPrefName - : chromeos::MultitaskMenuNudgeController:: - kClamshellShownCountPrefName; + return tablet_mode ? prefs::kMultitaskMenuNudgeTabletShownCount + : prefs::kMultitaskMenuNudgeClamshellShownCount; } std::string GetLastShownPrefName(bool tablet_mode) { - return tablet_mode - ? chromeos::MultitaskMenuNudgeController::kTabletLastShownPrefName - : chromeos::MultitaskMenuNudgeController:: - kClamshellLastShownPrefName; + return tablet_mode ? prefs::kMultitaskMenuNudgeTabletLastShown + : prefs::kMultitaskMenuNudgeClamshellLastShown; } } // namespace
diff --git a/base/base_switches.cc b/base/base_switches.cc index f396198b..88613473 100644 --- a/base/base_switches.cc +++ b/base/base_switches.cc
@@ -128,7 +128,7 @@ // Disable high-resolution timer on Windows. const char kDisableHighResTimer[] = "disable-highres-timer"; -// Disables the USB keyboard detection for blocking the OSK on Win8+. +// Disables the USB keyboard detection for blocking the OSK on Windows. const char kDisableUsbKeyboardDetect[] = "disable-usb-keyboard-detect"; #endif
diff --git a/base/command_line.cc b/base/command_line.cc index ae845dc..a5ccbce 100644 --- a/base/command_line.cc +++ b/base/command_line.cc
@@ -484,7 +484,7 @@ int num_args = 0; wchar_t** args = NULL; // When calling CommandLineToArgvW, use the apiset if available. - // Doing so will bypass loading shell32.dll on Win8+. + // Doing so will bypass loading shell32.dll on Windows. HMODULE downlevel_shell32_dll = ::LoadLibraryEx(L"api-ms-win-downlevel-shell32-l1-1-0.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
diff --git a/base/json/json_reader.cc b/base/json/json_reader.cc index 5b77bc2..83d51e9 100644 --- a/base/json/json_reader.cc +++ b/base/json/json_reader.cc
@@ -148,14 +148,6 @@ } // static -std::unique_ptr<Value> JSONReader::ReadDeprecated(StringPiece json, - int options, - size_t max_depth) { - absl::optional<Value> value = Read(json, options, max_depth); - return value ? Value::ToUniquePtrValue(std::move(*value)) : nullptr; -} - -// static JSONReader::Result JSONReader::ReadAndReturnValueWithError(StringPiece json, int options) { #if BUILDFLAG(BUILD_RUST_JSON_READER)
diff --git a/base/json/json_reader.h b/base/json/json_reader.h index 466bff3c..00d23cfc 100644 --- a/base/json/json_reader.h +++ b/base/json/json_reader.h
@@ -36,7 +36,6 @@ #ifndef BASE_JSON_JSON_READER_H_ #define BASE_JSON_JSON_READER_H_ -#include <memory> #include <string> #include "base/base_export.h" @@ -107,16 +106,6 @@ int options = JSON_PARSE_CHROMIUM_EXTENSIONS, size_t max_depth = internal::kAbsoluteMaxDepth); - // Deprecated. Use the Read() method above. - // Reads and parses |json|, returning a Value. - // If |json| is not a properly formed JSON string, returns nullptr. - // Wrap this in base::FooValue::From() to check the Value is of type Foo and - // convert to a FooValue at the same time. - static std::unique_ptr<Value> ReadDeprecated( - StringPiece json, - int options = JSON_PARSE_CHROMIUM_EXTENSIONS, - size_t max_depth = internal::kAbsoluteMaxDepth); - // Reads and parses |json| like Read(). On success returns a Value as the // expected value. Otherwise, it returns an Error instance, populated with a // formatted error message, an error code, and the error location if
diff --git a/base/metrics/field_trial.cc b/base/metrics/field_trial.cc index 98f387d..ff7025f 100644 --- a/base/metrics/field_trial.cc +++ b/base/metrics/field_trial.cc
@@ -12,6 +12,7 @@ #include "base/command_line.h" #include "base/logging.h" #include "base/metrics/field_trial_param_associator.h" +#include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "base/no_destructor.h" #include "base/notreached.h" @@ -642,6 +643,9 @@ DCHECK(global_->create_trials_from_command_line_called_); if (!global_->field_trial_allocator_) { + UmaHistogramBoolean( + "ChildProcess.FieldTrials.GetInitiallyActiveFieldTrials.FromString", + true); GetActiveFieldTrialGroupsFromString( command_line.GetSwitchValueASCII(switches::kForceFieldTrials), active_groups); @@ -738,6 +742,8 @@ // If the readonly handle did not get created, fall back to flags. if (!global_ || !global_->readonly_allocator_region_.IsValid()) { + UmaHistogramBoolean( + "ChildProcess.FieldTrials.PopulateLaunchOptions.CommandLine", true); AddFeatureAndFieldTrialFlags(command_line); return; }
diff --git a/base/task/sequence_manager/thread_controller.cc b/base/task/sequence_manager/thread_controller.cc index 6157f374..d96b50e 100644 --- a/base/task/sequence_manager/thread_controller.cc +++ b/base/task/sequence_manager/thread_controller.cc
@@ -61,8 +61,14 @@ base::HistogramBase::kUmaTargetedHistogramFlag); #if BUILDFLAG(ENABLE_BASE_TRACING) - perfetto_track_.emplace(reinterpret_cast<uint64_t>(this), - perfetto::ThreadTrack::Current()); + perfetto_track_.emplace( + reinterpret_cast<uint64_t>(this), + // TODO(crbug.com/1006541): Replace with ThreadTrack::Current() after SDK + // migration. + // In the non-SDK version, ThreadTrack::Current() returns a different + // track id on some platforms (for example Mac OS), which results in + // async tracks not being associated with their thread. + perfetto::ThreadTrack::ForThread(base::PlatformThread::CurrentId())); // TODO(1006541): Use Perfetto library to name this Track. // auto desc = perfetto_track_->Serialize(); // desc.set_name(JoinString({"MessagePumpPhases", thread_name}, " "));
diff --git a/base/threading/platform_thread_win.h b/base/threading/platform_thread_win.h index b06e773..18a7260 100644 --- a/base/threading/platform_thread_win.h +++ b/base/threading/platform_thread_win.h
@@ -14,9 +14,8 @@ namespace base { namespace internal { -// Assert that the memory priority of |thread| is |memory_priority|. No-op on -// Windows 7 because ::GetThreadInformation() is not available. Exposed for unit -// tests. +// Assert that the memory priority of `thread` is `memory_priority`. Exposed +// for unit tests. BASE_EXPORT void AssertMemoryPriority(HANDLE thread, int memory_priority); } // namespace internal
diff --git a/base/trace_event/trace_logging_minimal_win.h b/base/trace_event/trace_logging_minimal_win.h index f2c830c..346e6877 100644 --- a/base/trace_event/trace_logging_minimal_win.h +++ b/base/trace_event/trace_logging_minimal_win.h
@@ -346,49 +346,43 @@ // Helper for creating event descriptors for use with WriteEvent. constexpr EVENT_DESCRIPTOR TlmEventDescriptor(uint8_t level, uint64_t keyword) noexcept { - return { - // Id - // TraceLogging generally uses the event's Name instead of Id+Version, - // so Id is normally set to 0 for TraceLogging events. - 0, + return {// Id + // TraceLogging generally uses the event's Name instead of Id+Version, + // so Id is normally set to 0 for TraceLogging events. + 0, - // Version - // TraceLogging generally uses the event's Name instead of Id+Version, - // so Version is normally set to 0 for TraceLogging events. - 0, + // Version + // TraceLogging generally uses the event's Name instead of Id+Version, + // so Version is normally set to 0 for TraceLogging events. + 0, - // Channel (WINEVENT_CHANNEL_*) - // Setting Channel = 11 allows TraceLogging events to be decoded - // correctly even if they were collected on older operating systems. - // If a TraceLogging event sets channel to a value other than 11, the - // event will only decode correctly if it was collected on an - // operating system that has built-in TraceLogging support, i.e. - // Windows 7sp1 + patch, Windows 8.1 + patch, or Windows 10+. - 11, // = WINEVENT_CHANNEL_TRACELOGGING + // Channel (WINEVENT_CHANNEL_*) + // TraceLogging-based events normally use channel 11. + 11, // = WINEVENT_CHANNEL_TRACELOGGING - // Level (WINEVENT_LEVEL_*) - // 0=always, 1=fatal, 2=error, 3=warning, 4=info, 5=verbose. - // Levels higher than 5 are for user-defined debug levels. - level, + // Level (WINEVENT_LEVEL_*) + // 0=always, 1=fatal, 2=error, 3=warning, 4=info, 5=verbose. + // Levels higher than 5 are for user-defined debug levels. + level, - // Opcode (WINEVENT_OPCODE_*) - // Set Opcode for special semantics such as starting/ending an - // activity. - 0, // = WINEVENT_OPCODE_INFO + // Opcode (WINEVENT_OPCODE_*) + // Set Opcode for special semantics such as starting/ending an + // activity. + 0, // = WINEVENT_OPCODE_INFO - // Task - // Set Task for user-defined semantics. - 0, // = WINEVENT_TASK_NONE + // Task + // Set Task for user-defined semantics. + 0, // = WINEVENT_TASK_NONE - // Keyword - // A keyword is a 64-bit value used for filtering events. Each bit of - // the keyword indicates whether the event belongs to a particular - // category of events. The top 16 bits of keyword have - // Microsoft-defined semantics and should be set to 0. The low 48 bits - // of keyword have user-defined semantics. All events should use a - // nonzero keyword to support effective event filtering (events with - // keyword set to 0 always pass keyword filtering). - keyword}; + // Keyword + // A keyword is a 64-bit value used for filtering events. Each bit of + // the keyword indicates whether the event belongs to a particular + // category of events. The top 16 bits of keyword have + // Microsoft-defined semantics and should be set to 0. The low 48 bits + // of keyword have user-defined semantics. All events should use a + // nonzero keyword to support effective event filtering (events with + // keyword set to 0 always pass keyword filtering). + keyword}; } #endif // BASE_TRACE_EVENT_TRACE_LOGGING_MINIMAL_WIN_H_
diff --git a/base/win/pe_image.h b/base/win/pe_image.h index 7f3b0115f..b697493 100644 --- a/base/win/pe_image.h +++ b/base/win/pe_image.h
@@ -15,10 +15,6 @@ #include <stdint.h> -#if defined(_WIN32_WINNT_WIN8) -// The Windows 8 SDK defines FACILITY_VISUALCPP in winerror.h. -#undef FACILITY_VISUALCPP -#endif #include <DelayIMP.h> namespace base {
diff --git a/base/win/shortcut.h b/base/win/shortcut.h index 53b4b14..25f035b 100644 --- a/base/win/shortcut.h +++ b/base/win/shortcut.h
@@ -105,7 +105,7 @@ int icon_index = -1; // The app model id for the shortcut. std::wstring app_id; - // Whether this is a dual mode shortcut (Win8+). + // Whether this is a dual mode shortcut (Windows). bool dual_mode = false; // The CLSID of the COM object registered with the OS via the shortcut. This // is for app activation via user interaction with a toast notification in the
diff --git a/base/win/win_util.h b/base/win/win_util.h index c50b3c2..7ad82fc 100644 --- a/base/win/win_util.h +++ b/base/win/win_util.h
@@ -83,9 +83,8 @@ const PROPERTYKEY& property_key, const CLSID& property_clsid_value); -// Sets the application id in given IPropertyStore. The function is intended -// for tagging application/chromium shortcut, browser window and jump list for -// Win7. +// Sets the application id in given IPropertyStore. The function is used to tag +// application/Chrome shortcuts, and set app details for Chrome windows. BASE_EXPORT bool SetAppIdForPropertyStore(IPropertyStore* property_store, const wchar_t* app_id);
diff --git a/build/config/win/BUILD.gn b/build/config/win/BUILD.gn index a542f336..692e7adf 100644 --- a/build/config/win/BUILD.gn +++ b/build/config/win/BUILD.gn
@@ -285,10 +285,7 @@ } } -# Chromium supports running on Windows 7, but if these constants are set to -# Windows 7, then newer APIs aren't made available by the Windows SDK. -# So we set this to Windows 10 and then are careful to check at runtime -# to only call newer APIs when they're available. +# Chromium only supports Windowes 10+. # Some third-party libraries assume that these defines set what version of # Windows is available at runtime. Targets using these libraries need to # manually override this config for their compiles.
diff --git a/cc/slim/frame_sink_impl.cc b/cc/slim/frame_sink_impl.cc index 7776c3f8..48a267e5 100644 --- a/cc/slim/frame_sink_impl.cc +++ b/cc/slim/frame_sink_impl.cc
@@ -53,7 +53,10 @@ io_thread_id_(io_thread_id) {} FrameSinkImpl::~FrameSinkImpl() { - for (const auto& uploaded_resource_pair : uploaded_resources_) { + // Iterate a copy of `uploaded_resources_` since it might be modified + // when `UIResourceReleased()` is called. + for (const auto& uploaded_resource_pair : + UploadedResourceMap(uploaded_resources_)) { resource_provider_.RemoveImportedResource( uploaded_resource_pair.second.viz_resource_id); } @@ -160,6 +163,7 @@ uploaded_resource.size = resource_bitmap.GetSize(); uploaded_resource.is_opaque = resource_bitmap.GetOpaque(); + DCHECK(!uploaded_resources_.contains(resource_id)); uploaded_resources_.emplace(resource_id, uploaded_resource); }
diff --git a/cc/slim/layer_tree_cc_wrapper.cc b/cc/slim/layer_tree_cc_wrapper.cc index 3322b450..46a1f77 100644 --- a/cc/slim/layer_tree_cc_wrapper.cc +++ b/cc/slim/layer_tree_cc_wrapper.cc
@@ -76,7 +76,9 @@ cc::LayerTreeHost::CreateSingleThreaded(this, std::move(cc_init_params)); } -LayerTreeCcWrapper::~LayerTreeCcWrapper() = default; +LayerTreeCcWrapper::~LayerTreeCcWrapper() { + SetRoot(nullptr); +} cc::UIResourceManager* LayerTreeCcWrapper::GetUIResourceManager() { return host_->GetUIResourceManager(); @@ -150,9 +152,13 @@ root_->SetLayerTree(nullptr); } root_ = std::move(root); - root_->SetLayerTree(this); - DCHECK(root_->cc_layer_); - host_->SetRootLayer(root_->cc_layer_); + if (root_) { + root_->SetLayerTree(this); + DCHECK(root_->cc_layer_); + host_->SetRootLayer(root_->cc_layer_); + } else { + host_->SetRootLayer(nullptr); + } } void LayerTreeCcWrapper::SetFrameSink(std::unique_ptr<FrameSink> sink) {
diff --git a/cc/slim/layer_tree_impl.cc b/cc/slim/layer_tree_impl.cc index 815dabea..0eff70f 100644 --- a/cc/slim/layer_tree_impl.cc +++ b/cc/slim/layer_tree_impl.cc
@@ -43,7 +43,9 @@ LayerTreeImpl::LayerTreeImpl(LayerTreeClient* client) : client_(client) {} -LayerTreeImpl::~LayerTreeImpl() = default; +LayerTreeImpl::~LayerTreeImpl() { + SetRoot(nullptr); +} cc::UIResourceManager* LayerTreeImpl::GetUIResourceManager() { return &ui_resource_manager_; @@ -116,6 +118,7 @@ } } copy_requests_for_next_frame_.push_back(std::move(request)); + SetNeedsDraw(); } base::OnceClosure LayerTreeImpl::DeferBeginFrame() {
diff --git a/cc/slim/slim_layer_tree_compositor_frame_unittest.cc b/cc/slim/slim_layer_tree_compositor_frame_unittest.cc index 23b1e24..0680efd 100644 --- a/cc/slim/slim_layer_tree_compositor_frame_unittest.cc +++ b/cc/slim/slim_layer_tree_compositor_frame_unittest.cc
@@ -500,6 +500,10 @@ auto solid_color_layer = CreateSolidColorLayer(viewport_.size(), SkColors::kGray); layer_tree_->SetRoot(solid_color_layer); + { + viz::CompositorFrame frame = ProduceFrame(); + EXPECT_FALSE(layer_tree_->NeedsBeginFrames()); + } auto copy_request_no_source_1 = std::make_unique<viz::CopyOutputRequest>( viz::CopyOutputRequest::ResultFormat::RGBA, @@ -531,6 +535,7 @@ copy_request_with_difference_source->set_source(token2); layer_tree_->RequestCopyOfOutput(std::move(copy_request_no_source_1)); + EXPECT_TRUE(layer_tree_->NeedsBeginFrames()); layer_tree_->RequestCopyOfOutput(std::move(copy_request_no_source_2)); layer_tree_->RequestCopyOfOutput(std::move(copy_request_with_source)); layer_tree_->RequestCopyOfOutput(std::move(copy_request_with_same_source)); @@ -635,6 +640,50 @@ } } +TEST_F(SlimLayerTreeCompositorFrameTest, ReclaimResources) { + constexpr size_t kNumLayers = 6; + std::vector<scoped_refptr<UIResourceLayer>> layers; + for (size_t i = 0; i < kNumLayers; ++i) { + layers.push_back(UIResourceLayer::Create()); + layers[i]->SetBounds(viewport_.size()); + layers[i]->SetIsDrawable(true); + if (i == 0u) { + layer_tree_->SetRoot(layers[i]); + } else { + layers[i - 1]->AddChild(layers[i]); + } + + auto image_info = + SkImageInfo::Make(1, 1, kN32_SkColorType, kPremul_SkAlphaType); + SkBitmap bitmap; + bitmap.allocPixels(image_info); + bitmap.setImmutable(); + layers[i]->SetBitmap(bitmap); + } + + viz::CompositorFrame frame = ProduceFrame(); + EXPECT_EQ(frame.resource_list.size(), kNumLayers); + for (size_t i = 0; i < kNumLayers; ++i) { + EXPECT_TRUE(frame_sink_->client_resource_provider()->InUseByConsumer( + frame.resource_list[i].id)); + } + + // Return every other resource. + std::vector<viz::ReturnedResource> returned_resources; + for (size_t i = 0; i < kNumLayers; i += 2) { + returned_resources.push_back(frame.resource_list[i].ToReturnedResource()); + } + frame_sink_->ReclaimResources(std::move(returned_resources)); + for (size_t i = 0; i < kNumLayers; i += 2) { + EXPECT_FALSE(frame_sink_->client_resource_provider()->InUseByConsumer( + frame.resource_list[i].id)); + } + for (size_t i = 1; i < kNumLayers; i += 2) { + EXPECT_TRUE(frame_sink_->client_resource_provider()->InUseByConsumer( + frame.resource_list[i].id)); + } +} + TEST_F(SlimLayerTreeCompositorFrameTest, NinePatchLayerAppendQuads) { auto nine_patch_layer = NinePatchLayer::Create(); nine_patch_layer->SetBounds(viewport_.size());
diff --git a/cc/slim/slim_layer_tree_unittest.cc b/cc/slim/slim_layer_tree_unittest.cc index 50f24300..6bfcef2 100644 --- a/cc/slim/slim_layer_tree_unittest.cc +++ b/cc/slim/slim_layer_tree_unittest.cc
@@ -234,6 +234,27 @@ std::vector<viz::SurfaceRange>()); } +TEST_F(SlimLayerTreeTest, DestroyTreeBeforeLayer) { + // Regression test for use after free. + auto root_layer = Layer::Create(); + + // Use SurfaceLayer here because it accesses LayerTreeImpl pointer in + // SetLayerTree. + auto surface_layer = SurfaceLayer::Create(); + root_layer->AddChild(surface_layer); + base::UnguessableToken token = base::UnguessableToken::Create(); + viz::SurfaceId end(viz::FrameSinkId(1u, 2u), + viz::LocalSurfaceId(5u, 6u, token)); + surface_layer->SetSurfaceId(end, cc::DeadlinePolicy::UseDefaultDeadline()); + + layer_tree_->SetRoot(root_layer); + + layer_tree_.reset(); + + EXPECT_EQ(root_layer->layer_tree(), nullptr); + EXPECT_EQ(surface_layer->layer_tree(), nullptr); +} + } // namespace } // namespace cc::slim
diff --git a/cc/slim/surface_layer.cc b/cc/slim/surface_layer.cc index 690fae9..232b808 100644 --- a/cc/slim/surface_layer.cc +++ b/cc/slim/surface_layer.cc
@@ -121,6 +121,10 @@ return; } + if (layer_tree() == tree) { + return; + } + if (layer_tree() && surface_range_.IsValid()) { static_cast<LayerTreeImpl*>(layer_tree()) ->RemoveSurfaceRange(surface_range_);
diff --git a/chrome/VERSION b/chrome/VERSION index 8a7b4b7..faa4e64 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=113 MINOR=0 -BUILD=5621 +BUILD=5622 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index c38a8877..9703e28 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -414,11 +414,11 @@ "//components/commerce/core/android:core_java", "//components/component_updater/android:background_task_update_scheduler_java", "//components/content_capture/android:java", + "//components/content_relationship_verification/android:java", "//components/content_settings/android:content_settings_enums_java", "//components/content_settings/android:java", "//components/crash/android:anr_collector_java", "//components/crash/android:java", - "//components/digital_asset_links/android:java", "//components/digital_goods/mojom:mojom_java", "//components/dom_distiller/content/browser/android:dom_distiller_content_java", "//components/dom_distiller/core/android:dom_distiller_core_java", @@ -770,6 +770,7 @@ "//chrome/browser/android/policy/policy_auditor.cc", "//chrome/browser/android/webapk/webapk_installer.h", "//chrome/browser/long_screenshots/long_screenshots_tab_service.h", + "//chrome/browser/metrics/metrics_reporting_state.h", "//chrome/browser/notifications/notification_handler.h", "//chrome/browser/notifications/notification_platform_bridge_android.cc", ] @@ -1024,9 +1025,9 @@ "//components/commerce/core:proto_java", "//components/commerce/core/android:core_java", "//components/content_capture/android:java", + "//components/content_relationship_verification/android:java", + "//components/content_relationship_verification/android:junit_test_support", "//components/content_settings/android:content_settings_enums_java", - "//components/digital_asset_links/android:java", - "//components/digital_asset_links/android:junit_test_support", "//components/digital_goods/mojom:mojom_java", "//components/dom_distiller/core/android:dom_distiller_core_java", "//components/embedder_support/android:content_view_java", @@ -3725,7 +3726,7 @@ "//chrome/browser/ui/messages/android:jni_headers", "//chrome/browser/util:jni_headers", "//chrome/browser/webauthn/android:jni_headers", - "//components/digital_asset_links/android:jni_headers", + "//components/content_relationship_verification/android:jni_headers", "//components/image_fetcher:jni_headers", "//components/media_router/browser/android:jni_headers", "//components/ukm/android:jni_headers",
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogCoordinator.java index 4a72046b..86ffa34 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogCoordinator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogCoordinator.java
@@ -5,7 +5,6 @@ package org.chromium.chrome.browser.tasks.tab_management; import android.app.Activity; -import android.content.Context; import android.graphics.Rect; import android.view.LayoutInflater; import android.view.ViewGroup; @@ -61,11 +60,13 @@ TabListMediator.GridCardOnClickListenerProvider gridCardOnClickListenerProvider, TabGridDialogMediator.AnimationSourceViewProvider animationSourceViewProvider, Supplier<ShareDelegate> shareDelegateSupplier, ScrimCoordinator scrimCoordinator, - ViewGroup rootView) { + TabGroupTitleEditor tabGroupTitleEditor, ViewGroup rootView) { try (TraceEvent e = TraceEvent.scoped("TabGridDialogCoordinator.constructor")) { mActivity = activity; mComponentName = animationSourceViewProvider == null ? "TabGridDialogFromStrip" : "TabGridDialogInSwitcher"; + mTabModelSelector = tabModelSelector; + mTabContentManager = tabContentManager; mModel = new PropertyModel(TabGridPanelProperties.ALL_KEYS); mRootView = rootView; @@ -119,15 +120,10 @@ TabGridPanelViewBinder::bind); mBackPressChangedSupplier.set(isVisible()); mModel.addObserver((source, key) -> mBackPressChangedSupplier.set(isVisible())); - } - } - public void initWithNative(Context context, TabModelSelector tabModelSelector, - TabContentManager tabContentManager, TabGroupTitleEditor tabGroupTitleEditor) { - try (TraceEvent e = TraceEvent.scoped("TabGridDialogCoordinator.initWithNative")) { - mTabModelSelector = tabModelSelector; - mTabContentManager = tabContentManager; - + // This is always created post-native so calling these immediately is safe. + // TODO(crbug/1418690): Consider inlining these behaviors in their respective + // constructors if possible. mMediator.initWithNative(this::getTabSelectionEditorController, tabGroupTitleEditor); mTabListCoordinator.initWithNative(null); }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiCoordinator.java index 8dfdf7b..65b9b41 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiCoordinator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiCoordinator.java
@@ -81,6 +81,7 @@ private final TabContentManager mTabContentManager; private PropertyModelChangeProcessor mModelChangeProcessor; private TabGridDialogCoordinator mTabGridDialogCoordinator; + private Supplier<TabGridDialogMediator.DialogController> mTabGridDialogControllerSupplier; private TabListCoordinator mTabStripCoordinator; private TabGroupUiMediator mMediator; @@ -127,6 +128,16 @@ } } + private void initTabGridDialogCoordinator() { + assert mTabGridDialogControllerSupplier != null; + if (mTabGridDialogCoordinator != null) return; + + mTabGridDialogCoordinator = new TabGridDialogCoordinator(mActivity, mTabModelSelector, + mTabContentManager, mTabCreatorManager, mActivity.findViewById(R.id.coordinator), + null, null, null, mShareDelegateSupplier, mScrimCoordinator, + mTabStripCoordinator.getTabGroupTitleEditor(), mRootView); + } + /** * Handle any initialization that occurs once native has been loaded. */ @@ -154,21 +165,29 @@ // TODO(crbug.com/972217): find a way to enable interactions between grid tab switcher // and the dialog here. - TabGridDialogMediator.DialogController dialogController = null; if (TabUiFeatureUtilities.isTabGroupsAndroidEnabled(activity) && mScrimCoordinator != null) { - mTabGridDialogCoordinator = new TabGridDialogCoordinator(mActivity, - mTabModelSelector, mTabContentManager, mTabCreatorManager, - mActivity.findViewById(R.id.coordinator), null, null, null, - mShareDelegateSupplier, mScrimCoordinator, mRootView); - mTabGridDialogCoordinator.initWithNative(mContext, mTabModelSelector, - mTabContentManager, mTabStripCoordinator.getTabGroupTitleEditor()); - dialogController = mTabGridDialogCoordinator.getDialogController(); + mTabGridDialogControllerSupplier = + new Supplier<TabGridDialogMediator.DialogController>() { + @Override + public TabGridDialogMediator.DialogController get() { + initTabGridDialogCoordinator(); + return mTabGridDialogCoordinator.getDialogController(); + } + + @Override + public boolean hasValue() { + return mTabGridDialogCoordinator != null; + } + }; + } else { + mTabGridDialogControllerSupplier = null; } mMediator = new TabGroupUiMediator(mActivity, visibilityController, this, mModel, mTabModelSelector, mTabCreatorManager, mLayoutStateProviderSupplier, - mIncognitoStateProvider, dialogController, mOmniboxFocusStateSupplier); + mIncognitoStateProvider, mTabGridDialogControllerSupplier, + mOmniboxFocusStateSupplier); TabGroupUtils.startObservingForCreationIPH(); @@ -220,8 +239,8 @@ */ @Override public void resetGridWithListOfTabs(List<Tab> tabs) { - if (mTabGridDialogCoordinator != null) { - mTabGridDialogCoordinator.resetWithListOfTabs(tabs); + if (mTabGridDialogControllerSupplier != null) { + mTabGridDialogControllerSupplier.get().resetWithListOfTabs(tabs); } }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java index 855bfb3..65718075a 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java
@@ -17,6 +17,7 @@ import org.chromium.base.metrics.RecordUserAction; import org.chromium.base.supplier.ObservableSupplier; import org.chromium.base.supplier.OneshotSupplier; +import org.chromium.base.supplier.Supplier; import org.chromium.chrome.browser.layouts.LayoutStateProvider; import org.chromium.chrome.browser.layouts.LayoutStateProvider.LayoutStateObserver; import org.chromium.chrome.browser.layouts.LayoutType; @@ -99,7 +100,7 @@ private final BottomControlsCoordinator .BottomControlsVisibilityController mVisibilityController; private final IncognitoStateProvider mIncognitoStateProvider; - private final TabGridDialogMediator.DialogController mTabGridDialogController; + private final Supplier<TabGridDialogMediator.DialogController> mTabGridDialogControllerSupplier; private final IncognitoStateObserver mIncognitoStateObserver; private final TabModelSelectorObserver mTabModelSelectorObserver; private final ObservableSupplier<Boolean> mOmniboxFocusStateSupplier; @@ -119,7 +120,7 @@ TabCreatorManager tabCreatorManager, OneshotSupplier<LayoutStateProvider> layoutStateProviderSupplier, IncognitoStateProvider incognitoStateProvider, - @Nullable TabGridDialogMediator.DialogController dialogController, + @Nullable Supplier<TabGridDialogMediator.DialogController> dialogControllerSupplier, ObservableSupplier<Boolean> omniboxFocusStateSupplier) { mContext = context; mResetHandler = resetHandler; @@ -128,7 +129,7 @@ mTabCreatorManager = tabCreatorManager; mVisibilityController = visibilityController; mIncognitoStateProvider = incognitoStateProvider; - mTabGridDialogController = dialogController; + mTabGridDialogControllerSupplier = dialogControllerSupplier; mOmniboxFocusStateSupplier = omniboxFocusStateSupplier; if (layoutStateProviderSupplier.get() != null @@ -412,21 +413,27 @@ public boolean onBackPressed() { // TODO(crbug.com/1006421): add a regression test to make sure that the back button closes // the dialog when the dialog is showing. - return mTabGridDialogController != null && mTabGridDialogController.handleBackPressed(); + return mTabGridDialogControllerSupplier != null + && mTabGridDialogControllerSupplier.hasValue() + && mTabGridDialogControllerSupplier.get().handleBackPressed(); } @Override public @BackPressResult int handleBackPress() { - if (mTabGridDialogController != null) return mTabGridDialogController.handleBackPress(); + if (mTabGridDialogControllerSupplier != null + && mTabGridDialogControllerSupplier.hasValue()) { + return mTabGridDialogControllerSupplier.get().handleBackPress(); + } return BackPressResult.FAILURE; } @Override public ObservableSupplier<Boolean> getHandleBackPressChangedSupplier() { - if (mTabGridDialogController == null) { + if (mTabGridDialogControllerSupplier == null + || !mTabGridDialogControllerSupplier.hasValue()) { return BackPressHandler.super.getHandleBackPressChangedSupplier(); } - return mTabGridDialogController.getHandleBackPressChangedSupplier(); + return mTabGridDialogControllerSupplier.get().getHandleBackPressChangedSupplier(); } public void destroy() {
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherCoordinator.java index 599e4f7..d2c78ec 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherCoordinator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherCoordinator.java
@@ -19,6 +19,8 @@ import androidx.recyclerview.widget.RecyclerView.ViewHolder; import org.chromium.base.Callback; +import org.chromium.base.Promise; +import org.chromium.base.ThreadUtils; import org.chromium.base.TraceEvent; import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.metrics.RecordUserAction; @@ -119,8 +121,10 @@ private final TabListCoordinator mTabListCoordinator; private final TabSwitcherMediator mMediator; private final MultiThumbnailCardProvider mMultiThumbnailCardProvider; + private final ScrimCoordinator mGridDialogScrimCoordinator; + private final boolean mUsesTabGridDialogCoordinator; @Nullable - private final TabGridDialogCoordinator mTabGridDialogCoordinator; + private TabGridDialogCoordinator mTabGridDialogCoordinator; private final TabModelSelector mTabModelSelector; private final @TabListCoordinator.TabListMode int mMode; private final MessageCardProviderCoordinator mMessageCardProviderCoordinator; @@ -198,10 +202,58 @@ PropertyModel containerViewModel = new PropertyModel(TabListContainerProperties.ALL_KEYS); + OneshotSupplier<TabGridDialogMediator.DialogController> dialogControllerSupplier = null; + if (TabUiFeatureUtilities.isTabGroupsAndroidEnabled(activity)) { + mGridDialogScrimCoordinator = + shouldUseNewScrim() ? createScrimCoordinator() : scrimCoordinator; + mUsesTabGridDialogCoordinator = true; + dialogControllerSupplier = + new OneshotSupplier<TabGridDialogMediator.DialogController>() { + // Implementation is based on OneshotSupplierImpl with modifications + // such that onAvailable does not invoke get() unless the object already + // exists this prevents callers of onAvailable from triggering the lazy + // creation of the TabGridDialogCoordinator before it is required. + private final Promise<TabGridDialogMediator.DialogController> mPromise = + new Promise<>(); + private final ThreadUtils.ThreadChecker mThreadChecker = + new ThreadUtils.ThreadChecker(); + + @Override + public TabGridDialogMediator.DialogController onAvailable( + Callback<TabGridDialogMediator.DialogController> callback) { + mThreadChecker.assertOnValidThread(); + mPromise.then(callback); + if (!hasValue()) return null; + + return get(); + } + + @Override + public TabGridDialogMediator.DialogController get() { + mThreadChecker.assertOnValidThread(); + if (initTabGridDialogCoordinator()) { + assert !mPromise.isFulfilled(); + mPromise.fulfill( + mTabGridDialogCoordinator.getDialogController()); + } + assert mPromise.isFulfilled(); + return mPromise.getResult(); + } + + @Override + public boolean hasValue() { + return mTabGridDialogCoordinator != null; + } + }; + } else { + mGridDialogScrimCoordinator = null; + mUsesTabGridDialogCoordinator = false; + mTabGridDialogCoordinator = null; + } mMediator = new TabSwitcherMediator(activity, this, containerViewModel, tabModelSelector, browserControls, container, tabContentManager, this, this, multiWindowModeStateDispatcher, mode, incognitoReauthControllerSupplier, - backPressManager); + backPressManager, dialogControllerSupplier); mTabSwitcherCustomViewManager = new TabSwitcherCustomViewManager(mMediator); @@ -275,19 +327,6 @@ } }); - if (TabUiFeatureUtilities.isTabGroupsAndroidEnabled(activity)) { - ScrimCoordinator gridDialogScrimCoordinator = - shouldUseNewScrim() ? createScrimCoordinator() : scrimCoordinator; - mTabGridDialogCoordinator = new TabGridDialogCoordinator(activity, tabModelSelector, - tabContentManager, tabCreatorManager, mCoordinatorView, this, mMediator, - this::getTabGridDialogAnimationSourceView, shareDelegateSupplier, - gridDialogScrimCoordinator, rootView); - mMediator.setTabGridDialogController( - mTabGridDialogCoordinator.getDialogController()); - } else { - mTabGridDialogCoordinator = null; - } - mMenuOrKeyboardActionController = menuOrKeyboardActionController; if (mode == TabListCoordinator.TabListMode.GRID) { @@ -369,6 +408,22 @@ } /** + * @return false if already initialized or true when first initialized. + */ + private boolean initTabGridDialogCoordinator() { + assert mUsesTabGridDialogCoordinator; + if (mTabGridDialogCoordinator != null) return false; + + mTabGridDialogCoordinator = + new TabGridDialogCoordinator(mActivity, mTabModelSelector, mTabContentManager, + mTabCreatorManager, mCoordinatorView, TabSwitcherCoordinator.this, + mMediator, TabSwitcherCoordinator.this::getTabGridDialogAnimationSourceView, + mShareDelegateSupplier, mGridDialogScrimCoordinator, + mTabListCoordinator.getTabGroupTitleEditor(), mRootView); + return true; + } + + /** * Tablet Tab Switcher polish uses a scrim to show/hide tab switcher. * Create a new scrim via a new scrim coordinator for tab group dialog. * @return if tab switcher polish is enabled on tablets. @@ -416,11 +471,6 @@ setUpTabGroupManualSelectionMode(mActivity); } } - if (TabUiFeatureUtilities.isTabGroupsAndroidEnabled(mActivity) - && mTabGridDialogCoordinator != null) { - mTabGridDialogCoordinator.initWithNative(mActivity, mTabModelSelector, - mTabContentManager, mTabListCoordinator.getTabGroupTitleEditor()); - } final TabSelectionEditorController controller = mTabSelectionEditorCoordinator != null ? mTabSelectionEditorCoordinator.getController() @@ -574,8 +624,15 @@ @Override public Supplier<Boolean> getTabGridDialogVisibilitySupplier() { - if (mTabGridDialogCoordinator != null) { - return mTabGridDialogCoordinator::isVisible; + if (mUsesTabGridDialogCoordinator) { + // mTabGridDialogCoordinator is lazily created when first displaying something in the + // dialog. Return false until it has shown something. + return () -> { + if (mTabGridDialogCoordinator != null) { + return mTabGridDialogCoordinator.isVisible(); + } + return false; + }; } return () -> false; }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java index 3d45856..df98be4 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java
@@ -149,7 +149,8 @@ private CallbackController mCallbackController; private Integer mSoftCleanupDelayMsForTesting; private Integer mCleanupDelayMsForTesting; - private TabGridDialogMediator.DialogController mTabGridDialogController; + private OneshotSupplier<TabGridDialogMediator.DialogController> + mTabGridDialogControllerSupplier; private TabSelectionEditorCoordinator .TabSelectionEditorController mTabSelectionEditorController; private TabSwitcher.OnTabSelectingListener mOnTabSelectingListener; @@ -280,6 +281,8 @@ * @param incognitoReauthControllerSupplier {@link OneshotSupplier<IncognitoReauthController>} * to detect pending re-auth when tab switcher is shown. * @param backPressManager {@link BackPressManager} to handle back press gesture. + * @param tabGridDialogControllerSupplier {@link TabGridDialogMediator.DialogController} + * supplier for lazy initialization on first use. */ TabSwitcherMediator(Context context, ResetHandler resetHandler, PropertyModel containerViewModel, TabModelSelector tabModelSelector, @@ -288,7 +291,9 @@ PriceWelcomeMessageController priceWelcomeMessageController, MultiWindowModeStateDispatcher multiWindowModeStateDispatcher, @TabListMode int mode, @Nullable OneshotSupplier<IncognitoReauthController> incognitoReauthControllerSupplier, - @Nullable BackPressManager backPressManager) { + @Nullable BackPressManager backPressManager, + @Nullable OneshotSupplier<TabGridDialogMediator.DialogController> + tabGridDialogControllerSupplier) { mResetHandler = resetHandler; mContainerViewModel = containerViewModel; mTabModelSelector = tabModelSelector; @@ -321,8 +326,9 @@ mTabModelSelector.getTabModelFilterProvider().getCurrentTabModelFilter(); mContainerViewModel.set(IS_INCOGNITO, currentTabModelFilter.isIncognito()); notifyBackPressStateChangedInternal(); - if (mTabGridDialogController != null) { - mTabGridDialogController.hideDialog(false); + if (mTabGridDialogControllerSupplier != null + && mTabGridDialogControllerSupplier.hasValue()) { + mTabGridDialogControllerSupplier.get().hideDialog(false); } if (!mContainerViewModel.get(IS_VISIBLE)) return; @@ -530,6 +536,14 @@ }; mMultiWindowModeStateDispatcher.addObserver(mMultiWindowModeObserver); notifyBackPressStateChangedInternal(); + + mTabGridDialogControllerSupplier = tabGridDialogControllerSupplier; + if (mTabGridDialogControllerSupplier != null) { + mTabGridDialogControllerSupplier.onAvailable((tabGridDialogController) -> { + tabGridDialogController.getHandleBackPressChangedSupplier().addObserver( + mNotifyBackPressedCallback); + }); + } } /** @@ -558,17 +572,6 @@ } } - /** - * Set the controller of the TabGridDialog so that it can be directly controlled. - * @param tabGridDialogController The handler of the Grid Dialog - */ - void setTabGridDialogController( - TabGridDialogMediator.DialogController tabGridDialogController) { - mTabGridDialogController = tabGridDialogController; - mTabGridDialogController.getHandleBackPressChangedSupplier().addObserver( - mNotifyBackPressedCallback); - } - @VisibleForTesting int getSoftCleanupDelayForTesting() { return getSoftCleanupDelay(); @@ -730,10 +733,11 @@ @Override public void prepareHideTabSwitcherView() { - if (mTabGridDialogController != null) { + if (mTabGridDialogControllerSupplier != null + && mTabGridDialogControllerSupplier.hasValue()) { // Don't wait until switcher container view hides. // Hide dialog before GTS hides. - mTabGridDialogController.hideDialog(false); + mTabGridDialogControllerSupplier.get().hideDialog(false); } } @@ -743,10 +747,11 @@ setVisibility(false); mContainerViewModel.set(ANIMATE_VISIBILITY_CHANGES, true); - if (mTabGridDialogController != null) { + if (mTabGridDialogControllerSupplier != null + && mTabGridDialogControllerSupplier.hasValue()) { // Don't wait until didSelectTab(), which is after the GTS animation. // We need to hide the dialog immediately. - mTabGridDialogController.hideDialog(false); + mTabGridDialogControllerSupplier.get().hideDialog(false); } } @@ -864,7 +869,8 @@ return false; } - if (mTabGridDialogController != null && mTabGridDialogController.handleBackPressed()) { + if (mTabGridDialogControllerSupplier != null && mTabGridDialogControllerSupplier.hasValue() + && mTabGridDialogControllerSupplier.get().handleBackPressed()) { return true; } @@ -897,7 +903,8 @@ return true; } - if (mTabGridDialogController != null && mTabGridDialogController.isVisible()) { + if (mTabGridDialogControllerSupplier != null && mTabGridDialogControllerSupplier.hasValue() + && mTabGridDialogControllerSupplier.get().isVisible()) { return true; } return false; @@ -1016,9 +1023,11 @@ mNotifyBackPressedCallback); } - if (mTabGridDialogController != null) { - mTabGridDialogController.getHandleBackPressChangedSupplier().removeObserver( - mNotifyBackPressedCallback); + if (mTabGridDialogControllerSupplier != null + && mTabGridDialogControllerSupplier.hasValue()) { + mTabGridDialogControllerSupplier.get() + .getHandleBackPressChangedSupplier() + .removeObserver(mNotifyBackPressedCallback); } if (mIncognitoReauthController != null) { @@ -1050,13 +1059,13 @@ public TabListMediator.TabActionListener openTabGridDialog(Tab tab) { if (!ableToOpenDialog(tab)) return null; assert getRelatedTabs(tab.getId()).size() != 1; - assert mTabGridDialogController != null; + assert mTabGridDialogControllerSupplier != null; return tabId -> { List<Tab> relatedTabs = getRelatedTabs(tabId); if (relatedTabs.size() == 0) { relatedTabs = null; } - mTabGridDialogController.resetWithListOfTabs(relatedTabs); + mTabGridDialogControllerSupplier.get().resetWithListOfTabs(relatedTabs); RecordUserAction.record("TabGridDialog.ExpandedFromSwitcher"); }; }
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediatorUnitTest.java index e20bf9c5f..480a93d4 100644 --- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediatorUnitTest.java +++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediatorUnitTest.java
@@ -45,6 +45,7 @@ import org.chromium.base.Callback; import org.chromium.base.supplier.ObservableSupplier; import org.chromium.base.supplier.OneshotSupplierImpl; +import org.chromium.base.supplier.Supplier; import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.layouts.LayoutStateProvider; @@ -205,9 +206,12 @@ TabGridDialogMediator.DialogController controller = TabUiFeatureUtilities.isTabGroupsAndroidEnabled(mContext) ? mTabGridDialogController : null; + Supplier<TabGridDialogMediator.DialogController> controllerSupplier = () -> { + return controller; + }; mTabGroupUiMediator = new TabGroupUiMediator(mContext, mVisibilityController, mResetHandler, mModel, mTabModelSelector, mTabCreatorManager, mLayoutStateProviderSupplier, - mIncognitoStateProvider, controller, mOmniboxFocusStateSupplier); + mIncognitoStateProvider, controllerSupplier, mOmniboxFocusStateSupplier); if (currentTab == null) { verifyNeverReset();
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediatorUnitTest.java index 0813a60..ee6b6f7 100644 --- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediatorUnitTest.java +++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediatorUnitTest.java
@@ -19,6 +19,7 @@ import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.reset; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; @@ -107,6 +108,8 @@ private final OneshotSupplierImpl<IncognitoReauthController> mIncognitoReauthControllerSupplier = new OneshotSupplierImpl<>(); + private final OneshotSupplierImpl<TabGridDialogMediator.DialogController> + mTabGridDialogControllerSupplier = new OneshotSupplierImpl<>(); @Mock TabSwitcherMediator.ResetHandler mResetHandler; @@ -161,6 +164,9 @@ private ArgumentCaptor<IncognitoReauthManager.IncognitoReauthCallback> mIncognitoReauthCallbackArgumentCaptor; + @Mock + private TabSelectionEditorCoordinator.TabSelectionEditorController mEditorController; + private Tab mTab1; private Tab mTab2; private Tab mTab3; @@ -218,25 +224,25 @@ doReturn(true) .when(mMultiWindowModeStateDispatcher) .addObserver(mMultiWindowModeObserverCaptor.capture()); - TabSelectionEditorCoordinator.TabSelectionEditorController controller = - mock(TabSelectionEditorCoordinator.TabSelectionEditorController.class); doReturn(new ObservableSupplierImpl<Boolean>()) - .when(controller) + .when(mEditorController) .getHandleBackPressChangedSupplier(); doReturn(new ObservableSupplierImpl<Boolean>()) .when(mTabGridDialogController) .getHandleBackPressChangedSupplier(); when(mIncognitoReauthController.isIncognitoReauthPending()).thenReturn(false); mIncognitoReauthControllerSupplier.set(mIncognitoReauthController); + mTabGridDialogControllerSupplier.set(mTabGridDialogController); mModel = new PropertyModel(TabListContainerProperties.ALL_KEYS); mModel.addObserver(mPropertyObserver); mMediator = new TabSwitcherMediator(mContext, mResetHandler, mModel, mTabModelSelector, mBrowserControlsStateProvider, mCompositorViewHolder, null, mMessageItemsController, mPriceWelcomeMessageController, mMultiWindowModeStateDispatcher, - TabListCoordinator.TabListMode.GRID, mIncognitoReauthControllerSupplier, null); + TabListCoordinator.TabListMode.GRID, mIncognitoReauthControllerSupplier, null, + mTabGridDialogControllerSupplier); - mMediator.initWithNative(controller, null); + mMediator.initWithNative(mEditorController, null); mMediator.addTabSwitcherViewObserver(mTabSwitcherViewObserver); mMediator.setOnTabSelectingListener(mLayout::onTabSelecting); verify(mIncognitoReauthController, times(1)) @@ -318,7 +324,6 @@ @Test public void hidesWithAnimation() { initAndAssertAllProperties(); - mMediator.setTabGridDialogController(mTabGridDialogController); mMediator.showTabSwitcherView(true); assertThat( @@ -337,7 +342,6 @@ @Test public void hidesWithoutAnimation() { initAndAssertAllProperties(); - mMediator.setTabGridDialogController(mTabGridDialogController); mMediator.showTabSwitcherView(true); assertThat( @@ -363,13 +367,22 @@ @Test public void beforeHideTabSwitcherView_NullController() { + reset(mTabGridDialogController); + mMediator = new TabSwitcherMediator(mContext, mResetHandler, mModel, mTabModelSelector, + mBrowserControlsStateProvider, mCompositorViewHolder, null, mMessageItemsController, + mPriceWelcomeMessageController, mMultiWindowModeStateDispatcher, + TabListCoordinator.TabListMode.GRID, mIncognitoReauthControllerSupplier, null, + null); + mMediator.initWithNative(mEditorController, null); + mMediator.addTabSwitcherViewObserver(mTabSwitcherViewObserver); + mMediator.setOnTabSelectingListener(mLayout::onTabSelecting); + mMediator.prepareHideTabSwitcherView(); verifyNoMoreInteractions(mTabGridDialogController); } @Test public void beforeHideTabSwitcherView_WithController() { - mMediator.setTabGridDialogController(mTabGridDialogController); mMediator.prepareHideTabSwitcherView(); verify(mTabGridDialogController).hideDialog(eq(false)); } @@ -417,9 +430,6 @@ initAndAssertAllProperties(); mModel.set(TabListContainerProperties.IS_VISIBLE, true); - // Setup dialog reset handler. Default setup is that dialog handler is null. - mMediator.setTabGridDialogController(mTabGridDialogController); - doReturn(true).when(mTabModelFilter).isIncognito(); mTabModelSelectorObserverCaptor.getValue().onTabModelSelected(mTabModel, null); verify(mResetHandler).resetWithTabList(eq(mTabModelFilter), eq(false), eq(false)); @@ -432,6 +442,16 @@ @Test public void resetsAfterNewTabModelSelected_DialogNotEnabled() { + reset(mTabGridDialogController); + mMediator = new TabSwitcherMediator(mContext, mResetHandler, mModel, mTabModelSelector, + mBrowserControlsStateProvider, mCompositorViewHolder, null, mMessageItemsController, + mPriceWelcomeMessageController, mMultiWindowModeStateDispatcher, + TabListCoordinator.TabListMode.GRID, mIncognitoReauthControllerSupplier, null, + null); + mMediator.initWithNative(mEditorController, null); + mMediator.addTabSwitcherViewObserver(mTabSwitcherViewObserver); + mMediator.setOnTabSelectingListener(mLayout::onTabSelecting); + initAndAssertAllProperties(); mModel.set(TabListContainerProperties.IS_VISIBLE, true); @@ -450,9 +470,6 @@ initAndAssertAllProperties(); assertThat(mModel.get(TabListContainerProperties.IS_VISIBLE), equalTo(false)); - // Setup dialog reset handler. Default setup is that dialog handler is null. - mMediator.setTabGridDialogController(mTabGridDialogController); - doReturn(true).when(mTabModelFilter).isIncognito(); mTabModelSelectorObserverCaptor.getValue().onTabModelSelected(mTabModel, null); verify(mResetHandler, never()).resetWithTabList(any(), anyBoolean(), anyBoolean()); @@ -725,7 +742,6 @@ @Test @Features.EnableFeatures({ChromeFeatureList.TAB_GROUPS_ANDROID}) public void openDialogButton_SingleTab() { - mMediator.setTabGridDialogController(mTabGridDialogController); // Mock that tab 1 is a single tab. doReturn(new ArrayList<>(Arrays.asList(mTab1))) .when(mTabModelFilter) @@ -736,7 +752,6 @@ @Test @Features.EnableFeatures({ChromeFeatureList.TAB_GROUPS_ANDROID}) public void openDialogButton_TabGroup_NotEmpty() { - mMediator.setTabGridDialogController(mTabGridDialogController); // Set up a tab group. Tab newTab = prepareTab(TAB4_ID, TAB4_TITLE); List<Tab> tabs = new ArrayList<>(Arrays.asList(mTab1, newTab)); @@ -752,7 +767,6 @@ @Test @Features.EnableFeatures({ChromeFeatureList.TAB_GROUPS_ANDROID}) public void openDialogButton_TabGroup_Empty() { - mMediator.setTabGridDialogController(mTabGridDialogController); // Assume that due to tab model change, current group becomes empty in current model. doReturn(new ArrayList<>()).when(mTabModelFilter).getRelatedTabList(TAB1_ID); @@ -910,14 +924,16 @@ new TabSwitcherMediator(mContext, mResetHandler, mModel, mTabModelSelector, mBrowserControlsStateProvider, mCompositorViewHolder, null, mMessageItemsController, mPriceWelcomeMessageController, mMultiWindowModeStateDispatcher, - TabListCoordinator.TabListMode.GRID, mIncognitoReauthControllerSupplier, null); + TabListCoordinator.TabListMode.GRID, mIncognitoReauthControllerSupplier, null, + mTabGridDialogControllerSupplier); assertEquals(16, mModel.get(TabListContainerProperties.BOTTOM_PADDING)); mModel.set(TabListContainerProperties.BOTTOM_PADDING, 0); new TabSwitcherMediator(mContext, mResetHandler, mModel, mTabModelSelector, mBrowserControlsStateProvider, mCompositorViewHolder, null, mMessageItemsController, mPriceWelcomeMessageController, mMultiWindowModeStateDispatcher, - TabListCoordinator.TabListMode.STRIP, mIncognitoReauthControllerSupplier, null); + TabListCoordinator.TabListMode.STRIP, mIncognitoReauthControllerSupplier, null, + mTabGridDialogControllerSupplier); assertEquals(0, mModel.get(TabListContainerProperties.BOTTOM_PADDING)); } @@ -945,7 +961,6 @@ initAndAssertAllProperties(); Assert.assertFalse(mMediator.shouldInterceptBackPress()); - mMediator.setTabGridDialogController(mTabGridDialogController); doReturn(true).when(mTabGridDialogController).isVisible(); Assert.assertTrue("Should intercept back press if tab grid dialog is visible", mMediator.shouldInterceptBackPress());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/creator/CreatorActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/app/creator/CreatorActivity.java index 7d569b1..9cb8772 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/creator/CreatorActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/creator/CreatorActivity.java
@@ -57,7 +57,6 @@ public void onCreate(Bundle savedInstanceState) { byte[] mWebFeedId = getIntent().getByteArrayExtra(CreatorIntentConstants.CREATOR_WEB_FEED_ID); - String mTitle = getIntent().getStringExtra(CreatorIntentConstants.CREATOR_TITLE); String mUrl = getIntent().getStringExtra(CreatorIntentConstants.CREATOR_URL); int mEntryPoint = getIntent().getIntExtra( CreatorIntentConstants.CREATOR_ENTRY_POINT, SingleWebFeedEntryPoint.OTHER); @@ -72,10 +71,9 @@ super.onCreate(savedInstanceState); IntentRequestTracker intentRequestTracker = IntentRequestTracker.createFromActivity(this); mWindowAndroid = new ActivityWindowAndroid(this, false, intentRequestTracker); - CreatorCoordinator coordinator = - new CreatorCoordinator(this, mWebFeedId, getSnackbarManager(), mWindowAndroid, - mProfile, mTitle, mUrl, this::createWebContents, this::createNewTab, - mTabShareDelegateSupplier, mEntryPoint); + CreatorCoordinator coordinator = new CreatorCoordinator(this, mWebFeedId, + getSnackbarManager(), mWindowAndroid, mProfile, mUrl, this::createWebContents, + this::createNewTab, mTabShareDelegateSupplier, mEntryPoint); mBottomSheetController = coordinator.getBottomSheetController(); ShareDelegate shareDelegate = new ShareDelegateImpl(mBottomSheetController,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/DEPS b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/DEPS index 4d74607..eaf525e8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/DEPS +++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/DEPS
@@ -1,4 +1,4 @@ include_rules = [ "+chrome/browser/android/browserservices", - "+components/digital_asset_links/android/java/src/org/chromium/components/digital_asset_links", + "+components/content_relationship_verification/android/java/src/org/chromium/components/content_relationship_verification", ]
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/PostMessageHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/PostMessageHandler.java index 68e30e5..86a7b7b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/PostMessageHandler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/PostMessageHandler.java
@@ -18,8 +18,8 @@ import org.chromium.base.task.PostTask; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.tab.Tab; -import org.chromium.components.digital_asset_links.OriginVerifier; -import org.chromium.components.digital_asset_links.OriginVerifier.OriginVerificationListener; +import org.chromium.components.content_relationship_verification.OriginVerifier; +import org.chromium.components.content_relationship_verification.OriginVerifier.OriginVerificationListener; import org.chromium.components.embedder_support.util.Origin; import org.chromium.content_public.browser.GlobalRenderFrameHostId; import org.chromium.content_public.browser.LifecycleState;
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 index de055cf..9230aa9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
@@ -22,6 +22,7 @@ import android.view.PointerIcon; import android.view.View; import android.view.ViewGroup; +import android.view.ViewGroup.LayoutParams; import android.view.accessibility.AccessibilityEvent; import android.widget.FrameLayout; @@ -104,9 +105,11 @@ ChromeAccessibilityUtil.Observer, TabObscuringHandler.Observer, ViewGroup.OnHierarchyChangeListener { private static final long SYSTEM_UI_VIEWPORT_UPDATE_DELAY_MS = 500; - private static MutableFlagWithSafeDefault sDeferKeepScreenOnFlag = + private static final MutableFlagWithSafeDefault sDeferKeepScreenOnFlag = new MutableFlagWithSafeDefault( ChromeFeatureList.DEFER_KEEP_SCREEN_ON_DURING_GESTURE, false); + private static final MutableFlagWithSafeDefault sDeferNotifyInMotion = + new MutableFlagWithSafeDefault(ChromeFeatureList.DEFER_NOTIFY_IN_MOTION, false); private Runnable mSetBackgroundRunnable; /** @@ -754,7 +757,9 @@ mInGesture = false; updateViewportSize(); } - updateInMotion(); + if (!sDeferNotifyInMotion.isEnabled()) { + updateInMotion(); + } } private void updateInMotion() { @@ -805,7 +810,16 @@ updateLastActiveTouchEvent(e); updateIsInGesture(e); for (TouchEventObserver o : mTouchEventObservers) o.handleTouchEvent(e); - return super.dispatchTouchEvent(e); + + // This is where input events go from android through native to the web content. This + // process is latency sensitive. Ideally observers that might be expensive, such as + // notifying in motion, should be done after this. + boolean handled = super.dispatchTouchEvent(e); + + if (sDeferNotifyInMotion.isEnabled()) { + updateInMotion(); + } + return handled; } private void updateLastActiveTouchEvent(MotionEvent e) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/RelatedSearchesStamp.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/RelatedSearchesStamp.java index 76848ed..844ef0e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/RelatedSearchesStamp.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/RelatedSearchesStamp.java
@@ -35,7 +35,6 @@ private static final String RELATED_SEARCHES_EXPERIMENT_RECIPE_STAGE = "R"; private static final String RELATED_SEARCHES_NO_EXPERIMENT = "n"; private static final String RELATED_SEARCHES_LANGUAGE_RESTRICTION = "l"; - private static final String RELATED_SEARCHES_DARK_LAUNCH = "d"; private static final String RELATED_SEARCHES_USER_INTERACTION = "U"; private static final String RELATED_SEARCHES_SELECTED_POSITION = "p"; private static final String NO_EXPERIMENT_STAMP = RELATED_SEARCHES_STAMP_VERSION @@ -45,17 +44,6 @@ private boolean mDisableDefaultAllowedLanguagesForTesting; /** - * Verbosity param used to control requested results. - * <ul> - * <li> "d" specifies a dark launch, which means return none </li> - * <li> "v" for verbose </li> - * <li> "x" for extra verbose </li> - * <li> "" for the default </li></ul> - * See also the verbosity entry in about_flags to correlate. - */ - private static final String RELATED_SEARCHES_VERBOSITY_PARAM = "verbosity"; - - /** * Creates a Related Searches Stamp handling instance that works with the given {@code * ContextualSearchPolicy} */ @@ -208,27 +196,13 @@ } /** - * Returns the number of results to request from the server, as a single coded letter, or - * {@code null} if the server should just return the default number of Related Searches. - */ - private String getNumberOfRelatedSearchesToRequestCode() { - if (!ChromeFeatureList.isEnabled(ChromeFeatureList.RELATED_SEARCHES_UI)) { - return RELATED_SEARCHES_DARK_LAUNCH; - } - // Return the Feature param, which could be an empty string if not present. - return ChromeFeatureList.getFieldTrialParamByFeature( - ChromeFeatureList.RELATED_SEARCHES_UI, RELATED_SEARCHES_VERBOSITY_PARAM); - } - - /** * Builds the "stamp" that tracks the processing of Related Searches and describes what was * done at each stage using a shorthand notation. The notation is described in go/rsearches-dd * here: http://doc/1DryD8NAP5LQAo326LnxbqkIDCNfiCOB7ak3gAYaNWAM#bookmark=id.nx7ivu2upqw * <p>The first stage is built here: "1" for schema version one, "R" for the configuration * Recipe which has a character describing how we'll formulate the search. Typically all of * this comes from the Variations config at runtime. We programmatically append an "l" that - * indicates a language restriction (when present), and currently a "d" for "dark launch" so - * the server knows to return normal Contextual Search results for this older client. + * indicates a language restriction (when present). * @param isLanguageRestricted Whether there are any language restrictions needed by the * server. * @return A string that represents and encoded description of the current request processing. @@ -239,10 +213,7 @@ if (TextUtils.isEmpty(experimentConfigStamp)) experimentConfigStamp = NO_EXPERIMENT_STAMP; StringBuilder stampBuilder = new StringBuilder().append(experimentConfigStamp); if (isLanguageRestricted) stampBuilder.append(RELATED_SEARCHES_LANGUAGE_RESTRICTION); - // Add a tag so the server knows this version of the client is doing a dark launch - // and cannot decode Related Searches, unless overridden by a Feature flag. - String resultsToReturnCode = getNumberOfRelatedSearchesToRequestCode(); - if (resultsToReturnCode.length() > 0) stampBuilder.append(resultsToReturnCode); + return stampBuilder.toString(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/ClientManager.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/ClientManager.java index a7c3ce6..4eeedf58 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/ClientManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/ClientManager.java
@@ -36,7 +36,7 @@ import org.chromium.chrome.browser.browserservices.verification.ChromeOriginVerifier; import org.chromium.chrome.browser.browserservices.verification.ChromeOriginVerifierFactory; import org.chromium.chrome.browser.browserservices.verification.ChromeOriginVerifierFactoryImpl; -import org.chromium.components.digital_asset_links.OriginVerifier.OriginVerificationListener; +import org.chromium.components.content_relationship_verification.OriginVerifier.OriginVerificationListener; import org.chromium.components.embedder_support.util.Origin; import org.chromium.components.embedder_support.util.UrlUtilities; import org.chromium.components.installedapp.InstalledAppProviderImpl;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunUtils.java index 8e32e79..1ed0ad4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunUtils.java
@@ -13,6 +13,7 @@ import org.chromium.base.ContextUtils; import org.chromium.base.annotations.NativeMethods; +import org.chromium.chrome.browser.metrics.ChangeMetricsReportingStateCalledFrom; import org.chromium.chrome.browser.metrics.UmaSessionStats; import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; import org.chromium.chrome.browser.preferences.SharedPreferencesManager; @@ -70,7 +71,8 @@ * collect stats. */ static void acceptTermsOfService(boolean allowMetricsAndCrashUploading) { - UmaSessionStats.changeMetricsReportingConsent(allowMetricsAndCrashUploading); + UmaSessionStats.changeMetricsReportingConsent( + allowMetricsAndCrashUploading, ChangeMetricsReportingStateCalledFrom.UI_FIRST_RUN); SharedPreferencesManager.getInstance().writeBoolean( ChromePreferenceKeys.FIRST_RUN_CACHED_TOS_ACCEPTED, true); setEulaAccepted();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/metrics/UmaSessionStats.java b/chrome/android/java/src/org/chromium/chrome/browser/metrics/UmaSessionStats.java index 414ba33..346fecfed 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/metrics/UmaSessionStats.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/metrics/UmaSessionStats.java
@@ -158,13 +158,14 @@ * Updates the metrics services based on a change of consent. This can happen during first-run * flow, and when the user changes their preferences. */ - public static void changeMetricsReportingConsent(boolean consent) { + public static void changeMetricsReportingConsent( + boolean consent, @ChangeMetricsReportingStateCalledFrom int calledFrom) { PrivacyPreferencesManagerImpl privacyManager = PrivacyPreferencesManagerImpl.getInstance(); // Update the metrics reporting preference. privacyManager.setUsageAndCrashReporting(consent); // Perform native changes needed to reflect the new consent value. - UmaSessionStatsJni.get().changeMetricsReportingConsent(consent); + UmaSessionStatsJni.get().changeMetricsReportingConsent(consent, calledFrom); updateMetricsServiceState(); } @@ -271,7 +272,7 @@ @NativeMethods interface Natives { long init(); - void changeMetricsReportingConsent(boolean consent); + void changeMetricsReportingConsent(boolean consent, int calledFrom); void initMetricsAndCrashReportingForTesting(); void unsetMetricsAndCrashReportingForTesting(); void updateMetricsAndCrashReportingForTesting(boolean consent);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/GoogleServicesSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/GoogleServicesSettings.java index 2a772a1..5751848 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/GoogleServicesSettings.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/GoogleServicesSettings.java
@@ -23,6 +23,7 @@ import org.chromium.chrome.browser.contextualsearch.ContextualSearchManager; import org.chromium.chrome.browser.feedback.HelpAndFeedbackLauncherImpl; import org.chromium.chrome.browser.flags.ChromeFeatureList; +import org.chromium.chrome.browser.metrics.ChangeMetricsReportingStateCalledFrom; import org.chromium.chrome.browser.metrics.UmaSessionStats; import org.chromium.chrome.browser.preferences.Pref; import org.chromium.chrome.browser.price_tracking.PriceTrackingFeatures; @@ -229,7 +230,8 @@ } else if (PREF_SEARCH_SUGGESTIONS.equals(key)) { mPrefService.setBoolean(Pref.SEARCH_SUGGEST_ENABLED, (boolean) newValue); } else if (PREF_USAGE_AND_CRASH_REPORTING.equals(key)) { - UmaSessionStats.changeMetricsReportingConsent((boolean) newValue); + UmaSessionStats.changeMetricsReportingConsent( + (boolean) newValue, ChangeMetricsReportingStateCalledFrom.UI_SETTINGS); } else if (PREF_URL_KEYED_ANONYMIZED_DATA.equals(key)) { UnifiedConsentServiceBridge.setUrlKeyedAnonymizedDataCollectionEnabled( Profile.getLastUsedRegularProfile(), (boolean) newValue);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchInstrumentationBase.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchInstrumentationBase.java index f8e57c3..9cc6737e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchInstrumentationBase.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchInstrumentationBase.java
@@ -334,25 +334,24 @@ */ protected static final ImmutableMap<String, Boolean> ENABLE_NONE = ImmutableMap.of( // All false - ChromeFeatureList.RELATED_SEARCHES, false, ChromeFeatureList.RELATED_SEARCHES_UI, false, + ChromeFeatureList.RELATED_SEARCHES, false, ChromeFeatureList.CONTEXTUAL_SEARCH_FORCE_CAPTION, false); /** This is the Related Searches Feature in the MVP configuration. */ private static final ImmutableMap<String, Boolean> ENABLE_RELATED_SEARCHES = ImmutableMap.of( // Related Searches needs these 3: - ChromeFeatureList.RELATED_SEARCHES, true, ChromeFeatureList.RELATED_SEARCHES_UI, true, + ChromeFeatureList.RELATED_SEARCHES, true, ChromeFeatureList.CONTEXTUAL_SEARCH_FORCE_CAPTION, false); /** This is the helper-text Feature. */ - private static final ImmutableMap<String, Boolean> ENABLE_FORCE_CAPTION = ImmutableMap.of( - ChromeFeatureList.RELATED_SEARCHES, false, ChromeFeatureList.RELATED_SEARCHES_UI, false, - // Just this one enabled: - ChromeFeatureList.CONTEXTUAL_SEARCH_FORCE_CAPTION, true); + private static final ImmutableMap<String, Boolean> ENABLE_FORCE_CAPTION = + ImmutableMap.of(ChromeFeatureList.RELATED_SEARCHES, false, + // Just this one enabled: + ChromeFeatureList.CONTEXTUAL_SEARCH_FORCE_CAPTION, true); /** This is the helper-text Feature with Related Searches */ private static final ImmutableMap<String, Boolean> ENABLE_FORCE_CAPTION_WITH_RELATED_SEARCHES = ImmutableMap.of(ChromeFeatureList.RELATED_SEARCHES, true, - ChromeFeatureList.RELATED_SEARCHES_UI, true, ChromeFeatureList.CONTEXTUAL_SEARCH_FORCE_CAPTION, true); //--------------------------------------------------------------------------------------------
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/search_engines/settings/SearchEngineSettingsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/search_engines/settings/SearchEngineSettingsTest.java index bd9177a..31c3057 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/search_engines/settings/SearchEngineSettingsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/search_engines/settings/SearchEngineSettingsTest.java
@@ -22,6 +22,7 @@ import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; import org.chromium.chrome.browser.init.ChromeBrowserInitializer; +import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.search_engines.TemplateUrlServiceFactory; import org.chromium.chrome.browser.settings.MainSettings; import org.chromium.chrome.browser.settings.SettingsActivityTestRule; @@ -57,6 +58,8 @@ .around(mMainSettingsTestRule) .around(mSearchEngineSettingsTestRule); + private TemplateUrlService mTemplateUrlService; + /** * Change search engine and make sure it works correctly. */ @@ -81,18 +84,15 @@ // Simulate selecting the third search engine, ensure that TemplateUrlService is // updated. String keyword2 = pref.setValueForTesting("2"); - TemplateUrlService templateUrlService = TemplateUrlServiceFactory.get(); Assert.assertEquals( - keyword2, templateUrlService.getDefaultSearchEngineTemplateUrl().getKeyword()); + keyword2, mTemplateUrlService.getDefaultSearchEngineTemplateUrl().getKeyword()); // Simulate selecting the fourth search engine. String keyword3 = pref.getKeywordFromIndexForTesting(3); - String url = templateUrlService.getSearchEngineUrlFromTemplateUrl(keyword3); + String url = mTemplateUrlService.getSearchEngineUrlFromTemplateUrl(keyword3); keyword3 = pref.setValueForTesting("3"); - Assert.assertEquals(keyword3, - TemplateUrlServiceFactory.get() - .getDefaultSearchEngineTemplateUrl() - .getKeyword()); + Assert.assertEquals( + keyword3, mTemplateUrlService.getDefaultSearchEngineTemplateUrl().getKeyword()); }); } @@ -105,7 +105,7 @@ () -> { ChromeBrowserInitializer.getInstance().handleSynchronousStartup(); }); ensureTemplateUrlServiceLoaded(); - CriteriaHelper.pollUiThread(() -> TemplateUrlServiceFactory.get().isDefaultSearchManaged()); + CriteriaHelper.pollUiThread(() -> mTemplateUrlService.isDefaultSearchManaged()); mMainSettingsTestRule.startSettingsActivity(); @@ -154,19 +154,17 @@ int index = indexOfFirstHttpSearchEngine(pref); String keyword = pref.setValueForTesting(Integer.toString(index)); - TemplateUrlService templateUrlService = TemplateUrlServiceFactory.get(); Assert.assertEquals( - keyword, templateUrlService.getDefaultSearchEngineTemplateUrl().getKeyword()); + keyword, mTemplateUrlService.getDefaultSearchEngineTemplateUrl().getKeyword()); }); } private int indexOfFirstHttpSearchEngine(SearchEngineSettings pref) { - TemplateUrlService templateUrlService = TemplateUrlServiceFactory.get(); - List<TemplateUrl> urls = templateUrlService.getTemplateUrls(); + List<TemplateUrl> urls = mTemplateUrlService.getTemplateUrls(); int index; for (index = 0; index < urls.size(); ++index) { String keyword = pref.getKeywordFromIndexForTesting(index); - String url = templateUrlService.getSearchEngineUrlFromTemplateUrl(keyword); + String url = mTemplateUrlService.getSearchEngineUrlFromTemplateUrl(keyword); if (url.startsWith("http:")) { return index; } @@ -179,16 +177,20 @@ // Make sure the template_url_service is loaded. final CallbackHelper onTemplateUrlServiceLoadedHelper = new CallbackHelper(); TestThreadUtils.runOnUiThreadBlocking(() -> { - if (TemplateUrlServiceFactory.get().isLoaded()) { + if (mTemplateUrlService == null) { + mTemplateUrlService = TemplateUrlServiceFactory.getForProfile( + Profile.getLastUsedRegularProfile()); + } + if (mTemplateUrlService.isLoaded()) { onTemplateUrlServiceLoadedHelper.notifyCalled(); } else { - TemplateUrlServiceFactory.get().registerLoadListener(new LoadListener() { + mTemplateUrlService.registerLoadListener(new LoadListener() { @Override public void onTemplateUrlServiceLoaded() { onTemplateUrlServiceLoadedHelper.notifyCalled(); } }); - TemplateUrlServiceFactory.get().load(); + mTemplateUrlService.load(); } }); onTemplateUrlServiceLoadedHelper.waitForCallback(0);
diff --git a/chrome/android/junit/DEPS b/chrome/android/junit/DEPS index 38ec2fc..1e7a5c9 100644 --- a/chrome/android/junit/DEPS +++ b/chrome/android/junit/DEPS
@@ -27,7 +27,7 @@ "+components/browser_ui/test/android", "+components/browser_ui/widget/android", "+components/commerce/core", - "+components/digital_asset_links/android/java/src/org/chromium/components/digital_asset_links", + "+components/content_relationship_verification/android/java/src/org/chromium/components/content_relationship_verification", "+components/dom_distiller/core", "+components/feature_engagement/public/android", "+components/offline_items_collection/core/android/java/src",
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/ui/controller/trustedwebactivity/TwaVerifierTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/ui/controller/trustedwebactivity/TwaVerifierTest.java index d5185835..320ad74 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/ui/controller/trustedwebactivity/TwaVerifierTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/ui/controller/trustedwebactivity/TwaVerifierTest.java
@@ -36,7 +36,7 @@ import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher; import org.chromium.chrome.test.util.browser.Features; import org.chromium.chrome.test.util.browser.Features.DisableFeatures; -import org.chromium.components.digital_asset_links.OriginVerifier.OriginVerificationListener; +import org.chromium.components.content_relationship_verification.OriginVerifier.OriginVerificationListener; import org.chromium.components.embedder_support.util.Origin; import org.chromium.components.externalauth.ExternalAuthUtils;
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/CompositorViewHolderUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/CompositorViewHolderUnitTest.java index 6884cad..25081c5 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/CompositorViewHolderUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/CompositorViewHolderUnitTest.java
@@ -4,6 +4,7 @@ package org.chromium.chrome.browser.compositor; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; @@ -46,23 +47,40 @@ import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabObserver; import org.chromium.chrome.browser.toolbar.ControlContainer; import org.chromium.chrome.test.util.browser.Features; +import org.chromium.chrome.test.util.browser.Features.DisableFeatures; import org.chromium.chrome.test.util.browser.Features.EnableFeatures; +import org.chromium.components.browser_ui.widget.TouchEventObserver; import org.chromium.components.embedder_support.view.ContentView; import org.chromium.content_public.browser.WebContents; import org.chromium.ui.KeyboardVisibilityDelegate; import org.chromium.ui.mojom.VirtualKeyboardMode; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + /** * Unit tests for {@link CompositorViewHolder}. */ @RunWith(BaseRobolectricTestRunner.class) public class CompositorViewHolderUnitTest { - @Rule - public TestRule mProcessor = new Features.JUnitProcessor(); - // Since these tests don't depend on the heights being pixels, we can use these as dpi directly. private static final int TOOLBAR_HEIGHT = 56; + private static final long TOUCH_TIME = 0; + private static final MotionEvent MOTION_EVENT_DOWN = + MotionEvent.obtain(TOUCH_TIME, TOUCH_TIME, MotionEvent.ACTION_DOWN, 1, 1, 0); + private static final MotionEvent MOTION_EVENT_UP = + MotionEvent.obtain(TOUCH_TIME, TOUCH_TIME, MotionEvent.ACTION_UP, 1, 1, 0); + + enum EventSource { + IN_MOTION, + TOUCH_EVENT_OBSERVER; + } + + @Rule + public TestRule mProcessor = new Features.JUnitProcessor(); + @Mock private Activity mActivity; @Mock @@ -116,6 +134,7 @@ mContext = new ContextThemeWrapper( ApplicationProvider.getApplicationContext(), R.style.Theme_BrowserUI_DayNight); + mCompositorViewHolder = spy(new CompositorViewHolder(mContext)); mCompositorViewHolder.setCompositorViewForTesting(mCompositorView); mCompositorViewHolder.setBrowserControlsManager(mBrowserControlsManager); @@ -127,6 +146,25 @@ when(mContainerView.getWindowToken()).thenReturn(windowToken); } + private List<EventSource> observeTouchAndMotionEvents() { + List<EventSource> eventSequence = new ArrayList<>(); + mCompositorViewHolder.getInMotionSupplier().addObserver( + (inMotion) -> eventSequence.add(EventSource.IN_MOTION)); + // This touch observer is used as a proxy for when ViewGroup#dispatchTouchEvent is called, + // which is when the touch is propagated to children. + mCompositorViewHolder.addTouchEventObserver(new TouchEventObserver() { + @Override + public boolean shouldInterceptTouchEvent(MotionEvent e) { + return false; + } + @Override + public void handleTouchEvent(MotionEvent e) { + eventSequence.add(EventSource.TOUCH_EVENT_OBSERVER); + } + }); + return eventSequence; + } + // controlsResizeView tests --- // For these tests, we will simulate the scrolls assuming we either completely show or hide (or // scroll until the min-height) the controls and don't leave at in-between positions. The reason @@ -392,27 +430,45 @@ @Test public void testInMotionSupplier() { - long time = System.currentTimeMillis(); - MotionEvent down = MotionEvent.obtain(time, time, MotionEvent.ACTION_DOWN, 1, 1, 0); - MotionEvent up = MotionEvent.obtain(time, time, MotionEvent.ACTION_UP, 1, 1, 0); - - mCompositorViewHolder.dispatchTouchEvent(down); - mCompositorViewHolder.onInterceptTouchEvent(down); + mCompositorViewHolder.dispatchTouchEvent(MOTION_EVENT_DOWN); + mCompositorViewHolder.onInterceptTouchEvent(MOTION_EVENT_DOWN); Assert.assertTrue(mCompositorViewHolder.getInMotionSupplier().get()); - mCompositorViewHolder.dispatchTouchEvent(up); - mCompositorViewHolder.onInterceptTouchEvent(up); + mCompositorViewHolder.dispatchTouchEvent(MOTION_EVENT_UP); + mCompositorViewHolder.onInterceptTouchEvent(MOTION_EVENT_UP); Assert.assertFalse(mCompositorViewHolder.getInMotionSupplier().get()); - mCompositorViewHolder.dispatchTouchEvent(down); - mCompositorViewHolder.onInterceptTouchEvent(down); + mCompositorViewHolder.dispatchTouchEvent(MOTION_EVENT_DOWN); + mCompositorViewHolder.onInterceptTouchEvent(MOTION_EVENT_DOWN); Assert.assertTrue(mCompositorViewHolder.getInMotionSupplier().get()); // Simulate a child handling a scroll, where they call requestDisallowInterceptTouchEvent // and then we no longer get onInterceptTouchEvent. The dispatchTouchEvent alone should // still cause our motion status to correctly update. mCompositorViewHolder.requestDisallowInterceptTouchEvent(true); - mCompositorViewHolder.dispatchTouchEvent(up); + mCompositorViewHolder.dispatchTouchEvent(MOTION_EVENT_UP); Assert.assertFalse(mCompositorViewHolder.getInMotionSupplier().get()); } + + @Test + @DisableFeatures(ChromeFeatureList.DEFER_NOTIFY_IN_MOTION) + public void testInMotionOrdering_NoDefer() { + // With the 'defer in motion' experiment disabled, touch events are routed to android UI + // before being sent to native/web content. + List<EventSource> eventSequence = observeTouchAndMotionEvents(); + mCompositorViewHolder.dispatchTouchEvent(MOTION_EVENT_DOWN); + assertEquals(Arrays.asList(EventSource.IN_MOTION, EventSource.TOUCH_EVENT_OBSERVER), + eventSequence); + } + + @Test + @EnableFeatures(ChromeFeatureList.DEFER_NOTIFY_IN_MOTION) + public void testInMotionOrdering_WithDefer() { + // With the 'defer in motion' experiment enabled, touch events are routed to android UI + // after being sent to native/web content. + List<EventSource> eventSequence = observeTouchAndMotionEvents(); + mCompositorViewHolder.dispatchTouchEvent(MOTION_EVENT_DOWN); + assertEquals(Arrays.asList(EventSource.TOUCH_EVENT_OBSERVER, EventSource.IN_MOTION), + eventSequence); + } }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/contextualsearch/RelatedSearchesStampTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/contextualsearch/RelatedSearchesStampTest.java index 09e4bea..c2af0d7 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/contextualsearch/RelatedSearchesStampTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/contextualsearch/RelatedSearchesStampTest.java
@@ -15,8 +15,6 @@ import android.net.Uri; import android.text.TextUtils; -import androidx.annotation.Nullable; - import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -51,10 +49,6 @@ private static final String RELATED_SEARCHES_DARK_LAUNCH = "d"; private static final String RELATED_SEARCHES_USER_INTERACTION = "U"; private static final String RELATED_SEARCHES_SELECTED_POSITION = "p"; - private static final String RELATED_SEARCHES_VERBOSITY_PARAM = "verbosity"; - private static final String RELATED_SEARCHES_VERBOSITY_DEFAULT = ""; - private static final String RELATED_SEARCHES_VERBOSITY_VERBOSE = "v"; - private static final String RELATED_SEARCHES_VERBOSITY_EXTREME = "x"; /** * The stamps to use for various experiment configurations. Note that users still may need @@ -87,7 +81,6 @@ * Values to return from Shadows. * These must be static because the original and shadow methods are static. */ - private static String sRelatedSearchesVerbosity; private static String sRelatedSearchesLanguageAllowlist; // These need to be Boolean instead of boolean so they can be static. private static Boolean sRelatedSearchesNeedsUrl; @@ -105,14 +98,6 @@ */ @Implements(ChromeFeatureList.class) static class ShadowChromeFeatureList { - /** @see {@link #setVerbosity} for how to define a return value for this function. */ - @Implementation - protected static String getFieldTrialParamByFeature(String featureName, String paramName) { - assertThat(featureName, is(ChromeFeatureList.RELATED_SEARCHES_UI)); - assertThat(paramName, is(RELATED_SEARCHES_VERBOSITY_PARAM)); - return sRelatedSearchesVerbosity; - } - @Implementation protected static boolean getFieldTrialParamByFeatureAsBoolean( String featureName, String paramName, boolean defaultValue) { @@ -187,18 +172,12 @@ /** Resets all of the static return values for all our shadow classes. */ private void resetShadows() { - sRelatedSearchesVerbosity = ""; sRelatedSearchesLanguageAllowlist = ""; sRelatedSearchesNeedsUrl = null; sRelatedSearchesNeedsContent = null; sRelatedSearchesExperimentConfigurationStamp = null; } - /** Sets the verbosity character that our shadow should return (normally set in the config). */ - private void setVerbosity(String verbosityCharacter) { - sRelatedSearchesVerbosity = verbosityCharacter; - } - /** Sets whether the user has allowed sending content (has done the opt-in). */ private void setCanSendContent(boolean canSend) { mPolicy.overrideDecidedStateForTesting(canSend); @@ -259,15 +238,6 @@ } /** - * Sets a standard config setup for a particular Related Searches experiment arm. - * @param stampFromConfig The base stamp just as we expect it to be set in the experiment - * config. - */ - private void setStandardExperimentConfiguration(String stampFromConfig) { - setStandardExperimentConfiguration(stampFromConfig, RELATED_SEARCHES_VERBOSITY_DEFAULT); - } - - /** * Sets a standard config setup for the default Related Searches launch configuration. */ private void setStandardDefaultLaunchConfiguration() { @@ -280,7 +250,7 @@ * config. */ private void setStandardLaunchConfiguration(String stampFromConfig) { - setStandardExperimentConfiguration(stampFromConfig, RELATED_SEARCHES_VERBOSITY_DEFAULT); + setStandardExperimentConfiguration(stampFromConfig); clearLanguageAllowlist(); } @@ -288,14 +258,11 @@ * Sets a standard config setup for a particular Related Searches experiment arm. * @param stampFromConfig The base stamp just as we expect it to be set in the experiment * config. - * @param verbosity The verbosity param as we expect it to be set in the experiment config. */ - private void setStandardExperimentConfiguration( - String stampFromConfig, @Nullable String verbosity) { + private void setStandardExperimentConfiguration(String stampFromConfig) { setStandardExperimentRequirements(); setCanSendUrl(true); setCanSendContent(true); - setVerbosity(verbosity); setRelatedSearchesExperimentConfigurationStamp(stampFromConfig); } @@ -469,38 +436,6 @@ @Test @Feature({"RelatedSearches", "RelatedSearchesStamp"}) - public void testGetVerbosityVerbose() { - setStandardDefaultLaunchConfiguration(); - setVerbosity(RELATED_SEARCHES_VERBOSITY_VERBOSE); - assertThat("The verbose variant is not working as expected for the default launch " - + "configuration!", - mStamp.getRelatedSearchesStamp(GERMAN), - is(EXPECTED_DEFAULT_STAMP + RELATED_SEARCHES_VERBOSITY_VERBOSE)); - } - - @Test - @Feature({"RelatedSearches", "RelatedSearchesStamp"}) - public void testGetVerbosityExtreme() { - setStandardDefaultLaunchConfiguration(); - setVerbosity(RELATED_SEARCHES_VERBOSITY_EXTREME); - assertThat("The verbose-extreme variant is not working as expected for the default launch " - + "configuration!", - mStamp.getRelatedSearchesStamp(GERMAN), - is(EXPECTED_DEFAULT_STAMP + RELATED_SEARCHES_VERBOSITY_EXTREME)); - } - - @Test - @Feature({"RelatedSearches", "RelatedSearchesStamp"}) - public void testGetVerbosityDefault() { - setStandardDefaultLaunchConfiguration(); - setVerbosity(""); - assertThat("The default setting for verbosity is not working as expected for the default " - + "launch configuration!", - mStamp.getRelatedSearchesStamp(GERMAN), is(EXPECTED_DEFAULT_STAMP)); - } - - @Test - @Feature({"RelatedSearches", "RelatedSearchesStamp"}) public void testUpdateUriForSelectedPosition() { setStandardDefaultLaunchConfiguration(); Uri updatedUri = RelatedSearchesStamp.updateUriForSuggestionPosition(SAMPLE_URI, 3);
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/ClientManagerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/ClientManagerTest.java index 87020d8c..2098ca3 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/ClientManagerTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/ClientManagerTest.java
@@ -48,9 +48,9 @@ import org.chromium.chrome.browser.browserservices.verification.ChromeOriginVerifierJni; import org.chromium.chrome.browser.document.ChromeLauncherActivity; import org.chromium.chrome.browser.profiles.Profile; -import org.chromium.components.digital_asset_links.OriginVerifier; -import org.chromium.components.digital_asset_links.OriginVerifierJni; -import org.chromium.components.digital_asset_links.OriginVerifierUnitTestSupport; +import org.chromium.components.content_relationship_verification.OriginVerifier; +import org.chromium.components.content_relationship_verification.OriginVerifierJni; +import org.chromium.components.content_relationship_verification.OriginVerifierUnitTestSupport; import org.chromium.components.embedder_support.util.Origin; import org.chromium.components.embedder_support.util.ShadowUrlUtilities;
diff --git a/chrome/android/profiles/arm.newest.txt b/chrome/android/profiles/arm.newest.txt index 35b5b20..c43f3bfd 100644 --- a/chrome/android/profiles/arm.newest.txt +++ b/chrome/android/profiles/arm.newest.txt
@@ -1 +1 @@ -chromeos-chrome-arm-113.0.5619.0_rc-r1-merged.afdo.bz2 +chromeos-chrome-arm-113.0.5620.0_rc-r1-merged.afdo.bz2
diff --git a/chrome/app/chrome_main_delegate.cc b/chrome/app/chrome_main_delegate.cc index 441c319..c9acdb09 100644 --- a/chrome/app/chrome_main_delegate.cc +++ b/chrome/app/chrome_main_delegate.cc
@@ -1412,7 +1412,7 @@ #if BUILDFLAG(IS_WIN) // TODO(zturner): Throbber icons and cursors are still stored in chrome.dll, // this can be killed once those are merged into resources.pak. See - // GlassBrowserFrameView::InitThrobberIcons(), https://crbug.com/368327 and + // BrowserFrameViewWin::InitThrobberIcons(), https://crbug.com/368327 and // https://crbug.com/1178117. ui::SetResourcesDataDLL(_AtlBaseModule.GetResourceInstance()); #endif
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 28d5730..68c31f6 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -2096,6 +2096,7 @@ "//components/component_updater/installer_policies", "//components/consent_auditor", "//components/content_capture/browser", + "//components/content_relationship_verification", "//components/content_settings/browser", "//components/content_settings/common:mojom", "//components/content_settings/core/browser", @@ -2109,7 +2110,6 @@ "//components/custom_handlers", "//components/device_event_log", "//components/device_reauth", - "//components/digital_asset_links", "//components/dom_distiller/content/browser", "//components/dom_distiller/content/common/mojom", "//components/domain_reliability", @@ -5043,6 +5043,7 @@ "//ash/webui/personalization_app/search:mojo_bindings", "//ash/webui/print_management", "//ash/webui/projector_app", + "//ash/webui/projector_app/mojom:annotator_mojo_bindings", "//ash/webui/scanning", "//ash/webui/scanning/mojom", "//ash/webui/shimless_rma", @@ -5368,6 +5369,8 @@ "lacros/launcher_search/search_controller_lacros.h", "lacros/metrics_reporting_observer.cc", "lacros/metrics_reporting_observer.h", + "lacros/multitask_menu_nudge_delegate_lacros.cc", + "lacros/multitask_menu_nudge_delegate_lacros.h", "lacros/net/lacros_extension_proxy_tracker.cc", "lacros/net/lacros_extension_proxy_tracker.h", "lacros/net/network_change_manager_bridge.cc",
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS index 16d4a533..a0785aa 100644 --- a/chrome/browser/DEPS +++ b/chrome/browser/DEPS
@@ -117,7 +117,7 @@ "+components/device_event_log", "+components/device_signals/core/browser", "+components/device_signals/core/common", - "+components/digital_asset_links", + "+components/content_relationship_verification", "+components/digital_goods", "+components/domain_reliability", "+components/dom_distiller/content/browser",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index aedc919b..a46f136c 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -1956,12 +1956,6 @@ {"from URL", &kRelatedSearchesUrl, 1, nullptr}, {"from content", &kRelatedSearchesContent, 1, nullptr}, }; -const FeatureEntry::FeatureParam kRelatedSearchesUiVerbose = {"verbosity", "v"}; -const FeatureEntry::FeatureParam kRelatedSearchesUiExtreme = {"verbosity", "x"}; -const FeatureEntry::FeatureVariation kRelatedSearchesUiVariations[] = { - {"verbose", &kRelatedSearchesUiVerbose, 1, nullptr}, - {"extreme", &kRelatedSearchesUiExtreme, 1, nullptr}, -}; const FeatureEntry::FeatureParam kContextualSearchSuppressShortViewWith300Dp[] = {{"contextual_search_minimum_page_height_dp", "300"}}; @@ -3340,11 +3334,6 @@ FEATURE_WITH_PARAMS_VALUE_TYPE(chrome::android::kRelatedSearches, kRelatedSearchesVariations, "RelatedSearches")}, - {"related-searches-ui", flag_descriptions::kRelatedSearchesUiName, - flag_descriptions::kRelatedSearchesUiDescription, kOsAndroid, - FEATURE_WITH_PARAMS_VALUE_TYPE(chrome::android::kRelatedSearchesUi, - kRelatedSearchesUiVariations, - "RelatedSearchesUi")}, #endif // BUILDFLAG(IS_ANDROID) {"show-autofill-type-predictions", flag_descriptions::kShowAutofillTypePredictionsName, @@ -3503,6 +3492,10 @@ flag_descriptions::kCaptureModeDemoToolsName, flag_descriptions::kCaptureModeDemoToolsDescription, kOsCrOS, FEATURE_VALUE_TYPE(ash::features::kCaptureModeDemoTools)}, + {"ash-capture-mode-gif-recording", + flag_descriptions::kCaptureModeGifRecordingName, + flag_descriptions::kCaptureModeGifRecordingDescription, kOsCrOS, + FEATURE_VALUE_TYPE(ash::features::kGifRecording)}, {"ash-overview-button", flag_descriptions::kOverviewButtonName, flag_descriptions::kOverviewButtonDescription, kOsCrOS, FEATURE_VALUE_TYPE(ash::features::kOverviewButton)}, @@ -6969,12 +6962,6 @@ kOsAll, FEATURE_VALUE_TYPE(features::kEnableBackForwardCacheForScreenReader)}, -#if !BUILDFLAG(IS_ANDROID) - {"closed-tab-cache", flag_descriptions::kClosedTabCacheName, - flag_descriptions::kClosedTabCacheDescription, kOsDesktop, - FEATURE_VALUE_TYPE(features::kClosedTabCache)}, -#endif // !BUILDFLAG(IS_ANDROID) - {"windows-scrolling-personality", flag_descriptions::kWindowsScrollingPersonalityName, flag_descriptions::kWindowsScrollingPersonalityDescription, kOsAll, @@ -7128,10 +7115,6 @@ flag_descriptions::kFullUserAgentDescription, kOsDesktop | kOsAndroid, FEATURE_VALUE_TYPE(blink::features::kFullUserAgent)}, - {"reduce-user-agent", flag_descriptions::kReduceUserAgentName, - flag_descriptions::kReduceUserAgentDescription, kOsDesktop | kOsAndroid, - FEATURE_VALUE_TYPE(blink::features::kReduceUserAgent)}, - #if BUILDFLAG(IS_WIN) {"run-video-capture-service-in-browser", flag_descriptions::kRunVideoCaptureServiceInBrowserProcessName, @@ -8504,13 +8487,6 @@ FEATURE_VALUE_TYPE(blink::features::kOriginAgentClusterDefaultEnabled)}, #if !BUILDFLAG(IS_ANDROID) - {"enable-user-cloud-signin-restriction-policy", - flag_descriptions::kEnableUserCloudSigninRestrictionPolicyName, - flag_descriptions::kEnableUserCloudSigninRestrictionPolicyDescription, - kOsDesktop, - FEATURE_VALUE_TYPE( - policy::features::kEnableUserCloudSigninRestrictionPolicyFetcher)}, - {"enable-code-based-rbd", flag_descriptions::kCodeBasedRBDName, flag_descriptions::kCodeBasedRBDDescription, kOsDesktop, FEATURE_WITH_PARAMS_VALUE_TYPE(commerce::kCodeBasedRBD, @@ -8577,16 +8553,6 @@ flag_descriptions::kReduceAcceptLanguageDescription, kOsAll, FEATURE_VALUE_TYPE(network::features::kReduceAcceptLanguage)}, - {"reduce-user-agent-minor-version", - flag_descriptions::kReduceUserAgentMinorVersionName, - flag_descriptions::kReduceUserAgentMinorVersionDescription, kOsAll, - FEATURE_VALUE_TYPE(blink::features::kReduceUserAgentMinorVersion)}, - - {"reduce-user-agent-platform-oscpu", - flag_descriptions::kReduceUserAgentPlatformOsCpuName, - flag_descriptions::kReduceUserAgentPlatformOsCpuDescription, kOsAll, - FEATURE_VALUE_TYPE(blink::features::kReduceUserAgentPlatformOsCpu)}, - #if BUILDFLAG(IS_ANDROID) {"reduce-user-agent-android-version-device-model", flag_descriptions::kReduceUserAgentAndroidVersionDeviceModelName, @@ -8671,6 +8637,10 @@ flag_descriptions::kAmbientModeThrottleAnimationName, flag_descriptions::kAmbientModeThrottleAnimationDescription, kOsCrOS, FEATURE_VALUE_TYPE(ash::features::kAmbientModeThrottleAnimation)}, + {"ambient-mode-managed-screensaver-enabled", + flag_descriptions::kAmbientModeManagedScreensaverName, + flag_descriptions::kAmbientModeManagedScreensaverDescription, kOsCrOS, + FEATURE_VALUE_TYPE(ash::features::kAmbientModeManagedScreensaver)}, {"enable-touchpads-in-diagnostics-app", flag_descriptions::kEnableTouchpadsInDiagnosticsAppName, flag_descriptions::kEnableTouchpadsInDiagnosticsAppDescription, kOsCrOS, @@ -9148,7 +9118,7 @@ {"chrome-root-store-enabled", flag_descriptions::kChromeRootStoreEnabledName, flag_descriptions::kChromeRootStoreEnabledDescription, - kOsWin | kOsMac | kOsAndroid, + kOsWin | kOsMac | kOsAndroid | kOsLinux | kOsCrOS | kOsLacros, FEATURE_VALUE_TYPE(net::features::kChromeRootStoreUsed)}, #endif // BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
diff --git a/chrome/browser/android/browserservices/verification/BUILD.gn b/chrome/browser/android/browserservices/verification/BUILD.gn index 3a061cc..ae59c48 100644 --- a/chrome/browser/android/browserservices/verification/BUILD.gn +++ b/chrome/browser/android/browserservices/verification/BUILD.gn
@@ -19,8 +19,8 @@ "//chrome/browser/flags:java", "//chrome/browser/preferences:java", "//chrome/browser/profiles/android:java", - "//components/digital_asset_links:java", - "//components/digital_asset_links/android:java", + "//components/content_relationship_verification:java", + "//components/content_relationship_verification/android:java", "//components/embedder_support/android:util_java", "//components/externalauth/android:java", "//content/public/android:content_java", @@ -46,7 +46,7 @@ "//base:base_java_test_support", "//chrome/browser/flags:java", "//chrome/test/android:chrome_java_integration_test_support", - "//components/digital_asset_links/android:java", + "//components/content_relationship_verification/android:java", "//components/embedder_support/android:util_java", "//components/externalauth/android:java", "//content/public/android:content_java", @@ -65,9 +65,9 @@ "//base:base_java_test_support", "//base:base_junit_test_support", "//chrome/browser/profiles/android:java", - "//components/digital_asset_links:java", - "//components/digital_asset_links/android:java", - "//components/digital_asset_links/android:junit_test_support", + "//components/content_relationship_verification:java", + "//components/content_relationship_verification/android:java", + "//components/content_relationship_verification/android:junit_test_support", "//components/embedder_support/android:util_java", "//content/public/android:content_java", "//content/public/test/android:content_java_test_support",
diff --git a/chrome/browser/android/browserservices/verification/DEPS b/chrome/browser/android/browserservices/verification/DEPS index 5fe5af7..0fff097 100644 --- a/chrome/browser/android/browserservices/verification/DEPS +++ b/chrome/browser/android/browserservices/verification/DEPS
@@ -5,7 +5,7 @@ "+chrome/browser/android/browserservices/metrics", "+chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences", "+chrome/browser/profiles/android/java/src/org/chromium/chrome/browser/profiles", - "+components/digital_asset_links/android/java/src/org/chromium/components/digital_asset_links", + "+components/content_relationship_verification/android/java/src/org/chromium/components/content_relationship_verification", "+components/embedder_support/android/java/src/org/chromium/components/embedder_support/util", "+components/externalauth/android/java/src/org/chromium/components/externalauth", "+content/public/android/java/src/org/chromium/content_public/browser",
diff --git a/chrome/browser/android/browserservices/verification/java/src/org/chromium/chrome/browser/browserservices/verification/ChromeOriginVerifier.java b/chrome/browser/android/browserservices/verification/java/src/org/chromium/chrome/browser/browserservices/verification/ChromeOriginVerifier.java index 2fd8400..ce6b08e6 100644 --- a/chrome/browser/android/browserservices/verification/java/src/org/chromium/chrome/browser/browserservices/verification/ChromeOriginVerifier.java +++ b/chrome/browser/android/browserservices/verification/java/src/org/chromium/chrome/browser/browserservices/verification/ChromeOriginVerifier.java
@@ -28,8 +28,8 @@ import org.chromium.chrome.browser.browserservices.metrics.OriginVerifierMetricsRecorder.VerificationResult; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.profiles.Profile; -import org.chromium.components.digital_asset_links.OriginVerifier; -import org.chromium.components.digital_asset_links.Relationship; +import org.chromium.components.content_relationship_verification.OriginVerifier; +import org.chromium.components.content_relationship_verification.Relationship; import org.chromium.components.embedder_support.util.Origin; import org.chromium.components.externalauth.ExternalAuthUtils; import org.chromium.content_public.browser.BrowserContextHandle;
diff --git a/chrome/browser/android/browserservices/verification/java/src/org/chromium/chrome/browser/browserservices/verification/ChromeOriginVerifierJunitTest.java b/chrome/browser/android/browserservices/verification/java/src/org/chromium/chrome/browser/browserservices/verification/ChromeOriginVerifierJunitTest.java index e6638055..8844b87 100644 --- a/chrome/browser/android/browserservices/verification/java/src/org/chromium/chrome/browser/browserservices/verification/ChromeOriginVerifierJunitTest.java +++ b/chrome/browser/android/browserservices/verification/java/src/org/chromium/chrome/browser/browserservices/verification/ChromeOriginVerifierJunitTest.java
@@ -27,11 +27,11 @@ import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.JniMocker; import org.chromium.chrome.browser.profiles.Profile; -import org.chromium.components.digital_asset_links.OriginVerifier; -import org.chromium.components.digital_asset_links.OriginVerifier.OriginVerificationListener; -import org.chromium.components.digital_asset_links.OriginVerifierJni; -import org.chromium.components.digital_asset_links.OriginVerifierUnitTestSupport; -import org.chromium.components.digital_asset_links.RelationshipCheckResult; +import org.chromium.components.content_relationship_verification.OriginVerifier; +import org.chromium.components.content_relationship_verification.OriginVerifier.OriginVerificationListener; +import org.chromium.components.content_relationship_verification.OriginVerifierJni; +import org.chromium.components.content_relationship_verification.OriginVerifierUnitTestSupport; +import org.chromium.components.content_relationship_verification.RelationshipCheckResult; import org.chromium.components.embedder_support.util.Origin; import org.chromium.content_public.browser.test.util.TestThreadUtils;
diff --git a/chrome/browser/android/browserservices/verification/java/src/org/chromium/chrome/browser/browserservices/verification/ChromeOriginVerifierTest.java b/chrome/browser/android/browserservices/verification/java/src/org/chromium/chrome/browser/browserservices/verification/ChromeOriginVerifierTest.java index cedd152..60ec230 100644 --- a/chrome/browser/android/browserservices/verification/java/src/org/chromium/chrome/browser/browserservices/verification/ChromeOriginVerifierTest.java +++ b/chrome/browser/android/browserservices/verification/java/src/org/chromium/chrome/browser/browserservices/verification/ChromeOriginVerifierTest.java
@@ -22,7 +22,7 @@ import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.ChromeTabbedActivityTestRule; -import org.chromium.components.digital_asset_links.OriginVerifier.OriginVerificationListener; +import org.chromium.components.content_relationship_verification.OriginVerifier.OriginVerificationListener; import org.chromium.components.embedder_support.util.Origin; import org.chromium.components.externalauth.ExternalAuthUtils; import org.chromium.content_public.browser.UiThreadTaskTraits;
diff --git a/chrome/browser/android/browserservices/verification/java/src/org/chromium/chrome/browser/browserservices/verification/ChromeVerificationResultStore.java b/chrome/browser/android/browserservices/verification/java/src/org/chromium/chrome/browser/browserservices/verification/ChromeVerificationResultStore.java index 13bd1cf3..21fdf47 100644 --- a/chrome/browser/android/browserservices/verification/java/src/org/chromium/chrome/browser/browserservices/verification/ChromeVerificationResultStore.java +++ b/chrome/browser/android/browserservices/verification/java/src/org/chromium/chrome/browser/browserservices/verification/ChromeVerificationResultStore.java
@@ -9,7 +9,7 @@ import org.chromium.base.StrictModeContext; import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; import org.chromium.chrome.browser.preferences.SharedPreferencesManager; -import org.chromium.components.digital_asset_links.VerificationResultStore; +import org.chromium.components.content_relationship_verification.VerificationResultStore; import java.util.HashSet; import java.util.Set;
diff --git a/chrome/browser/android/customtabs/chrome_origin_verifier.cc b/chrome/browser/android/customtabs/chrome_origin_verifier.cc index a723ac9..174efab 100644 --- a/chrome/browser/android/customtabs/chrome_origin_verifier.cc +++ b/chrome/browser/android/customtabs/chrome_origin_verifier.cc
@@ -7,7 +7,7 @@ #include "base/android/jni_android.h" #include "chrome/browser/android/browserservices/verification/jni_headers/ChromeOriginVerifier_jni.h" #include "chrome/browser/browser_process.h" -#include "components/digital_asset_links/origin_verifier.h" +#include "components/content_relationship_verification/origin_verifier.h" namespace customtabs {
diff --git a/chrome/browser/android/metrics/uma_session_stats.cc b/chrome/browser/android/metrics/uma_session_stats.cc index 388b2527..30ba52a 100644 --- a/chrome/browser/android/metrics/uma_session_stats.cc +++ b/chrome/browser/android/metrics/uma_session_stats.cc
@@ -206,8 +206,10 @@ // the Java side. static void JNI_UmaSessionStats_ChangeMetricsReportingConsent( JNIEnv*, - jboolean consent) { - UpdateMetricsPrefsOnPermissionChange(consent); + jboolean consent, + jint called_from) { + UpdateMetricsPrefsOnPermissionChange( + consent, static_cast<ChangeMetricsReportingStateCalledFrom>(called_from)); // This function ensures a consent file in the data directory is either // created, or deleted, depending on consent. Starting up metrics services
diff --git a/chrome/browser/ash/browser_context_keyed_service_factories.cc b/chrome/browser/ash/browser_context_keyed_service_factories.cc index 62e0ad03..aee7b7c7 100644 --- a/chrome/browser/ash/browser_context_keyed_service_factories.cc +++ b/chrome/browser/ash/browser_context_keyed_service_factories.cc
@@ -94,6 +94,7 @@ #include "chrome/browser/speech/cros_speech_recognition_service_factory.h" #include "chrome/browser/speech/extension_api/tts_engine_extension_observer_chromeos.h" #include "chrome/browser/ui/ash/calendar/calendar_keyed_service_factory.h" +#include "chrome/browser/ui/ash/glanceables/glanceables_keyed_service_factory.h" #include "chrome/browser/ui/ash/global_media_controls/cast_media_notification_producer_keyed_service_factory.h" #include "chrome/browser/ui/ash/holding_space/holding_space_keyed_service_factory.h" #include "chrome/browser/ui/webui/settings/ash/os_settings_manager_factory.h" @@ -206,6 +207,7 @@ SyncedPrintersManagerFactory::GetInstance(); tether::TetherServiceFactory::GetInstance(); TtsEngineExtensionObserverChromeOS::EnsureFactoryBuilt(); + GlanceablesKeyedServiceFactory::GetInstance(); } } // namespace ash
diff --git a/chrome/browser/ash/crosapi/browser_action.cc b/chrome/browser/ash/crosapi/browser_action.cc index 40f05f7b..92cb4b6e 100644 --- a/chrome/browser/ash/crosapi/browser_action.cc +++ b/chrome/browser/ash/crosapi/browser_action.cc
@@ -10,6 +10,7 @@ #include "chrome/browser/ash/crosapi/desk_template_ash.h" #include "chrome/browser/prefs/incognito_mode_prefs.h" #include "chrome/browser/profiles/profile_manager.h" +#include "chrome/browser/profiles/profiles_state.h" #include "components/user_manager/user_manager.h" namespace crosapi { @@ -393,16 +394,18 @@ } // No window will be opened in the following circumstances: -// 1. Lacros-chrome is initialized in the web Kiosk session +// 1. Lacros-chrome is initialized in the Kiosk session // 2. Full restore is responsible for restoring/launching Lacros. // static std::unique_ptr<BrowserAction> BrowserAction::GetActionForSessionStart() { - if (user_manager::UserManager::Get()->IsLoggedInAsGuest()) + if (user_manager::UserManager::Get()->IsLoggedInAsGuest()) { return std::make_unique<NewWindowAction>( /*incognito=*/false, /*should_trigger_session_restore=*/false, -1); - if (user_manager::UserManager::Get()->IsLoggedInAsWebKioskApp() || - ash::full_restore::MaybeCreateFullRestoreServiceForLacros()) + } + if (profiles::IsKioskSession() || + ash::full_restore::MaybeCreateFullRestoreServiceForLacros()) { return std::make_unique<NoOpAction>(); + } return std::make_unique<NewWindowAction>( /*incognito=*/false, /*should_trigger_session_restore=*/true, -1); }
diff --git a/chrome/browser/ash/crosapi/browser_data_migrator.cc b/chrome/browser/ash/crosapi/browser_data_migrator.cc index 6720dc6..ff35b74 100644 --- a/chrome/browser/ash/crosapi/browser_data_migrator.cc +++ b/chrome/browser/ash/crosapi/browser_data_migrator.cc
@@ -262,16 +262,6 @@ return false; } - // Profile migration should only be run for LacrosOnly i.e. no migration - // should run if Ash is still used as a browser. - if (IsAshWebBrowserEnabledForMigration(user, policy_init_state)) { - // TODO(crbug.com/1277848): Once `BrowserDataMigrator` stabilises, remove - // this log message. - LOG(WARNING) - << "Profile migration is only avaiable if Lacros is the only browser."; - return false; - } - int attempts = GetMigrationAttemptCountForUser(local_state, user_id_hash); // TODO(crbug.com/1178702): Once BrowserDataMigrator stabilises, reduce the // log level to VLOG(1).
diff --git a/chrome/browser/ash/crosapi/browser_data_migrator_browsertest.cc b/chrome/browser/ash/crosapi/browser_data_migrator_browsertest.cc index 29bf6a0..722e12c4 100644 --- a/chrome/browser/ash/crosapi/browser_data_migrator_browsertest.cc +++ b/chrome/browser/ash/crosapi/browser_data_migrator_browsertest.cc
@@ -122,6 +122,66 @@ LoginManagerMixin login_manager_mixin_{&mixin_host_, {regular_user_}}; }; +class BrowserDataMigratorCopyMigrateOnSignIn + : public BrowserDataMigratorOnSignIn { + public: + BrowserDataMigratorCopyMigrateOnSignIn() = default; + BrowserDataMigratorCopyMigrateOnSignIn( + BrowserDataMigratorCopyMigrateOnSignIn&) = delete; + BrowserDataMigratorCopyMigrateOnSignIn& operator=( + BrowserDataMigratorCopyMigrateOnSignIn&) = delete; + ~BrowserDataMigratorCopyMigrateOnSignIn() override = default; + + void SetUp() override { + feature_list_.InitWithFeatures({ash::features::kLacrosSupport}, {}); + + BrowserDataMigratorOnSignIn::SetUp(); + } + + private: + base::test::ScopedFeatureList feature_list_; +}; + +// Check that migration is triggered from signin flow if Lacros is enabled. +IN_PROC_BROWSER_TEST_F(BrowserDataMigratorCopyMigrateOnSignIn, + MigrateOnSignIn) { + base::RunLoop run_loop; + ScopedRestartAttemptForTesting scoped_restart_attempt( + base::BindLambdaForTesting([&]() { run_loop.Quit(); })); + ASSERT_TRUE(LoginAsExistingRegularUser()); + run_loop.Run(); + EXPECT_TRUE( + FakeSessionManagerClient::Get()->request_browser_data_migration_called()); + // Migration should be triggered in copy mode and not move mode. + EXPECT_TRUE(FakeSessionManagerClient::Get() + ->request_browser_data_migration_mode_called()); + EXPECT_EQ(FakeSessionManagerClient::Get() + ->request_browser_data_migration_mode_value(), + "copy"); +} + +// Check that migration marked as completed for a new user and thus migration is +// not triggered from signin flow. +IN_PROC_BROWSER_TEST_F(BrowserDataMigratorCopyMigrateOnSignIn, + SkipMigrateOnSignInForNewUser) { + ash::test::ProfilePreparedWaiter profile_prepared(regular_user_.account_id); + ASSERT_TRUE(LoginAsRegularUser()); + // Note that `ProfilePreparedWaiter` waits for + // `ExistingUserController::OnProfilePrepared()` to be called and this is + // called after `UserSessionManager::InitializeUserSession()` is called, which + // leads to `BrowserDataMigratorImpl::MaybeRestartToMigrate()`. Therefore by + // the time the wait ends, migration check would have happened. + profile_prepared.Wait(); + EXPECT_FALSE( + FakeSessionManagerClient::Get()->request_browser_data_migration_called()); + const std::string user_id_hash = + user_manager::FakeUserManager::GetFakeUsernameHash( + regular_user_.account_id); + EXPECT_TRUE( + crosapi::browser_util::IsCopyOrMoveProfileMigrationCompletedForUser( + g_browser_process->local_state(), user_id_hash)); +} + class BrowserDataMigratorMoveMigrateOnSignInByPolicy : public BrowserDataMigratorOnSignIn { public: @@ -193,29 +253,6 @@ "move"); } -// Check that migration marked as completed for a new user and thus migration is -// not triggered from signin flow. The key of this test is to use -// `LoginAsRegularUser()` instead of `LoginAsExistingUser()`. -IN_PROC_BROWSER_TEST_F(BrowserDataMigratorMoveMigrateOnSignInByFeature, - SkipMigrateOnSignInForNewUser) { - ash::test::ProfilePreparedWaiter profile_prepared(regular_user_.account_id); - ASSERT_TRUE(LoginAsRegularUser()); - // Note that `ProfilePreparedWaiter` waits for - // `ExistingUserController::OnProfilePrepared()` to be called and this is - // called after `UserSessionManager::InitializeUserSession()` is called, which - // leads to `BrowserDataMigratorImpl::MaybeRestartToMigrate()`. Therefore by - // the time the wait ends, migration check would have happened. - profile_prepared.Wait(); - EXPECT_FALSE( - FakeSessionManagerClient::Get()->request_browser_data_migration_called()); - const std::string user_id_hash = - user_manager::FakeUserManager::GetFakeUsernameHash( - regular_user_.account_id); - EXPECT_TRUE( - crosapi::browser_util::IsCopyOrMoveProfileMigrationCompletedForUser( - g_browser_process->local_state(), user_id_hash)); -} - class BrowserDataMigratorResumeOnSignIn : public BrowserDataMigratorOnSignIn, public LocalStateMixin::Delegate { public: @@ -422,10 +459,7 @@ ~BrowserDataMigratorForKiosk() override = default; void SetUp() override { - feature_list_.InitWithFeatures( - {ash::features::kLacrosSupport, ash::features::kLacrosPrimary, - ash::features::kLacrosOnly}, - {}); + feature_list_.InitWithFeatures({ash::features::kLacrosSupport}, {}); KioskBaseTest::SetUp(); }
diff --git a/chrome/browser/ash/crosapi/browser_data_migrator_unittest.cc b/chrome/browser/ash/crosapi/browser_data_migrator_unittest.cc index dbe93471..4debf01 100644 --- a/chrome/browser/ash/crosapi/browser_data_migrator_unittest.cc +++ b/chrome/browser/ash/crosapi/browser_data_migrator_unittest.cc
@@ -428,28 +428,12 @@ } { - // If Lacros enabled, but is not Lacros only, migration should not run. + // If Lacros is enabled, migration should run. base::test::ScopedFeatureList feature_list; - feature_list.InitWithFeatures( - {ash::features::kLacrosSupport, ash::features::kLacrosPrimary}, {}); + feature_list.InitWithFeatures({ash::features::kLacrosSupport}, {}); EXPECT_EQ(crosapi::browser_util::GetMigrationMode( user, crosapi::browser_util::PolicyInitState::kAfterInit), crosapi::browser_util::MigrationMode::kCopy); - EXPECT_FALSE(BrowserDataMigratorImpl::MaybeRestartToMigrateInternal( - user->GetAccountId(), user->username_hash(), - crosapi::browser_util::PolicyInitState::kAfterInit)); - } - - { - // If LacrosOnly is enabled, migration should run. - base::test::ScopedFeatureList feature_list; - feature_list.InitWithFeatures( - {ash::features::kLacrosSupport, ash::features::kLacrosPrimary, - ash::features::kLacrosOnly}, - {}); - EXPECT_EQ(crosapi::browser_util::GetMigrationMode( - user, crosapi::browser_util::PolicyInitState::kAfterInit), - crosapi::browser_util::MigrationMode::kMove); EXPECT_TRUE(BrowserDataMigratorImpl::MaybeRestartToMigrateInternal( user->GetAccountId(), user->username_hash(), crosapi::browser_util::PolicyInitState::kAfterInit));
diff --git a/chrome/browser/ash/crosapi/browser_manager.cc b/chrome/browser/ash/crosapi/browser_manager.cc index 2b14823..d45963b 100644 --- a/chrome/browser/ash/crosapi/browser_manager.cc +++ b/chrome/browser/ash/crosapi/browser_manager.cc
@@ -1538,14 +1538,19 @@ case user_manager::USER_TYPE_KIOSK_APP: case user_manager::USER_TYPE_PUBLIC_ACCOUNT: case user_manager::USER_TYPE_WEB_KIOSK_APP: { - policy::DeviceLocalAccountPolicyBroker* broker = + policy::DeviceLocalAccountPolicyService* policy_service = g_browser_process->platform_part() ->browser_policy_connector_ash() - ->GetDeviceLocalAccountPolicyService() - ->GetBrokerForUser(user->GetAccountId().GetUserEmail()); - if (broker) { - core = broker->core(); - component_policy_service = broker->component_policy_service(); + ->GetDeviceLocalAccountPolicyService(); + // `policy_service` can be nullptr, e.g. in unit tests. + if (policy_service) { + policy::DeviceLocalAccountPolicyBroker* broker = + policy_service->GetBrokerForUser( + user->GetAccountId().GetUserEmail()); + if (broker) { + core = broker->core(); + component_policy_service = broker->component_policy_service(); + } } break; }
diff --git a/chrome/browser/ash/crosapi/browser_manager_unittest.cc b/chrome/browser/ash/crosapi/browser_manager_unittest.cc index 3f522c5..04770cc 100644 --- a/chrome/browser/ash/crosapi/browser_manager_unittest.cc +++ b/chrome/browser/ash/crosapi/browser_manager_unittest.cc
@@ -23,6 +23,7 @@ #include "components/component_updater/mock_component_updater_service.h" #include "components/session_manager/core/session_manager.h" #include "components/user_manager/scoped_user_manager.h" +#include "components/user_manager/user_manager.h" #include "content/public/test/browser_task_environment.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -79,8 +80,9 @@ void SimulateLacrosTermination() { SetStatePublic(State::TERMINATING); - if (browser_service_.has_value()) + if (browser_service_.has_value()) { OnBrowserServiceDisconnected(*crosapi_id_, browser_service_->mojo_id); + } OnLacrosChromeTerminated(); } @@ -192,15 +194,57 @@ crosapi::browser_util::ClearLacrosAvailabilityCacheForTest(); } - void AddRegularUser(const std::string& email) { + enum class UserType { + kRegularUser = 0, + kWebKiosk = 1, + kChromeAppKiosk = 2, + kMaxValue = kChromeAppKiosk, + }; + + void AddUser(UserType user_type) { + const std::string email = "user@test.com"; AccountId account_id = AccountId::FromUserEmail(email); - const User* user = fake_user_manager_->AddUser(account_id); + + User* user; + switch (user_type) { + case UserType::kRegularUser: + user = fake_user_manager_->AddUser(account_id); + break; + case UserType::kWebKiosk: + user = fake_user_manager_->AddWebKioskAppUser(account_id); + break; + case UserType::kChromeAppKiosk: + user = fake_user_manager_->AddKioskAppUser(account_id); + break; + } + fake_user_manager_->UserLoggedIn(account_id, user->username_hash(), /*browser_restart=*/false, /*is_child=*/false); fake_user_manager_->SimulateUserProfileLoad(account_id); ash::ProfileHelper::Get()->SetUserToProfileMappingForTesting( user, &testing_profile_); + + browser_util::SetProfileMigrationCompletedForUser( + local_state_.Get(), + ash::ProfileHelper::Get() + ->GetUserByProfile(&testing_profile_) + ->username_hash(), + browser_util::MigrationMode::kCopy); + + EXPECT_TRUE(browser_util::IsLacrosEnabled()); + EXPECT_TRUE(browser_util::IsLacrosAllowedToLaunch()); + } + + void ExpectCallingLoad(browser_util::LacrosSelection load_selection = + browser_util::LacrosSelection::kRootfs, + const std::string& lacros_path = "/run/lacros") { + EXPECT_CALL(*browser_loader_, Load(_)) + .WillOnce([load_selection, lacros_path]( + BrowserLoader::LoadCompletionCallback callback) { + std::move(callback).Run(base::FilePath(lacros_path), load_selection, + base::Version()); + }); } protected: @@ -227,27 +271,14 @@ }; TEST_F(BrowserManagerTest, LacrosKeepAlive) { - AddRegularUser("user@test.com"); - browser_util::SetProfileMigrationCompletedForUser( - local_state_.Get(), - ash::ProfileHelper::Get() - ->GetUserByProfile(&testing_profile_) - ->username_hash(), - browser_util::MigrationMode::kCopy); - EXPECT_TRUE(browser_util::IsLacrosEnabled()); - EXPECT_TRUE(browser_util::IsLacrosAllowedToLaunch()); + AddUser(UserType::kRegularUser); using State = BrowserManagerFake::State; EXPECT_EQ(fake_browser_manager_->start_count(), 0); // Attempt to mount the Lacros image. Will not start as it does not meet the // automatic start criteria. - EXPECT_CALL(*browser_loader_, Load(_)) - .WillOnce([](BrowserLoader::LoadCompletionCallback callback) { - std::move(callback).Run(base::FilePath("/run/lacros"), - browser_util::LacrosSelection::kRootfs, - base::Version()); - }); + ExpectCallingLoad(); fake_browser_manager_->InitializeAndStartIfNeeded(); EXPECT_EQ(fake_browser_manager_->start_count(), 0); @@ -274,22 +305,8 @@ } TEST_F(BrowserManagerTest, LacrosKeepAliveReloadsWhenUpdateAvailable) { - AddRegularUser("user@test.com"); - browser_util::SetProfileMigrationCompletedForUser( - local_state_.Get(), - ash::ProfileHelper::Get() - ->GetUserByProfile(&testing_profile_) - ->username_hash(), - browser_util::MigrationMode::kCopy); - EXPECT_TRUE(browser_util::IsLacrosEnabled()); - EXPECT_TRUE(browser_util::IsLacrosAllowedToLaunch()); - - EXPECT_CALL(*browser_loader_, Load(_)) - .WillOnce([](BrowserLoader::LoadCompletionCallback callback) { - std::move(callback).Run(base::FilePath("/run/lacros"), - browser_util::LacrosSelection::kRootfs, - base::Version()); - }); + AddUser(UserType::kRegularUser); + ExpectCallingLoad(); fake_browser_manager_->InitializeAndStartIfNeeded(); using State = BrowserManagerFake::State; @@ -305,12 +322,8 @@ std::unique_ptr<BrowserManager::ScopedKeepAlive> keep_alive = fake_browser_manager_->KeepAlive(BrowserManager::Feature::kTestOnly); - EXPECT_CALL(*browser_loader_, Load(_)) - .WillOnce([](BrowserLoader::LoadCompletionCallback callback) { - std::move(callback).Run(base::FilePath(kSampleLacrosPath), - browser_util::LacrosSelection::kStateful, - base::Version()); - }); + ExpectCallingLoad(browser_util::LacrosSelection::kStateful, + kSampleLacrosPath); // On simulated termination, KeepAlive restarts Lacros. Since there is an // update, it should first load the updated image. @@ -320,22 +333,8 @@ } TEST_F(BrowserManagerTest, NewWindowReloadsWhenUpdateAvailable) { - AddRegularUser("user@test.com"); - browser_util::SetProfileMigrationCompletedForUser( - local_state_.Get(), - ash::ProfileHelper::Get() - ->GetUserByProfile(&testing_profile_) - ->username_hash(), - browser_util::MigrationMode::kCopy); - EXPECT_TRUE(browser_util::IsLacrosEnabled()); - EXPECT_TRUE(browser_util::IsLacrosAllowedToLaunch()); - - EXPECT_CALL(*browser_loader_, Load(_)) - .WillOnce([](BrowserLoader::LoadCompletionCallback callback) { - std::move(callback).Run(base::FilePath("/run/lacros"), - browser_util::LacrosSelection::kRootfs, - base::Version()); - }); + AddUser(UserType::kRegularUser); + ExpectCallingLoad(); fake_browser_manager_->InitializeAndStartIfNeeded(); // Set the state of the browser manager as stopped, which would match the @@ -360,28 +359,14 @@ TEST_F(BrowserManagerTest, LacrosKeepAliveDoesNotBlockRestart) { EXPECT_CALL(mock_browser_service_, UpdateKeepAlive(_)).Times(0); - - AddRegularUser("user@test.com"); - browser_util::SetProfileMigrationCompletedForUser( - local_state_.Get(), - ash::ProfileHelper::Get() - ->GetUserByProfile(&testing_profile_) - ->username_hash(), - browser_util::MigrationMode::kCopy); - EXPECT_TRUE(browser_util::IsLacrosEnabled()); - EXPECT_TRUE(browser_util::IsLacrosAllowedToLaunch()); + AddUser(UserType::kRegularUser); using State = BrowserManagerFake::State; EXPECT_EQ(fake_browser_manager_->start_count(), 0); // Attempt to mount the Lacros image. Will not start as it does not meet the // automatic start criteria. - EXPECT_CALL(*browser_loader_, Load(_)) - .WillOnce([](BrowserLoader::LoadCompletionCallback callback) { - std::move(callback).Run(base::FilePath("/run/lacros"), - browser_util::LacrosSelection::kRootfs, - base::Version()); - }); + ExpectCallingLoad(); fake_browser_manager_->InitializeAndStartIfNeeded(); EXPECT_EQ(fake_browser_manager_->start_count(), 0); @@ -431,4 +416,28 @@ EXPECT_EQ(fake_browser_manager_->start_count(), 4); } +// In the Kiosk session, the Lacros window is created during the kiosk launch, +// no need to create a new window in this case. +TEST_F(BrowserManagerTest, DoNotOpenNewLacrosWindowInChromeAppKiosk) { + AddUser(UserType::kChromeAppKiosk); + ExpectCallingLoad(); + + fake_browser_manager_->InitializeAndStartIfNeeded(); + + EXPECT_CALL(mock_browser_service_, NewWindow(_, _, _, _)).Times(0); + + fake_browser_manager_->SimulateLacrosStart(&mock_browser_service_); +} + +TEST_F(BrowserManagerTest, DoNotOpenNewLacrosWindowInWebKiosk) { + AddUser(UserType::kWebKiosk); + ExpectCallingLoad(); + + fake_browser_manager_->InitializeAndStartIfNeeded(); + + EXPECT_CALL(mock_browser_service_, NewWindow(_, _, _, _)).Times(0); + + fake_browser_manager_->SimulateLacrosStart(&mock_browser_service_); +} + } // namespace crosapi
diff --git a/chrome/browser/ash/crosapi/browser_util.cc b/chrome/browser/ash/crosapi/browser_util.cc index cf2eee9..1971636 100644 --- a/chrome/browser/ash/crosapi/browser_util.cc +++ b/chrome/browser/ash/crosapi/browser_util.cc
@@ -433,12 +433,6 @@ return false; } - // Profile migration is only available for is Lacros is the only browser i.e. - // LacrosOnly mode. - if (IsAshWebBrowserEnabled()) { - return false; - } - // If migration is already completed, it is not necessary to run again. if (IsCopyOrMoveProfileMigrationCompletedForUser( user_manager->GetLocalState(), user->username_hash())) {
diff --git a/chrome/browser/ash/crosapi/prefs_ash.cc b/chrome/browser/ash/crosapi/prefs_ash.cc index f7b9f91..60a843dd 100644 --- a/chrome/browser/ash/crosapi/prefs_ash.cc +++ b/chrome/browser/ash/crosapi/prefs_ash.cc
@@ -53,6 +53,10 @@ {mojom::PrefPath::kApplicationLocale, language::prefs::kApplicationLocale}, {mojom::PrefPath::kSharedStorage, prefs::kSharedStorage}, + {mojom::PrefPath::kMultitaskMenuNudgeClamshellShownCount, + ash::prefs::kMultitaskMenuNudgeClamshellShownCount}, + {mojom::PrefPath::kMultitaskMenuNudgeClamshellLastShown, + ash::prefs::kMultitaskMenuNudgeClamshellLastShown}, }); auto pref_name = profile_prefpath_to_name->find(path); DCHECK(pref_name != profile_prefpath_to_name->end()); @@ -251,7 +255,9 @@ case mojom::PrefPath::kQuickAnswersNoticeImpressionDuration: case mojom::PrefPath::kPreferredLanguages: case mojom::PrefPath::kApplicationLocale: - case mojom::PrefPath::kSharedStorage: { + case mojom::PrefPath::kSharedStorage: + case mojom::PrefPath::kMultitaskMenuNudgeClamshellShownCount: + case mojom::PrefPath::kMultitaskMenuNudgeClamshellLastShown: { if (!profile_prefs_registrar_) { LOG(WARNING) << "Primary profile is not yet initialized"; return absl::nullopt;
diff --git a/chrome/browser/ash/login/oobe_quick_start/connectivity/BUILD.gn b/chrome/browser/ash/login/oobe_quick_start/connectivity/BUILD.gn index 0b6decd..99477cf7 100644 --- a/chrome/browser/ash/login/oobe_quick_start/connectivity/BUILD.gn +++ b/chrome/browser/ash/login/oobe_quick_start/connectivity/BUILD.gn
@@ -39,6 +39,8 @@ "target_device_connection_broker_factory.h", "target_device_connection_broker_impl.cc", "target_device_connection_broker_impl.h", + "wifi_credentials.cc", + "wifi_credentials.h", ] }
diff --git a/chrome/browser/ash/login/oobe_quick_start/connectivity/authenticated_connection.cc b/chrome/browser/ash/login/oobe_quick_start/connectivity/authenticated_connection.cc index 2de6803..64f0fa16 100644 --- a/chrome/browser/ash/login/oobe_quick_start/connectivity/authenticated_connection.cc +++ b/chrome/browser/ash/login/oobe_quick_start/connectivity/authenticated_connection.cc
@@ -103,6 +103,11 @@ SendPayload(message_payload); } +void AuthenticatedConnection::RequestWifiCredentials( + RequestWifiCredentialsCallback callback) { + NOTIMPLEMENTED(); +} + void AuthenticatedConnection::SendBootstrapOptions( ConnectionResponseCallback callback) { base::Value::Dict bootstrap_options;
diff --git a/chrome/browser/ash/login/oobe_quick_start/connectivity/authenticated_connection.h b/chrome/browser/ash/login/oobe_quick_start/connectivity/authenticated_connection.h index 1e37bd6..e6e8a255 100644 --- a/chrome/browser/ash/login/oobe_quick_start/connectivity/authenticated_connection.h +++ b/chrome/browser/ash/login/oobe_quick_start/connectivity/authenticated_connection.h
@@ -11,6 +11,7 @@ #include "base/memory/weak_ptr.h" #include "chrome/browser/ash/login/oobe_quick_start/connectivity/connection.h" #include "chrome/browser/ash/login/oobe_quick_start/connectivity/fido_assertion_info.h" +#include "chrome/browser/ash/login/oobe_quick_start/connectivity/wifi_credentials.h" #include "chrome/browser/nearby_sharing/public/cpp/nearby_connection.h" #include "components/cbor/values.h" #include "url/origin.h" @@ -26,6 +27,9 @@ using RequestAccountTransferAssertionCallback = base::OnceCallback<void(absl::optional<FidoAssertionInfo>)>; + using RequestWifiCredentialsCallback = + base::OnceCallback<void(absl::optional<WifiCredentials>)>; + explicit AuthenticatedConnection(NearbyConnection* nearby_connection); AuthenticatedConnection(AuthenticatedConnection&) = delete; AuthenticatedConnection& operator=(AuthenticatedConnection&) = delete; @@ -35,6 +39,8 @@ const std::string& challenge_b64url, RequestAccountTransferAssertionCallback callback); + void RequestWifiCredentials(RequestWifiCredentialsCallback callback); + void NotifySourceOfUpdate(); private:
diff --git a/chrome/browser/ash/login/oobe_quick_start/connectivity/wifi_credentials.cc b/chrome/browser/ash/login/oobe_quick_start/connectivity/wifi_credentials.cc new file mode 100644 index 0000000..a6ed628f --- /dev/null +++ b/chrome/browser/ash/login/oobe_quick_start/connectivity/wifi_credentials.cc
@@ -0,0 +1,18 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "wifi_credentials.h" + +namespace ash::quick_start { + +WifiCredentials::WifiCredentials() = default; + +WifiCredentials::~WifiCredentials() = default; + +WifiCredentials::WifiCredentials(const WifiCredentials& other) = default; + +WifiCredentials& WifiCredentials::operator=(const WifiCredentials& other) = + default; + +} // namespace ash::quick_start
diff --git a/chrome/browser/ash/login/oobe_quick_start/connectivity/wifi_credentials.h b/chrome/browser/ash/login/oobe_quick_start/connectivity/wifi_credentials.h new file mode 100644 index 0000000..0767a203 --- /dev/null +++ b/chrome/browser/ash/login/oobe_quick_start/connectivity/wifi_credentials.h
@@ -0,0 +1,37 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_ASH_LOGIN_OOBE_QUICK_START_CONNECTIVITY_WIFI_CREDENTIALS_H_ +#define CHROME_BROWSER_ASH_LOGIN_OOBE_QUICK_START_CONNECTIVITY_WIFI_CREDENTIALS_H_ + +#include <string> + +namespace ash::quick_start { + +// A `struct` to store the information related to a device's Wifi Credentials. +// It is constructed from the information returned by whatever device is +// helping setup this device, and is used in the Quick Start flow to configure +// the device's Wifi connection. +struct WifiCredentials { + WifiCredentials(); + WifiCredentials(const WifiCredentials& other); + WifiCredentials& operator=(const WifiCredentials& other); + ~WifiCredentials(); + + // The SSID of the Wifi Network. + std::string ssid; + + // The password of the Wifi Network. + std::string password; + + // Whether this is a hidden Wifi Network. + bool is_hidden; + + // The Security Type of the Wifi Network. + std::string security_type; +}; + +} // namespace ash::quick_start + +#endif // CHROME_BROWSER_ASH_LOGIN_OOBE_QUICK_START_CONNECTIVITY_WIFI_CREDENTIALS_H_
diff --git a/chrome/browser/ash/login/saml/saml_browsertest.cc b/chrome/browser/ash/login/saml/saml_browsertest.cc index ff4c582..10f1e5e 100644 --- a/chrome/browser/ash/login/saml/saml_browsertest.cc +++ b/chrome/browser/ash/login/saml/saml_browsertest.cc
@@ -1122,6 +1122,10 @@ protected: policy::DevicePolicyCrosTestHelper test_helper_; + // TODO(b/270930387): refactor to do device policy updates through + // `device_state_` from `SamlTestBase` instead. Right now we have two ways to + // do device policy updates in this fixture and they are not interchangeable + // as they update different policy blobs. policy::DevicePolicyBuilder* device_policy_; NiceMock<policy::MockConfigurationPolicyProvider> provider_; net::CookieList cookie_list_; @@ -1760,6 +1764,58 @@ SigninFrameJS().ExpectEQ("navigator.language", std::string(kLoginLocale)); } +// For tests relying on sso_profile in device policy blob which is responcible +// for per-OU IdP configuration. +class SsoProfileTest : public SamlTestBase { + public: + SsoProfileTest(); + + SsoProfileTest(const SsoProfileTest&) = delete; + SsoProfileTest& operator=(const SsoProfileTest&) = delete; + + ~SsoProfileTest() override = default; +}; + +SsoProfileTest::SsoProfileTest() { + device_state_.SetState( + DeviceStateMixin::State::OOBE_COMPLETED_CLOUD_ENROLLED); + std::unique_ptr<ScopedDevicePolicyUpdate> policy_update = + device_state_.RequestDevicePolicyUpdate(); + // Set LoginAuthenticationBehavior policy to go directly to 3P IdP login page + em::ChromeDeviceSettingsProto& proto(*policy_update->policy_payload()); + proto.mutable_login_authentication_behavior() + ->set_login_authentication_behavior( + em::LoginAuthenticationBehaviorProto_LoginBehavior_SAML_INTERSTITIAL); + // Set SSO Profile corresponding to `fake_saml_idp()` + policy_update->policy_data()->set_sso_profile( + fake_saml_idp()->GetIdpSsoProfile()); +} + +// Tests that we land on 3P IdP page corresponding to sso_profile from the +// device policy blob during "add user" flow. +IN_PROC_BROWSER_TEST_F(SsoProfileTest, AddNewUser) { + fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html"); + + // Set wrong redirect url for domain-based saml redirection. This ensures that + // for test to finish successfully it should perform redirection based on sso + // profile. + const GURL wrong_redirect_url("https://wrong.com"); + fake_gaia_.fake_gaia()->RegisterSamlDomainRedirectUrl( + fake_saml_idp()->GetIdpDomain(), wrong_redirect_url); + + // Launch "add user" flow. + ASSERT_TRUE(LoginScreenTestApi::ClickAddUserButton()); + OobeScreenWaiter(GaiaView::kScreenId).Wait(); + test::OobeJS().CreateVisibilityWaiter(true, kSigninFrameDialog)->Wait(); + test::OobeJS().CreateVisibilityWaiter(false, kGaiaLoading)->Wait(); + + SigninFrameJS().TypeIntoPath("fake_user", {"Email"}); + SigninFrameJS().TypeIntoPath("fake_password", {"Password"}); + + SigninFrameJS().TapOn("Submit"); + test::WaitForPrimaryUserSessionStart(); +} + class SAMLPasswordAttributesTest : public SAMLPolicyTest, public testing::WithParamInterface<bool> { public:
diff --git a/chrome/browser/ash/login/session/user_session_initializer.cc b/chrome/browser/ash/login/session/user_session_initializer.cc index b1b874d..580559a 100644 --- a/chrome/browser/ash/login/session/user_session_initializer.cc +++ b/chrome/browser/ash/login/session/user_session_initializer.cc
@@ -42,6 +42,7 @@ #include "chrome/browser/ui/ash/calendar/calendar_keyed_service_factory.h" #include "chrome/browser/ui/ash/clipboard_image_model_factory_impl.h" #include "chrome/browser/ui/ash/glanceables/chrome_glanceables_delegate.h" +#include "chrome/browser/ui/ash/glanceables/glanceables_keyed_service_factory.h" #include "chrome/browser/ui/ash/holding_space/holding_space_keyed_service_factory.h" #include "chrome/browser/ui/ash/media_client_impl.h" #include "chrome/browser/ui/webui/settings/ash/peripheral_data_access_handler.h" @@ -259,6 +260,9 @@ // created one per user in a multiprofile session. CalendarKeyedServiceFactory::GetInstance()->GetService(profile); + // Ensure that the `GlanceablesKeyedService` for `profile` is created. + GlanceablesKeyedServiceFactory::GetInstance()->GetService(profile); + if (is_primary_user) { DCHECK_EQ(primary_profile_, profile);
diff --git a/chrome/browser/ash/login/wizard_controller.cc b/chrome/browser/ash/login/wizard_controller.cc index a234c1d..c82a879 100644 --- a/chrome/browser/ash/login/wizard_controller.cc +++ b/chrome/browser/ash/login/wizard_controller.cc
@@ -207,8 +207,6 @@ #include "chromeos/ash/components/timezone/timezone_provider.h" #include "chromeos/ash/components/timezone/timezone_request.h" #include "chromeos/ash/services/rollback_network_config/public/mojom/rollback_network_config.mojom.h" -#include "components/crash/core/app/breakpad_linux.h" -#include "components/crash/core/app/crashpad.h" #include "components/metrics/structured/neutrino_logging.h" #include "components/metrics/structured/neutrino_logging_util.h" #include "components/prefs/pref_registry_simple.h"
diff --git a/chrome/browser/ash/policy/reporting/os_updates/os_updates_reporter_browsertest.cc b/chrome/browser/ash/policy/reporting/os_updates/os_updates_reporter_browsertest.cc new file mode 100644 index 0000000..bc609a9 --- /dev/null +++ b/chrome/browser/ash/policy/reporting/os_updates/os_updates_reporter_browsertest.cc
@@ -0,0 +1,183 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <string> + +#include "ash/constants/ash_switches.h" +#include "chrome/browser/ash/login/session/user_session_manager_test_api.h" +#include "chrome/browser/ash/login/test/login_manager_mixin.h" +#include "chrome/browser/ash/login/test/session_manager_state_waiter.h" +#include "chrome/browser/ash/login/test/user_policy_mixin.h" +#include "chrome/browser/ash/policy/core/device_policy_cros_browser_test.h" +#include "chrome/browser/ash/settings/scoped_testing_cros_settings.h" +#include "chrome/browser/ash/settings/stub_cros_settings_provider.h" +#include "chrome/browser/policy/messaging_layer/proto/synced/os_events.pb.h" +#include "chrome/test/base/fake_gaia_mixin.h" +#include "chrome/test/base/mixin_based_in_process_browser_test.h" +#include "chrome/test/base/testing_browser_process.h" +#include "chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h" +#include "chromeos/ash/components/dbus/update_engine/fake_update_engine_client.h" +#include "chromeos/ash/components/settings/cros_settings_names.h" +#include "chromeos/dbus/missive/missive_client.h" +#include "chromeos/dbus/missive/missive_client_test_observer.h" +#include "components/reporting/proto/synced/record.pb.h" +#include "components/reporting/proto/synced/record_constants.pb.h" +#include "components/signin/public/identity_manager/identity_test_utils.h" +#include "content/public/test/browser_test.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using ::chromeos::MissiveClientTestObserver; +using ::reporting::Destination; +using ::reporting::Priority; +using ::reporting::Record; +using ::testing::Eq; + +namespace ash::reporting { +namespace { + +constexpr char kTestUserEmail[] = "test@example.com"; +constexpr char kTestAffiliationId[] = "test_affiliation_id"; +constexpr char kNewPlatformVersion[] = "1235.0.0"; +static const AccountId kTestAccountId = AccountId::FromUserEmailGaiaId( + kTestUserEmail, + signin::GetTestGaiaIdForEmail(kTestUserEmail)); + +struct OsUpdatesReporterBrowserTestCase { + update_engine::Operation operation; + bool enterprise_rollback; +}; + +Record GetNextOsEventsRecord(MissiveClientTestObserver* observer) { + std::tuple<Priority, Record> enqueued_record = + observer->GetNextEnqueuedRecord(); + Priority priority = std::get<0>(enqueued_record); + Record record = std::get<1>(enqueued_record); + + EXPECT_THAT(priority, Eq(Priority::SECURITY)); + return record; +} + +class OsUpdatesReporterBrowserTest + : public policy::DevicePolicyCrosBrowserTest { + protected: + OsUpdatesReporterBrowserTest() { + login_manager_mixin_.AppendRegularUsers(1); + scoped_testing_cros_settings_.device_settings()->SetBoolean( + kReportOsUpdateStatus, true); + } + + void SetUpOnMainThread() override { + login_manager_mixin_.set_should_launch_browser(true); + policy::DevicePolicyCrosBrowserTest::SetUpOnMainThread(); + } + + void SetUpInProcessBrowserTestFixture() override { + policy::DevicePolicyCrosBrowserTest::SetUpInProcessBrowserTestFixture(); + fake_update_engine_client_ = + ash::UpdateEngineClient::InitializeFakeForTest(); + + // Set up affiliation for the test user. + auto device_policy_update = device_state_.RequestDevicePolicyUpdate(); + auto user_policy_update = user_policy_mixin_.RequestPolicyUpdate(); + + device_policy_update->policy_data()->add_device_affiliation_ids( + kTestAffiliationId); + user_policy_update->policy_data()->add_user_affiliation_ids( + kTestAffiliationId); + } + + void SendFakeUpdateEngineStatus(const std::string& version, + bool is_rollback, + update_engine::Operation current_operation) { + update_engine::StatusResult status; + status.set_new_version(version); + status.set_is_enterprise_rollback(is_rollback); + status.set_will_powerwash_after_reboot(false); + status.set_current_operation(current_operation); + fake_update_engine_client_->set_default_status(status); + fake_update_engine_client_->NotifyObserversThatStatusChanged(status); + } + + ash::FakeSessionManagerClient* session_manager_client(); + + UserPolicyMixin user_policy_mixin_{&mixin_host_, kTestAccountId}; + + FakeGaiaMixin fake_gaia_mixin_{&mixin_host_}; + + LoginManagerMixin login_manager_mixin_{ + &mixin_host_, LoginManagerMixin::UserList(), &fake_gaia_mixin_}; + + ScopedTestingCrosSettings scoped_testing_cros_settings_; + + FakeUpdateEngineClient* fake_update_engine_client_ = nullptr; +}; + +IN_PROC_BROWSER_TEST_F(OsUpdatesReporterBrowserTest, ReportUpdateSuccessEvent) { + MissiveClientTestObserver observer(Destination::OS_EVENTS); + + SendFakeUpdateEngineStatus( + /*version=*/kNewPlatformVersion, /*is_rollback=*/false, + /*current_operation=*/update_engine::Operation::UPDATED_NEED_REBOOT); + + const Record& update_record = GetNextOsEventsRecord(&observer); + OsEventsRecord update_record_data; + ASSERT_TRUE(update_record_data.ParseFromString(update_record.data())); + + ASSERT_TRUE(update_record_data.has_update_event()); + EXPECT_TRUE(update_record_data.has_event_timestamp_sec()); + EXPECT_EQ(update_record_data.target_os_version(), kNewPlatformVersion); + EXPECT_EQ(update_record_data.os_operation_type(), + reporting::OsOperationType::SUCCESS); +} + +class OsUpdatesReporterBrowserErrorTest + : public OsUpdatesReporterBrowserTest, + public ::testing::WithParamInterface<OsUpdatesReporterBrowserTestCase> { + protected: + OsUpdatesReporterBrowserErrorTest() {} +}; + +IN_PROC_BROWSER_TEST_P(OsUpdatesReporterBrowserErrorTest, ReportErrorEvent) { + const auto test_case = GetParam(); + MissiveClientTestObserver observer(Destination::OS_EVENTS); + + SendFakeUpdateEngineStatus( + /*version=*/kNewPlatformVersion, + /*is_rollback=*/test_case.enterprise_rollback, + /*current_operation=*/test_case.operation); + + const Record& update_record = GetNextOsEventsRecord(&observer); + OsEventsRecord update_record_data; + ASSERT_TRUE(update_record_data.ParseFromString(update_record.data())); + + if (test_case.enterprise_rollback) { + ASSERT_TRUE(update_record_data.has_rollback_event()); + } else { + ASSERT_TRUE(update_record_data.has_update_event()); + } + + EXPECT_TRUE(update_record_data.has_event_timestamp_sec()); + EXPECT_EQ(update_record_data.target_os_version(), kNewPlatformVersion); + // The reported os_operation_type is FAILURE regardless of the + // test_case.operation. + EXPECT_EQ(update_record_data.os_operation_type(), + reporting::OsOperationType::FAILURE); +} + +INSTANTIATE_TEST_SUITE_P( + All, + OsUpdatesReporterBrowserErrorTest, + ::testing::ValuesIn<OsUpdatesReporterBrowserTestCase>( + {{/*operation=*/update_engine::Operation::ERROR, + /*enterprise_rollback=*/true}, + {/*operation=*/update_engine::Operation::ERROR, + /*enterprise_rollback=*/false}, + {/*operation=*/update_engine::Operation::REPORTING_ERROR_EVENT, + /*enterprise_rollback=*/true}, + {/*operation=*/update_engine::Operation::REPORTING_ERROR_EVENT, + /*enterprise_rollback=*/false}})); + +} // namespace +} // namespace ash::reporting
diff --git a/chrome/browser/ash/web_applications/firmware_update_system_web_app_info.cc b/chrome/browser/ash/web_applications/firmware_update_system_web_app_info.cc index e285593..e69d4cba 100644 --- a/chrome/browser/ash/web_applications/firmware_update_system_web_app_info.cc +++ b/chrome/browser/ash/web_applications/firmware_update_system_web_app_info.cc
@@ -6,7 +6,10 @@ #include <memory> +#include "ash/constants/ash_features.h" +#include "ash/shell.h" #include "ash/strings/grit/ash_strings.h" +#include "ash/style/color_util.h" #include "ash/webui/firmware_update_ui/url_constants.h" #include "ash/webui/grit/ash_firmware_update_app_resources.h" #include "ash/webui/system_apps/public/system_web_app_type.h" @@ -15,7 +18,7 @@ #include "chrome/browser/web_applications/web_app_install_info.h" #include "third_party/blink/public/mojom/manifest/display_mode.mojom.h" #include "ui/base/l10n/l10n_util.h" -#include "ui/chromeos/styles/cros_styles.h" +#include "ui/chromeos/styles/cros_tokens_color_mappings.h" #include "ui/display/screen.h" namespace { @@ -27,9 +30,18 @@ // FirmwareUpdateApp's title bar and background needs to be bg-elevation-2 for // dark mode instead of the default dark mode background color. SkColor GetDarkModeBackgroundColor() { - return cros_styles::ResolveColor(cros_styles::ColorName::kBgColorElevation2, - /*is_dark_mode=*/true); + // This code will be deleted after Jelly launch. Do NOT copy it! This was + // copied from system_web_app_install_utils.cc + ui::ColorProviderSource* color_provider_source = + ash::ColorUtil::GetColorProviderSourceForWindow( + ash::Shell::GetPrimaryRootWindow()); + DCHECK(color_provider_source); + const ui::ColorProvider* color_provider = + color_provider_source->GetColorProvider(); + DCHECK(color_provider); + return color_provider->GetColor(cros_tokens::kBgColorElevation2Dark); } + } // namespace // TODO(michaelcheco): Update to correct icon. @@ -47,9 +59,13 @@ info->user_display_mode = web_app::mojom::UserDisplayMode::kStandalone; info->theme_color = web_app::GetDefaultBackgroundColor(/*use_dark_mode=*/false); - info->dark_mode_theme_color = GetDarkModeBackgroundColor(); + if (!ash::features::IsJellyEnabled()) { + // Once Jelly is launched, the theme and background colors for SWA are + // ignored and this can be deleted. + info->dark_mode_theme_color = GetDarkModeBackgroundColor(); + info->dark_mode_background_color = info->dark_mode_theme_color; + } info->background_color = info->theme_color; - info->dark_mode_background_color = info->dark_mode_theme_color; return info; }
diff --git a/chrome/browser/ash/web_applications/projector_app/projector_app_integration_browsertest.cc b/chrome/browser/ash/web_applications/projector_app/projector_app_integration_browsertest.cc index 70719c3..91007c3 100644 --- a/chrome/browser/ash/web_applications/projector_app/projector_app_integration_browsertest.cc +++ b/chrome/browser/ash/web_applications/projector_app/projector_app_integration_browsertest.cc
@@ -72,7 +72,7 @@ ProjectorAppClientImpl* projector_app_client = static_cast<ProjectorAppClientImpl*>(ash::ProjectorAppClient::Get()); content::WebContents* annotator_embedder = - projector_app_client->get_annotator_message_handler_for_test() + projector_app_client->get_annotator_handler_for_test() ->get_web_ui_for_test() ->GetWebContents(); PrepareAppForTest(annotator_embedder);
diff --git a/chrome/browser/autofill/content_autofill_driver_browsertest.cc b/chrome/browser/autofill/content_autofill_driver_browsertest.cc index 5c2c0a8..3ff1836 100644 --- a/chrome/browser/autofill/content_autofill_driver_browsertest.cc +++ b/chrome/browser/autofill/content_autofill_driver_browsertest.cc
@@ -160,7 +160,7 @@ }; IN_PROC_BROWSER_TEST_F(ContentAutofillDriverBrowserTest, - SwitchTabAndHideAutofillPopup) { + DISABLED_SwitchTabAndHideAutofillPopup) { EXPECT_CALL(autofill_client(), HideAutofillPopup(PopupHidingReason::kTabGone)); @@ -173,7 +173,7 @@ } IN_PROC_BROWSER_TEST_F(ContentAutofillDriverBrowserTest, - SameDocumentNavigationHideAutofillPopup) { + DISABLED_SameDocumentNavigationHideAutofillPopup) { ASSERT_TRUE(ui_test_utils::NavigateToURL( browser(), embedded_test_server()->GetURL("/autofill/autofill_test_form.html"))); @@ -196,7 +196,7 @@ } IN_PROC_BROWSER_TEST_F(ContentAutofillDriverBrowserTest, - PrerenderNavigationDoesntHideAutofillPopup) { + DISABLED_PrerenderNavigationDoesntHideAutofillPopup) { GURL initial_url = embedded_test_server()->GetURL("/autofill/autofill_test_form.html"); GURL prerender_url = embedded_test_server()->GetURL("/empty.html"); @@ -221,7 +221,7 @@ } IN_PROC_BROWSER_TEST_F(ContentAutofillDriverBrowserTest, - SubframeNavigationDoesntHideAutofillPopup) { + DISABLED_SubframeNavigationDoesntHideAutofillPopup) { // Main frame is on a.com, iframe is on b.com. GURL url = embedded_test_server()->GetURL( "a.com", "/autofill/cross_origin_iframe.html"); @@ -243,7 +243,7 @@ } IN_PROC_BROWSER_TEST_F(ContentAutofillDriverBrowserTest, - TestPageNavigationHidingAutofillPopup) { + DISABLED_TestPageNavigationHidingAutofillPopup) { // HideAutofillPopup is called once for each navigation. EXPECT_CALL(autofill_client(), HideAutofillPopup(PopupHidingReason::kNavigation)) @@ -275,7 +275,7 @@ }; IN_PROC_BROWSER_TEST_F(ContentAutofillDriverPrerenderBrowserTest, - PrerenderingDoesNotSubmitForm) { + DISABLED_PrerenderingDoesNotSubmitForm) { GURL initial_url = embedded_test_server()->GetURL("/autofill/autofill_test_form.html"); ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), initial_url));
diff --git a/chrome/browser/autofill/form_structure_browsertest.cc b/chrome/browser/autofill/form_structure_browsertest.cc index 58bfc69..c1737a4 100644 --- a/chrome/browser/autofill/form_structure_browsertest.cc +++ b/chrome/browser/autofill/form_structure_browsertest.cc
@@ -228,7 +228,10 @@ {// TODO(crbug.com/1311937): Remove once launched. // This feature is part of the AutofillRefinedPhoneNumberTypes rollout. // As it is not supported on iOS yet, it is disabled. - features::kAutofillConsiderPhoneNumberSeparatorsValidLabels}); + features::kAutofillConsiderPhoneNumberSeparatorsValidLabels, + // TODO(crbug.com/1317961): Remove once launched. This feature is + // disabled since it is not supported on iOS. + features::kAutofillAlwaysParsePlaceholders}); } FormStructureBrowserTest::~FormStructureBrowserTest() = default;
diff --git a/chrome/browser/chrome_browser_interface_binders.cc b/chrome/browser/chrome_browser_interface_binders.cc index a00df9b7..b6a072f9 100644 --- a/chrome/browser/chrome_browser_interface_binders.cc +++ b/chrome/browser/chrome_browser_interface_binders.cc
@@ -249,6 +249,8 @@ #include "ash/webui/personalization_app/personalization_app_ui.h" #include "ash/webui/personalization_app/search/search.mojom.h" #include "ash/webui/print_management/print_management_ui.h" +#include "ash/webui/projector_app/mojom/annotator.mojom.h" +#include "ash/webui/projector_app/trusted_projector_annotator_ui.h" #include "ash/webui/scanning/mojom/scanning.mojom.h" #include "ash/webui/scanning/scanning_ui.h" #include "ash/webui/shimless_rma/shimless_rma.h" @@ -1208,6 +1210,10 @@ ash::camera_app::mojom::CameraAppHelper, ash::CameraAppUI>(map); RegisterWebUIControllerInterfaceBinder< + ash::annotator::mojom::AnnotatorPageHandlerFactory, + ash::TrustedProjectorAnnotatorUI>(map); + + RegisterWebUIControllerInterfaceBinder< ash::help_app::mojom::PageHandlerFactory, ash::HelpAppUI>(map); RegisterWebUIControllerInterfaceBinder<
diff --git a/chrome/browser/chrome_browser_main_linux.cc b/chrome/browser/chrome_browser_main_linux.cc index c5a8c21..62fef8b 100644 --- a/chrome/browser/chrome_browser_main_linux.cc +++ b/chrome/browser/chrome_browser_main_linux.cc
@@ -18,9 +18,6 @@ #include "chrome/browser/browser_process.h" #include "chrome/common/chrome_features.h" #include "chrome/grit/chromium_strings.h" -#include "components/crash/core/app/breakpad_linux.h" -#include "components/crash/core/app/crashpad.h" -#include "components/metrics/metrics_service.h" #include "content/public/browser/browser_task_traits.h" #include "device/bluetooth/dbus/bluez_dbus_manager.h" #include "device/bluetooth/dbus/bluez_dbus_thread_manager.h"
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index e5845ca..959b84fe 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -1525,8 +1525,22 @@ #endif +std::unique_ptr<blocked_content::PopupNavigationDelegate> +CreatePopupNavigationDelegate(NavigateParams params) { + return std::make_unique<ChromePopupNavigationDelegate>(std::move(params)); +} + +ChromeContentBrowserClient::PopupNavigationDelegateFactory + g_popup_navigation_delegate_factory = &CreatePopupNavigationDelegate; + } // namespace +// static +ChromeContentBrowserClient::PopupNavigationDelegateFactory& +ChromeContentBrowserClient::GetPopupNavigationDelegateFactoryForTesting() { + return g_popup_navigation_delegate_factory; +} + ChromeContentBrowserClient::ChromeContentBrowserClient() { #if BUILDFLAG(ENABLE_PLUGINS) extra_parts_.push_back(new ChromeContentBrowserClientPluginsPart); @@ -3853,8 +3867,7 @@ return !blocked_content::ConsiderForPopupBlocking(disposition) || blocked_content::MaybeBlockPopup( web_contents, &opener_top_level_frame_url, - std::make_unique<ChromePopupNavigationDelegate>( - std::move(nav_params)), + (*g_popup_navigation_delegate_factory)(std::move(nav_params)), nullptr /*=open_url_params*/, blocked_params.features(), HostContentSettingsMapFactory::GetForProfile(profile)) != nullptr; }
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h index 7ecb90a..cb52c65 100644 --- a/chrome/browser/chrome_content_browser_client.h +++ b/chrome/browser/chrome_content_browser_client.h
@@ -57,6 +57,10 @@ class URLLoaderThrottle; } // namespace blink +namespace blocked_content { +class PopupNavigationDelegate; +} // namespace blocked_content + namespace content { class BrowserContext; class RenderFrameHost; @@ -104,6 +108,7 @@ class ChromeSerialDelegate; class ChromeUsbDelegate; class ChromeWebAuthenticationDelegate; +struct NavigateParams; #if BUILDFLAG(ENABLE_VR) namespace vr { @@ -113,6 +118,13 @@ class ChromeContentBrowserClient : public content::ContentBrowserClient { public: + using PopupNavigationDelegateFactory = + std::unique_ptr<blocked_content::PopupNavigationDelegate> (*)( + NavigateParams); + + static PopupNavigationDelegateFactory& + GetPopupNavigationDelegateFactoryForTesting(); + ChromeContentBrowserClient(); ChromeContentBrowserClient(const ChromeContentBrowserClient&) = delete;
diff --git a/chrome/browser/chromeos/app_mode/chrome_kiosk_app_launcher_unittest.cc b/chrome/browser/chromeos/app_mode/chrome_kiosk_app_launcher_unittest.cc index b067b24..bb88e9dc 100644 --- a/chrome/browser/chromeos/app_mode/chrome_kiosk_app_launcher_unittest.cc +++ b/chrome/browser/chromeos/app_mode/chrome_kiosk_app_launcher_unittest.cc
@@ -59,11 +59,11 @@ extensions::api::app_runtime::OnLaunched::kEventName); ASSERT_EQ(1u, event.event_args.size()); - const base::Value& launch_data = event.event_args[0]; - const base::Value* is_kiosk_session = - launch_data.FindKeyOfType("isKioskSession", base::Value::Type::BOOLEAN); + const base::Value::Dict& launch_data = event.event_args[0].GetDict(); + absl::optional<bool> is_kiosk_session = + launch_data.FindBool("isKioskSession"); ASSERT_TRUE(is_kiosk_session); - EXPECT_TRUE(is_kiosk_session->GetBool()); + EXPECT_TRUE(*is_kiosk_session); launched_apps_.push_back(extension_id); }
diff --git a/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorCoordinator.java b/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorCoordinator.java index b1fa4df..7d952a56 100644 --- a/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorCoordinator.java +++ b/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorCoordinator.java
@@ -93,7 +93,6 @@ private HybridListRenderer mHybridListRenderer; private SurfaceScope mSurfaceScope; private FeedSurfaceScopeDependencyProvider mDependencyProvider; - private byte[] mWebFeedId; private PropertyModel mCreatorModel; private PropertyModelChangeProcessor<PropertyModel, CreatorProfileView, PropertyKey> mCreatorProfileModelChangeProcessor; @@ -109,7 +108,6 @@ private ViewGroup mLayout; private Profile mProfile; private Stream mStream; - private String mTitle; private int mHeaderCount; private EmptyBottomSheetObserver mSheetObserver; @@ -136,7 +134,6 @@ * @param snackbarManager the snackbarManager that is used for the feed. * @param windowAndroid the window needed by the feed * @param profile The Profile of the user. - * @param title The title used by the creator profile. * @param url the url used by the creator profile. * @param creatorWebContents the interface to generate webcontents for the bottomsheet. * @param creatorOpenTab the interface to open urls in a new tab, used by the bottomsheet. @@ -144,16 +141,14 @@ * bottomsheet. */ public CreatorCoordinator(Activity activity, byte[] webFeedId, SnackbarManager snackbarManager, - WindowAndroid windowAndroid, Profile profile, String title, String url, + WindowAndroid windowAndroid, Profile profile, String url, WebContentsCreator creatorWebContents, NewTabCreator creatorOpenTab, UnownedUserDataSupplier<ShareDelegate> bottomsheetShareDelegateSupplier, int entryPoint) { mActivity = activity; - mWebFeedId = webFeedId; mProfile = profile; mSnackbarManager = snackbarManager; mWindowAndroid = windowAndroid; - mTitle = title; mRecyclerView = setUpView(); mCreatorWebContents = creatorWebContents; mCreatorOpenTab = creatorOpenTab; @@ -176,13 +171,11 @@ mLayoutView.addView(mRecyclerView); // Generate Creator Model - mCreatorModel = generateCreatorModel(mWebFeedId, mTitle, url); - - // TODO(crbug.com/1377069): Add a JNI to get the follow status from CreatorBridge instead - if (mWebFeedId != null) { + mCreatorModel = generateCreatorModel(webFeedId, url); + // Attempt to avoid possible extra query if we already have metadata. + if (webFeedId != null) { getWebFeedMetadata(); } - initBottomSheet(); mCreatorProfileModelChangeProcessor = PropertyModelChangeProcessor.create( mCreatorModel, (CreatorProfileView) mProfileView, CreatorProfileViewBinder::bind); @@ -203,15 +196,32 @@ public void queryFeedStream(FeedActionDelegate feedActionDelegate, HelpAndFeedbackLauncher helpAndFeedbackLauncher, Supplier<ShareDelegate> shareDelegateSupplier) { - if (mWebFeedId == null) { + if (mCreatorModel.get(CreatorProperties.WEB_FEED_ID_KEY) == null) { Callback<QueryResult> queryWebFeedIdCallback = result -> { - mWebFeedId = result.webFeedId.getBytes(); mCreatorModel.set(CreatorProperties.WEB_FEED_ID_KEY, result.webFeedId.getBytes()); + mCreatorModel.set(CreatorProperties.TITLE_KEY, result.title); + if (TextUtils.isEmpty(mCreatorModel.get(CreatorProperties.URL_KEY))) { + mCreatorModel.set(CreatorProperties.URL_KEY, result.url); + mCreatorModel.set(CreatorProperties.FORMATTED_URL_KEY, + UrlFormatter.formatUrlForDisplayOmitSchemePathAndTrivialSubdomains( + new GURL(result.url))); + } initFeedStream(feedActionDelegate, helpAndFeedbackLauncher, shareDelegateSupplier); }; - WebFeedBridge.queryWebFeedId( + WebFeedBridge.queryWebFeed( mCreatorModel.get(CreatorProperties.URL_KEY), queryWebFeedIdCallback); - } else { + } else if (TextUtils.isEmpty(mCreatorModel.get(CreatorProperties.TITLE_KEY)) + || TextUtils.isEmpty(mCreatorModel.get(CreatorProperties.URL_KEY))) { + Callback<QueryResult> queryWebFeedIdCallback = result -> { + mCreatorModel.set(CreatorProperties.TITLE_KEY, result.title); + mCreatorModel.set(CreatorProperties.URL_KEY, result.url); + mCreatorModel.set(CreatorProperties.FORMATTED_URL_KEY, + UrlFormatter.formatUrlForDisplayOmitSchemePathAndTrivialSubdomains( + new GURL(result.url))); + }; + WebFeedBridge.queryWebFeedId( + new String(mCreatorModel.get(CreatorProperties.WEB_FEED_ID_KEY)), + queryWebFeedIdCallback); initFeedStream(feedActionDelegate, helpAndFeedbackLauncher, shareDelegateSupplier); } } @@ -232,7 +242,8 @@ helpAndFeedbackLauncher, /* FeedContentFirstLoadWatcher */ this, /* streamsMediator */ new StreamsMediatorImpl(), - new SingleWebFeedParameters(mWebFeedId, mEntryPoint)); + new SingleWebFeedParameters( + mCreatorModel.get(CreatorProperties.WEB_FEED_ID_KEY), mEntryPoint)); if (mEntryPoint == SingleWebFeedEntryPoint.MENU) { mStream.addOnContentChangedListener(new ContentChangedListener()); @@ -306,12 +317,11 @@ return mActivity.getResources().getDimensionPixelSize(R.dimen.content_previews_padding); } - private PropertyModel generateCreatorModel(byte[] webFeedId, String title, String url) { + private PropertyModel generateCreatorModel(byte[] webFeedId, String url) { String formattedUrl = UrlFormatter.formatUrlForDisplayOmitSchemePathAndTrivialSubdomains(new GURL(url)); PropertyModel model = new PropertyModel.Builder(CreatorProperties.ALL_KEYS) .with(CreatorProperties.WEB_FEED_ID_KEY, webFeedId) - .with(CreatorProperties.TITLE_KEY, title) .with(CreatorProperties.URL_KEY, url) .with(CreatorProperties.IS_FOLLOWED_KEY, false) .with(CreatorProperties.IS_TOOLBAR_VISIBLE_KEY, false) @@ -341,7 +351,8 @@ result.visitUrl)); } }; - WebFeedBridge.getWebFeedMetadata(mWebFeedId, metadata_callback); + WebFeedBridge.getWebFeedMetadata( + mCreatorModel.get(CreatorProperties.WEB_FEED_ID_KEY), metadata_callback); } /** @@ -446,7 +457,7 @@ mPeeked = false; mFullyOpened = false; - mTabMediator.requestShowContent(url, mTitle); + mTabMediator.requestShowContent(url, mCreatorModel.get(CreatorProperties.TITLE_KEY)); } @Override
diff --git a/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorCoordinatorTest.java b/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorCoordinatorTest.java index bf8179a..88aad8d 100644 --- a/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorCoordinatorTest.java +++ b/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorCoordinatorTest.java
@@ -94,7 +94,6 @@ private UrlFormatter.Natives mUrlFormatterJniMock; private final byte[] mWebFeedIdDefault = "webFeedId".getBytes(); - private final String mTitleDefault = "Example"; private final String mUrlDefault = JUnitTestGURLs.EXAMPLE_URL; private final String mTestUrl = JUnitTestGURLs.URL_1; private final int mEntryPointDefault = SingleWebFeedEntryPoint.OTHER; @@ -116,24 +115,23 @@ mActivityScenarioRule.getScenario().onActivity(activity -> mActivity = activity); } - private CreatorCoordinator newCreatorCoordinator( - String title, String url, byte[] webFeedId, int entryPoint) { + private CreatorCoordinator newCreatorCoordinator(String url, byte[] webFeedId, int entryPoint) { return new CreatorCoordinator(mActivity, webFeedId, mSnackbarManager, mWindowAndroid, - mProfile, title, url, mCreatorWebContents, mCreatorOpenTab, mShareDelegateSupplier, + mProfile, url, mCreatorWebContents, mCreatorOpenTab, mShareDelegateSupplier, entryPoint); } @Test public void testCreatorCoordinatorConstruction() { - CreatorCoordinator creatorCoordinator = newCreatorCoordinator( - mTitleDefault, mUrlDefault, mWebFeedIdDefault, mEntryPointDefault); + CreatorCoordinator creatorCoordinator = + newCreatorCoordinator(mUrlDefault, mWebFeedIdDefault, mEntryPointDefault); assertNotNull("Could not construct CreatorCoordinator", creatorCoordinator); } @Test public void testActionBar() { - CreatorCoordinator creatorCoordinator = newCreatorCoordinator( - mTitleDefault, mUrlDefault, mWebFeedIdDefault, mEntryPointDefault); + CreatorCoordinator creatorCoordinator = + newCreatorCoordinator(mUrlDefault, mWebFeedIdDefault, mEntryPointDefault); View outerView = creatorCoordinator.getView(); ViewGroup actionBar = (ViewGroup) outerView.findViewById(R.id.action_bar); assertNotNull("Could not retrieve ActionBar", actionBar); @@ -141,8 +139,8 @@ @Test public void testOnChangeListener_noError() { - CreatorCoordinator coordinator = newCreatorCoordinator( - mTitleDefault, mUrlDefault, mWebFeedIdDefault, mEntryPointDefault); + CreatorCoordinator coordinator = + newCreatorCoordinator(mUrlDefault, mWebFeedIdDefault, mEntryPointDefault); coordinator.setStreamForTest(mStreamMock); ContentChangedListener listener = coordinator.new ContentChangedListener(); @@ -158,8 +156,8 @@ @Test public void testOnChangeListener_error() { - CreatorCoordinator coordinator = newCreatorCoordinator( - mTitleDefault, mUrlDefault, mWebFeedIdDefault, mEntryPointDefault); + CreatorCoordinator coordinator = + newCreatorCoordinator(mUrlDefault, mWebFeedIdDefault, mEntryPointDefault); coordinator.setStreamForTest(mStreamMock); ContentChangedListener listener = coordinator.new ContentChangedListener(); @@ -175,35 +173,17 @@ @Test public void testCreatorModel_Creation() { - CreatorCoordinator creatorCoordinator = newCreatorCoordinator( - mTitleDefault, mUrlDefault, mWebFeedIdDefault, mEntryPointDefault); + CreatorCoordinator creatorCoordinator = + newCreatorCoordinator(mUrlDefault, mWebFeedIdDefault, mEntryPointDefault); PropertyModel creatorModel = creatorCoordinator.getCreatorModel(); assertNotNull("Could not retrieve CreatorModel", creatorModel); } @Test - public void testCreatorModel_DefaultTitle() { - String creatorTitle = "creatorTitle"; - CreatorCoordinator creatorCoordinator = newCreatorCoordinator( - creatorTitle, mUrlDefault, mWebFeedIdDefault, mEntryPointDefault); - PropertyModel creatorModel = creatorCoordinator.getCreatorModel(); - String modelTitle = creatorModel.get(CreatorProperties.TITLE_KEY); - assertEquals(creatorTitle, modelTitle); - - View creatorProfileView = creatorCoordinator.getProfileView(); - TextView profileTitleView = creatorProfileView.findViewById(R.id.creator_name); - assertEquals(creatorTitle, profileTitleView.getText()); - - View creatorView = creatorCoordinator.getView(); - TextView toolbarTitleView = creatorView.findViewById(R.id.creator_title_toolbar); - assertEquals(creatorTitle, toolbarTitleView.getText()); - } - - @Test public void testCreatorModel_DefaultUrl() { String creatorUrl = mTestUrl; - CreatorCoordinator creatorCoordinator = newCreatorCoordinator( - mTitleDefault, creatorUrl, mWebFeedIdDefault, mEntryPointDefault); + CreatorCoordinator creatorCoordinator = + newCreatorCoordinator(creatorUrl, mWebFeedIdDefault, mEntryPointDefault); PropertyModel creatorModel = creatorCoordinator.getCreatorModel(); String modelUrl = creatorModel.get(CreatorProperties.URL_KEY); assertEquals(creatorUrl, modelUrl); @@ -216,8 +196,8 @@ @Test public void testCreatorModel_DefaultWebFeedId() { byte[] creatorWebFeedId = "creatorWebFeedId".getBytes(); - CreatorCoordinator creatorCoordinator = newCreatorCoordinator( - mTitleDefault, mUrlDefault, creatorWebFeedId, mEntryPointDefault); + CreatorCoordinator creatorCoordinator = + newCreatorCoordinator(mUrlDefault, creatorWebFeedId, mEntryPointDefault); PropertyModel creatorModel = creatorCoordinator.getCreatorModel(); byte[] modelWebFeedId = creatorModel.get(CreatorProperties.WEB_FEED_ID_KEY); assertEquals(creatorWebFeedId, modelWebFeedId); @@ -225,8 +205,8 @@ @Test public void testCreatorModel_NewTitle() { - CreatorCoordinator creatorCoordinator = newCreatorCoordinator( - mTitleDefault, mUrlDefault, mWebFeedIdDefault, mEntryPointDefault); + CreatorCoordinator creatorCoordinator = + newCreatorCoordinator(mUrlDefault, mWebFeedIdDefault, mEntryPointDefault); String newTitle = "creatorTitle 2.0"; PropertyModel creatorModel = creatorCoordinator.getCreatorModel(); creatorModel.set(CreatorProperties.TITLE_KEY, newTitle); @@ -244,8 +224,8 @@ @Test public void testCreatorModel_NewUrl() { - CreatorCoordinator creatorCoordinator = newCreatorCoordinator( - mTitleDefault, mUrlDefault, mWebFeedIdDefault, mEntryPointDefault); + CreatorCoordinator creatorCoordinator = + newCreatorCoordinator(mUrlDefault, mWebFeedIdDefault, mEntryPointDefault); String newUrl = mTestUrl; PropertyModel creatorModel = creatorCoordinator.getCreatorModel(); creatorModel.set(CreatorProperties.URL_KEY, newUrl); @@ -259,8 +239,8 @@ @Test public void testCreatorModel_ToolbarVisibility() { - CreatorCoordinator creatorCoordinator = newCreatorCoordinator( - mTitleDefault, mUrlDefault, mWebFeedIdDefault, mEntryPointDefault); + CreatorCoordinator creatorCoordinator = + newCreatorCoordinator(mUrlDefault, mWebFeedIdDefault, mEntryPointDefault); PropertyModel creatorModel = creatorCoordinator.getCreatorModel(); View creatorView = creatorCoordinator.getView(); FrameLayout mButtonsContainer = creatorView.findViewById(R.id.creator_all_buttons_toolbar); @@ -272,8 +252,8 @@ @Test public void testCreatorModel_IsFollowedStatus() { - CreatorCoordinator creatorCoordinator = newCreatorCoordinator( - mTitleDefault, mUrlDefault, mWebFeedIdDefault, mEntryPointDefault); + CreatorCoordinator creatorCoordinator = + newCreatorCoordinator(mUrlDefault, mWebFeedIdDefault, mEntryPointDefault); PropertyModel creatorModel = creatorCoordinator.getCreatorModel(); View creatorProfileView = creatorCoordinator.getProfileView(); ButtonCompat followButton = creatorProfileView.findViewById(R.id.creator_follow_button);
diff --git a/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorMediatorTest.java b/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorMediatorTest.java index 10fbcfb5..e64c5dc 100644 --- a/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorMediatorTest.java +++ b/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorMediatorTest.java
@@ -95,7 +95,6 @@ public ActivityScenarioRule<TestActivity> mActivityScenarioRule = new ActivityScenarioRule<>(TestActivity.class); - private final String mTitle = "Example"; private final String mUrl = JUnitTestGURLs.EXAMPLE_URL; private final byte[] mWebFeedId = "webFeedId".getBytes(); private CreatorCoordinator mCreatorCoordinator; @@ -119,7 +118,7 @@ mActivityScenarioRule.getScenario().onActivity(activity -> mActivity = activity); mCreatorCoordinator = new CreatorCoordinator(mActivity, mWebFeedId, mSnackbarManager, - mWindowAndroid, mProfile, mTitle, mUrl, mCreatorWebContents, mCreatorOpenTab, + mWindowAndroid, mProfile, mUrl, mCreatorWebContents, mCreatorOpenTab, mShareDelegateSupplier, SingleWebFeedEntryPoint.OTHER); mCreatorModel = mCreatorCoordinator.getCreatorModel();
diff --git a/chrome/browser/downgrade/downgrade_manager.cc b/chrome/browser/downgrade/downgrade_manager.cc index 576b00d..0de94fa 100644 --- a/chrome/browser/downgrade/downgrade_manager.cc +++ b/chrome/browser/downgrade/downgrade_manager.cc
@@ -235,8 +235,7 @@ DCHECK(!user_data_dir.empty()); DCHECK_NE(type_, Type::kAdministrativeWipe); const base::StringPiece version(PRODUCT_VERSION); - base::WriteFile(GetLastVersionFile(user_data_dir), version.data(), - version.size()); + base::WriteFile(GetLastVersionFile(user_data_dir), version); } void DowngradeManager::DeleteMovedUserDataSoon(
diff --git a/chrome/browser/extensions/api/enterprise_hardware_platform/enterprise_hardware_platform_api_unittest.cc b/chrome/browser/extensions/api/enterprise_hardware_platform/enterprise_hardware_platform_api_unittest.cc index c931e2b..39a9da6 100644 --- a/chrome/browser/extensions/api/enterprise_hardware_platform/enterprise_hardware_platform_api_unittest.cc +++ b/chrome/browser/extensions/api/enterprise_hardware_platform/enterprise_hardware_platform_api_unittest.cc
@@ -66,19 +66,17 @@ browser_context()); ASSERT_TRUE(result); ASSERT_TRUE(result->is_dict()); - ASSERT_EQ(result->DictSize(), 2u); + const base::Value::Dict& result_dict = result->GetDict(); + ASSERT_EQ(result_dict.size(), 2u); - const base::Value* val = - result->FindKeyOfType("manufacturer", base::Value::Type::STRING); - ASSERT_TRUE(val); - const std::string& manufacturer = val->GetString(); + const std::string* manufacturer = result_dict.FindString("manufacturer"); + ASSERT_TRUE(manufacturer); - val = result->FindKeyOfType("model", base::Value::Type::STRING); - ASSERT_TRUE(val); - const std::string& model = val->GetString(); + const std::string* model = result_dict.FindString("model"); + ASSERT_TRUE(model); - EXPECT_FALSE(manufacturer.empty()); - EXPECT_FALSE(model.empty()); + EXPECT_FALSE(manufacturer->empty()); + EXPECT_FALSE(model->empty()); } TEST_F(EnterpriseHardwarePlatformAPITest,
diff --git a/chrome/browser/extensions/api/omnibox/omnibox_api_interactive_test.cc b/chrome/browser/extensions/api/omnibox/omnibox_api_interactive_test.cc index 6edac894..682ba13 100644 --- a/chrome/browser/extensions/api/omnibox/omnibox_api_interactive_test.cc +++ b/chrome/browser/extensions/api/omnibox/omnibox_api_interactive_test.cc
@@ -315,7 +315,7 @@ AutocompleteInput input(input_string, metrics::OmniboxEventProto::NTP, ChromeAutocompleteSchemeClassifier(profile())); autocomplete_controller->Start(input); - omnibox_view->model()->AcceptInput(disposition); + omnibox_view->model()->OpenSelection(base::TimeTicks(), disposition); WaitForAutocompleteDone(browser()); }; @@ -426,14 +426,17 @@ metrics::OmniboxEventProto::NTP, ChromeAutocompleteSchemeClassifier(profile())); GetAutocompleteController()->Start(input); - GetLocationBar(browser())->AcceptInput(); + GetLocationBar(browser())->GetOmniboxView()->model()->OpenSelection(); } { AutocompleteInput input( u"alpha word incognito", metrics::OmniboxEventProto::NTP, ChromeAutocompleteSchemeClassifier(incognito_profile)); incognito_controller->Start(input); - GetLocationBar(incognito_browser)->AcceptInput(); + GetLocationBar(incognito_browser) + ->GetOmniboxView() + ->model() + ->OpenSelection(); } EXPECT_TRUE(on_the_record_listener.WaitUntilSatisfied()); @@ -478,7 +481,7 @@ AutocompleteInput input(u"kw command", metrics::OmniboxEventProto::NTP, ChromeAutocompleteSchemeClassifier(profile())); autocomplete_controller->Start(input); - location_bar->AcceptInput(); + location_bar->GetOmniboxView()->model()->OpenSelection(); WaitForAutocompleteDone(browser()); EXPECT_TRUE(autocomplete_controller->done()); // This checks that the keyword provider (via javascript)
diff --git a/chrome/browser/extensions/api/tab_groups/tab_groups_api_unittest.cc b/chrome/browser/extensions/api/tab_groups/tab_groups_api_unittest.cc index 614e098..6d945fa 100644 --- a/chrome/browser/extensions/api/tab_groups/tab_groups_api_unittest.cc +++ b/chrome/browser/extensions/api/tab_groups/tab_groups_api_unittest.cc
@@ -237,9 +237,8 @@ const base::Value& group_info = groups_list[0]; ASSERT_TRUE(group_info.is_dict()); - EXPECT_EQ( - tab_groups_util::GetGroupId(group1), - group_info.FindKeyOfType("id", base::Value::Type::INTEGER)->GetInt()); + EXPECT_EQ(tab_groups_util::GetGroupId(group1), + *group_info.GetDict().FindInt("id")); } // Test that querying groups by color returns the correct groups. @@ -275,9 +274,8 @@ const base::Value& group_info = groups_list[0]; ASSERT_EQ(base::Value::Type::DICT, group_info.type()); - EXPECT_EQ( - tab_groups_util::GetGroupId(group3), - group_info.FindKeyOfType("id", base::Value::Type::INTEGER)->GetInt()); + EXPECT_EQ(tab_groups_util::GetGroupId(group3), + *group_info.GetDict().FindInt("id")); } // Test that getting a group returns the correct metadata.
diff --git a/chrome/browser/extensions/extension_action_runner_browsertest.cc b/chrome/browser/extensions/extension_action_runner_browsertest.cc index 2e7c453c..d948c13f 100644 --- a/chrome/browser/extensions/extension_action_runner_browsertest.cc +++ b/chrome/browser/extensions/extension_action_runner_browsertest.cc
@@ -742,8 +742,8 @@ // is either 'on all sites' or 'on site'). Note that we don't check if extension // `WantsToRun` because on user-restricted sites, actions are blocked rather // than withheld. -// TODO(crbug.com/1363781): Flaky on Win 7 and Mac 12. -#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) +// TODO(crbug.com/1363781): Flaky on Mac 12. +#if BUILDFLAG(IS_MAC) #define MAYBE_HandleUserSiteSettingModified_ExtensionHasAccess \ DISABLED_HandleUserSiteSettingModified_ExtensionHasAccess #else @@ -866,8 +866,8 @@ // is either 'on all sites' or 'on site'). Note that we don't check if extension // `WantsToRun` because on user-restricted sites, actions are blocked rather // than withheld. -// TODO(crbug.com/1363781): Flaky on Win 7 and Mac 12. -#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) +// TODO(crbug.com/1363781): Flaky on Mac 12. +#if BUILDFLAG(IS_MAC) #define MAYBE_HandleUserSiteSettingModified_ExtensionHasAccess \ DISABLED_HandleUserSiteSettingModified_ExtensionHasAccess #else
diff --git a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/CreatorIntentConstants.java b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/CreatorIntentConstants.java index ccfa49c..fbfedf5 100644 --- a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/CreatorIntentConstants.java +++ b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/CreatorIntentConstants.java
@@ -9,7 +9,6 @@ */ public final class CreatorIntentConstants { public static final String CREATOR_WEB_FEED_ID = "CREATOR_WEB_FEED_ID"; - public static final String CREATOR_TITLE = "CREATOR_TITLE"; public static final String CREATOR_URL = "CREATOR_URL"; public static final String CREATOR_ENTRY_POINT = "CREATOR_ENTRY_POINT";
diff --git a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedBridge.java b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedBridge.java index 4f91d22..d1b35749 100644 --- a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedBridge.java +++ b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedBridge.java
@@ -112,11 +112,20 @@ * @param url The URL for which the status is being requested. * @param callback The callback to receive the Web Feed metadata, or null if it is not found. */ - public static void queryWebFeedId(String url, Callback<QueryResult> callback) { + public static void queryWebFeed(String url, Callback<QueryResult> callback) { WebFeedBridgeJni.get().queryWebFeed(url, callback); } /** + * Returns the Web Feed id for the web feed associated with this page. + * @param url The URL for which the status is being requested. + * @param callback The callback to receive the Web Feed metadata, or null if it is not found. + */ + public static void queryWebFeedId(String id, Callback<QueryResult> callback) { + WebFeedBridgeJni.get().queryWebFeedId(id, callback); + } + + /** * Returns Web Feed metadata respective to the provided identifier. The callback will receive * `null` if no matching recommended or followed Web Feed is found. * @param webFeedId The idenfitier of the Web Feed. @@ -189,11 +198,15 @@ /** Container for results from an QueryWebFeed request. */ public static class QueryResult { @CalledByNative("QueryResult") - public QueryResult(String webFeedId) { + public QueryResult(String webFeedId, String title, String url) { this.webFeedId = webFeedId; + this.title = title; + this.url = url; } // Result of the operation. public final String webFeedId; + public final String title; + public final String url; } /** @@ -290,5 +303,6 @@ void getRecentVisitCountsToHost(GURL url, Callback<int[]> callback); void incrementFollowedFromWebPageMenuCount(); void queryWebFeed(String url, Callback<QueryResult> callback); + void queryWebFeedId(String id, Callback<QueryResult> callback); } }
diff --git a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedMainMenuItem.java b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedMainMenuItem.java index 476cf39..a583bdc7 100644 --- a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedMainMenuItem.java +++ b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedMainMenuItem.java
@@ -369,7 +369,6 @@ intent.putExtra( CreatorIntentConstants.CREATOR_WEB_FEED_ID, mRecommendedWebFeedName); } - intent.putExtra(CreatorIntentConstants.CREATOR_TITLE, mTitle); intent.putExtra(CreatorIntentConstants.CREATOR_URL, mUrl.getSpec()); intent.putExtra( CreatorIntentConstants.CREATOR_ENTRY_POINT, SingleWebFeedEntryPoint.MENU);
diff --git a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedMainMenuItemTest.java b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedMainMenuItemTest.java index a79da14..579b144 100644 --- a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedMainMenuItemTest.java +++ b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedMainMenuItemTest.java
@@ -215,9 +215,7 @@ verify(mContext).startActivity(mIntentCaptor.capture()); Intent intent = mIntentCaptor.getValue(); assertNotNull(intent); - assertEquals(3, intent.getExtras().size()); - assertTrue(intent.hasExtra(CreatorIntentConstants.CREATOR_TITLE)); - assertNotNull(intent.getExtras().getString(CreatorIntentConstants.CREATOR_TITLE)); + assertEquals(2, intent.getExtras().size()); assertTrue(intent.hasExtra(CreatorIntentConstants.CREATOR_URL)); assertNotNull(intent.getExtras().getString(CreatorIntentConstants.CREATOR_URL)); assertTrue(intent.hasExtra(CreatorIntentConstants.CREATOR_ENTRY_POINT));
diff --git a/chrome/browser/feed/android/web_feed_bridge.cc b/chrome/browser/feed/android/web_feed_bridge.cc index 95327a6..05b0249 100644 --- a/chrome/browser/feed/android/web_feed_bridge.cc +++ b/chrome/browser/feed/android/web_feed_bridge.cc
@@ -137,7 +137,9 @@ JNIEnv* env, const WebFeedSubscriptions::QueryWebFeedResult& result) { return Java_QueryResult_Constructor( - env, base::android::ConvertUTF8ToJavaString(env, result.web_feed_id)); + env, base::android::ConvertUTF8ToJavaString(env, result.web_feed_id), + base::android::ConvertUTF8ToJavaString(env, result.title), + base::android::ConvertUTF8ToJavaString(env, result.url)); } base::android::ScopedJavaLocalRef<jobject> ToJava( @@ -386,4 +388,19 @@ GURL(base::android::ConvertJavaStringToUTF8(env, url)), std::move(callback)); } + +static void JNI_WebFeedBridge_QueryWebFeedId( + JNIEnv* env, + const base::android::JavaParamRef<jstring>& id, + const base::android::JavaParamRef<jobject>& j_callback) { + base::OnceCallback<void(WebFeedSubscriptions::QueryWebFeedResult)> callback = + AdaptQueryWebFeedResultCallback(j_callback); + WebFeedSubscriptions* subscriptions = GetSubscriptions(); + if (!subscriptions) { + std::move(callback).Run({}); + return; + } + subscriptions->QueryWebFeedId(base::android::ConvertJavaStringToUTF8(env, id), + std::move(callback)); +} } // namespace feed
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index d8aaab5..1308ffc 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -142,6 +142,11 @@ "expiry_milestone": -1 }, { + "name": "ambient-mode-managed-screensaver-enabled", + "owners": [ "eariassoto", "fahadmansoor", "ghostbusters@google.com" ], + "expiry_milestone": 118 + }, + { "name": "android-force-app-language-prompt", "owners": [ "perrier", "chrome-language@google.com" ], "expiry_milestone": 115 @@ -169,7 +174,7 @@ { "name": "apn-revamp", "owners": [ "gordonseto@google.com", "cros-connectivity@google.com" ], - "expiry_milestone": 113 + "expiry_milestone": 128 }, { "name": "app-deduplication-service-fondue", @@ -338,6 +343,11 @@ "expiry_milestone": 122 }, { + "name": "ash-capture-mode-gif-recording", + "owners": [ "afakhry", "gzadina" ], + "expiry_milestone": 123 + }, + { "name": "ash-debug-shortcuts", "owners": [ "//ash/OWNERS" ], // Used by developers for debugging and to dump extra information to logs @@ -1082,16 +1092,6 @@ "expiry_milestone": 115 }, { - "name": "closed-tab-cache", - "owners": [ - "altimin@chromium.org", - "sky@chromium.org", - "sreejakshetty@chromium.org", - "tobias.soppa@code.berlin" - ], - "expiry_milestone": 110 - }, - { "name": "cloud-ap-auth", "owners": [ "igorruvinov", "zmin" ], "expiry_milestone": 120 @@ -1858,6 +1858,11 @@ "expiry_milestone": 120 }, { + "name": "enable-bookmarks-account-storage", + "owners": [ "jlebel", "bsazonov", "chrome-signin-team" ], + "expiry_milestone": 118 + }, + { "name": "enable-cardboard", "owners": [ "alcooper", "chrome-xr-eng@google.com"], "expiry_milestone": 120 @@ -3282,11 +3287,6 @@ "expiry_milestone": 115 }, { - "name": "enable-user-cloud-signin-restriction-policy", - "owners": [ "ydago" ], - "expiry_milestone": 105 - }, - { "name": "enable-user-policy", "owners": [ "vincb" ], "expiry_milestone": 130 @@ -4018,7 +4018,7 @@ { "name": "full-user-agent", "owners": [ "victortan", "abeyad"], - "expiry_milestone": 113 + "expiry_milestone": 115 }, { "name": "fullscreen-promos-manager", @@ -4779,7 +4779,7 @@ { "name": "messages-for-android-infrastructure", "owners": [ "lazzzis", "aishwaryarj" ], - "expiry_milestone": 112 + "expiry_milestone": 120 }, { "name": "messages-for-android-offer-notification", @@ -4799,7 +4799,7 @@ { "name": "messages-for-android-pwa-install", "owners": [ "lazzzis", "aishwaryarj" ], - "expiry_milestone": 112 + "expiry_milestone": 120 }, { "name": "messages-for-android-save-card", @@ -5028,7 +5028,7 @@ { "name": "ntp-modules-first-run-experience", "owners": [ "mahmadi", "pauladedeji", "tiborg" ], - "expiry_milestone": 111 + "expiry_milestone": 115 }, { "name": "ntp-modules-redesigned", @@ -5838,7 +5838,7 @@ "johnidel", "jkarlin", "pauljensen"], - "expiry_milestone": 112 + "expiry_milestone": 116 }, { "name": "privacy-sandbox-settings-4", @@ -6075,26 +6075,11 @@ "expiry_milestone": 95 }, { - "name": "reduce-user-agent", - "owners": [ "aarontag", "miketaylr"], - "expiry_milestone": 113 - }, - { "name": "reduce-user-agent-android-version-device-model", "owners": [ "miketaylr", "victortan"], "expiry_milestone": 116 }, { - "name": "reduce-user-agent-minor-version", - "owners": [ "abeyad", "victortan"], - "expiry_milestone": 113 - }, - { - "name": "reduce-user-agent-platform-oscpu", - "owners": [ "miketaylr", "victortan"], - "expiry_milestone": 113 - }, - { "name": "reengagement-notification", "owners": [ "dtrainor", "xingliu" ], "expiry_milestone": 90 @@ -6110,11 +6095,6 @@ "expiry_milestone": 110 }, { - "name": "related-searches-ui", - "owners": [ "gangwu", "related-searches-vteam@google.com" ], - "expiry_milestone": 110 - }, - { "name": "release-notes-notification-all-channels", "owners": [ "//ash/webui/help_app_ui/OWNERS" ], // This is required by test teams to verify functionality on dev/beta @@ -7262,6 +7242,11 @@ "expiry_milestone": 122 }, { + "name": "web-feed-feedback-reroute", + "owners": ["zekunjiang", "tinazwang", "chrome-with-friends@google.com"], + "expiry_milestone": 122 + }, + { "name": "web-feed-ios", "owners": [ "adamta", "sczs", "tinazwang" ], "expiry_milestone": 122 @@ -7385,7 +7370,7 @@ { "name": "wifi-connect-mac-address-randomization", "owners": [ "jsiuda", "chromeos-wifi-team" ], - "expiry_milestone": 108 + "expiry_milestone": 130 }, { "name": "win-10-tab-search-caption-button",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 87f076f..47b9abb 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -693,12 +693,6 @@ const char kChromeRefresh2023Name[] = "Chrome Refresh 2023"; const char kChromeRefresh2023Description[] = "Refresh of Chrome Desktop UI"; -const char kClosedTabCacheName[] = "Closed Tab Cache"; -const char kClosedTabCacheDescription[] = - "Enables closed tab cache to instantaneously restore recently closed tabs. " - "NOTE: This feature is highly experimental and will lead to various " - "breakages, enable at your own risk."; - const char kCommerceHintAndroidName[] = "Commerce Hint Android"; const char kCommerceHintAndroidDescription[] = "Enables commerce hint detection on Android."; @@ -2638,12 +2632,6 @@ "Reduce the amount of information available in the Accept-Language request " "header. See https://github.com/Tanych/accept-language for more info."; -const char kReduceUserAgentName[] = "Reduce User-Agent request header"; -const char kReduceUserAgentDescription[] = - "Reduce (formerly, \"freeze\") the amount of information available in " - "the User-Agent request header. " - "See https://www.chromium.org/updates/ua-reduction for more info."; - const char kRestrictGamepadAccessName[] = "Restrict gamepad access"; const char kRestrictGamepadAccessDescription[] = "Enables Permissions Policy and Secure Context restrictions on the Gamepad " @@ -3401,20 +3389,6 @@ const char kDurableClientHintsCacheDescription[] = "Persist the client hints cache beyond browser restarts."; -const char kReduceUserAgentMinorVersionName[] = - "Reduce the minor version in the User-Agent string"; -const char kReduceUserAgentMinorVersionDescription[] = - "Reduce the minor, build, and patch versions in the User-Agent string. " - "The Chrome version in the User-Agent string will be reported as " - "Chrome/<major_version>.0.0.0."; - -const char kReduceUserAgentPlatformOsCpuName[] = - "Reduce the plaftform and oscpu in the desktop User-Agent string"; -const char kReduceUserAgentPlatformOsCpuDescription[] = - "Reduce the plaftform and oscpu in the desktop User-Agent string. " - "The platform and oscpu in the User-Agent string will be reported as " - "<unifiedPlatform>"; - const char kSkipServiceWorkerFetchHandlerName[] = "Skip Service Worker Fetch Handler if skippable"; const char kSkipServiceWorkerFetchHandlerDescription[] = @@ -3930,13 +3904,6 @@ "Enables requesting related searches suggestions. These will be requested " "but not shown unless the UI flag is also enabled."; -const char kRelatedSearchesUiName[] = - "Forces showing of the Related Searches UI on Android"; -const char kRelatedSearchesUiDescription[] = - "Forces the Related Searches UI and underlying requests to be enabled " - "regardless of whether they are safe or useful. This requires the Related " - "Searches feature flag to also be enabled."; - const char kRequestDesktopSiteAdditionsName[] = "Secondary settings for request desktop site on Android."; const char kRequestDesktopSiteAdditionsDescription[] = @@ -4262,12 +4229,6 @@ "Have Read Anything use a local machine learning model for web page" "distillation."; -const char kEnableUserCloudSigninRestrictionPolicyName[] = - "Cloud User level Signin Restrictions Policy"; -const char kEnableUserCloudSigninRestrictionPolicyDescription[] = - "Enable the ManagedAccountsSigninRestrictions policy to be set at a cloud " - "user level"; - const char kEnableWebHidOnExtensionServiceWorkerName[] = "Enable WebHID on extension service workers"; const char kEnableWebHidOnExtensionServiceWorkerDescription[] = @@ -4718,6 +4679,12 @@ "Feature to enable the Jelly design in Personalization App. Requires " "jelly-colors flag to be enabled."; +const char kAmbientModeManagedScreensaverName[] = + "Enables the managed screensaver"; +const char kAmbientModeManagedScreensaverDescription[] = + "Enables a managed screensaver that is controlled by admin through " + "enterprise settings."; + const char kAmbientModeThrottleAnimationName[] = "Throttle the frame rate of Lottie animations in ambient mode"; const char kAmbientModeThrottleAnimationDescription[] = @@ -4958,6 +4925,11 @@ "Enables the ability to show clicks and keys during video recordings to " "enhance demo experience."; +const char kCaptureModeGifRecordingName[] = + "Enable GIF recording in screen capture"; +const char kCaptureModeGifRecordingDescription[] = + "Enables the ability to record the screen into animated GIFs"; + const char kCalendarModelDebugModeName[] = "Monthly Calendar Model Debug Mode"; const char kCalendarModelDebugModeDescription[] = "Debug mode for Monthly Calendar Model. This helps a lot in diagnosing any "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 962494e..380cd4b3 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -395,9 +395,6 @@ extern const char kClientStorageAccessContextAuditingName[]; extern const char kClientStorageAccessContextAuditingDescription[]; -extern const char kClosedTabCacheName[]; -extern const char kClosedTabCacheDescription[]; - extern const char kClearCrossSiteCrossBrowsingContextGroupWindowNameName[]; extern const char kClearCrossSiteCrossBrowsingContextGroupWindowNameDescription[]; @@ -1482,9 +1479,6 @@ extern const char kRecordWebAppDebugInfoName[]; extern const char kRecordWebAppDebugInfoDescription[]; -extern const char kReduceUserAgentName[]; -extern const char kReduceUserAgentDescription[]; - extern const char kRestrictGamepadAccessName[]; extern const char kRestrictGamepadAccessDescription[]; @@ -1948,12 +1942,6 @@ extern const char kReduceAcceptLanguageName[]; extern const char kReduceAcceptLanguageDescription[]; -extern const char kReduceUserAgentMinorVersionName[]; -extern const char kReduceUserAgentMinorVersionDescription[]; - -extern const char kReduceUserAgentPlatformOsCpuName[]; -extern const char kReduceUserAgentPlatformOsCpuDescription[]; - extern const char kSkipServiceWorkerFetchHandlerName[]; extern const char kSkipServiceWorkerFetchHandlerDescription[]; @@ -2251,9 +2239,6 @@ extern const char kRelatedSearchesName[]; extern const char kRelatedSearchesDescription[]; -extern const char kRelatedSearchesUiName[]; -extern const char kRelatedSearchesUiDescription[]; - extern const char kRequestDesktopSiteAdditionsName[]; extern const char kRequestDesktopSiteAdditionsDescription[]; @@ -2436,9 +2421,6 @@ extern const char kReadAnythingWithScreen2xName[]; extern const char kReadAnythingWithScreen2xDescription[]; -extern const char kEnableUserCloudSigninRestrictionPolicyName[]; -extern const char kEnableUserCloudSigninRestrictionPolicyDescription[]; - extern const char kEnableWebHidOnExtensionServiceWorkerName[]; extern const char kEnableWebHidOnExtensionServiceWorkerDescription[]; @@ -2707,6 +2689,9 @@ extern const char kAlwaysEnableHdcpType0[]; extern const char kAlwaysEnableHdcpType1[]; +extern const char kAmbientModeManagedScreensaverName[]; +extern const char kAmbientModeManagedScreensaverDescription[]; + extern const char kAmbientModeThrottleAnimationName[]; extern const char kAmbientModeThrottleAnimationDescription[]; @@ -2845,6 +2830,9 @@ extern const char kCaptureModeDemoToolsName[]; extern const char kCaptureModeDemoToolsDescription[]; +extern const char kCaptureModeGifRecordingName[]; +extern const char kCaptureModeGifRecordingDescription[]; + extern const char kDesks16Name[]; extern const char kDesks16Description[];
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc index afee33a..8a9a5bb 100644 --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -224,6 +224,7 @@ &kContextualSearchSuppressShortView, &kContextualSearchThinWebViewImplementation, &kDeferKeepScreenOnDuringGesture, + &kDeferNotifyInMotion, &kExperimentsForAgsa, &kExploreSites, &kFocusOmniboxInIncognitoTabIntents, @@ -257,7 +258,6 @@ &kRecordSuppressionMetrics, &kReengagementNotification, &kRelatedSearches, - &kRelatedSearchesUi, &kReportParentalControlSitesChild, &kRequestDesktopSiteDefaults, &kRequestDesktopSiteDefaultsControl, @@ -705,6 +705,10 @@ "DeferKeepScreenOnDuringGesture", base::FEATURE_DISABLED_BY_DEFAULT); +BASE_FEATURE(kDeferNotifyInMotion, + "DeferNotifyInMotion", + base::FEATURE_DISABLED_BY_DEFAULT); + BASE_FEATURE(kDownloadAutoResumptionThrottling, "DownloadAutoResumptionThrottling", base::FEATURE_ENABLED_BY_DEFAULT); @@ -829,10 +833,6 @@ "RelatedSearches", base::FEATURE_ENABLED_BY_DEFAULT); -BASE_FEATURE(kRelatedSearchesUi, - "RelatedSearchesUi", - base::FEATURE_ENABLED_BY_DEFAULT); - BASE_FEATURE(kReportParentalControlSitesChild, "ReportParentalControlSitesChild", base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser/flags/android/chrome_feature_list.h index 53d33e8..92e01a54 100644 --- a/chrome/browser/flags/android/chrome_feature_list.h +++ b/chrome/browser/flags/android/chrome_feature_list.h
@@ -82,6 +82,7 @@ BASE_DECLARE_FEATURE(kContextualSearchSuppressShortView); BASE_DECLARE_FEATURE(kContextualSearchThinWebViewImplementation); BASE_DECLARE_FEATURE(kDeferKeepScreenOnDuringGesture); +BASE_DECLARE_FEATURE(kDeferNotifyInMotion); BASE_DECLARE_FEATURE(kDontPrefetchLibraries); BASE_DECLARE_FEATURE(kDownloadAutoResumptionThrottling); BASE_DECLARE_FEATURE(kDownloadHomeForExternalApp); @@ -121,7 +122,6 @@ BASE_DECLARE_FEATURE(kReaderModeInCCT); BASE_DECLARE_FEATURE(kRecordSuppressionMetrics); BASE_DECLARE_FEATURE(kRelatedSearches); -BASE_DECLARE_FEATURE(kRelatedSearchesUi); BASE_DECLARE_FEATURE(kReportParentalControlSitesChild); BASE_DECLARE_FEATURE(kRequestDesktopSiteDefaults); BASE_DECLARE_FEATURE(kRequestDesktopSiteDefaultsControl);
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java index 538c3c6..be2470d 100644 --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
@@ -291,6 +291,7 @@ "DarkenWebsitesCheckboxInThemesSetting"; public static final String DEFER_KEEP_SCREEN_ON_DURING_GESTURE = "DeferKeepScreenOnDuringGesture"; + public static final String DEFER_NOTIFY_IN_MOTION = "DeferNotifyInMotion"; public static final String DETAILED_LANGUAGE_SETTINGS = "DetailedLanguageSettings"; public static final String DISCO_FEED_ENDPOINT = "DiscoFeedEndpoint"; public static final String DNS_OVER_HTTPS = "DnsOverHttps"; @@ -442,7 +443,6 @@ public static final String RECOVER_FROM_NEVER_SAVE_ANDROID = "RecoverFromNeverSaveAndroid"; public static final String REENGAGEMENT_NOTIFICATION = "ReengagementNotification"; public static final String RELATED_SEARCHES = "RelatedSearches"; - public static final String RELATED_SEARCHES_UI = "RelatedSearchesUi"; public static final String REPORT_PARENTAL_CONTROL_SITES_CHILD = "ReportParentalControlSitesChild"; public static final String REQUEST_DESKTOP_SITE_DEFAULTS = "RequestDesktopSiteDefaults";
diff --git a/chrome/browser/lacros/chrome_browser_main_extra_parts_lacros.cc b/chrome/browser/lacros/chrome_browser_main_extra_parts_lacros.cc index a886e0c8..5eceb62 100644 --- a/chrome/browser/lacros/chrome_browser_main_extra_parts_lacros.cc +++ b/chrome/browser/lacros/chrome_browser_main_extra_parts_lacros.cc
@@ -32,6 +32,7 @@ #include "chrome/browser/lacros/lacros_file_system_provider.h" #include "chrome/browser/lacros/lacros_memory_pressure_evaluator.h" #include "chrome/browser/lacros/launcher_search/search_controller_lacros.h" +#include "chrome/browser/lacros/multitask_menu_nudge_delegate_lacros.h" #include "chrome/browser/lacros/net/network_change_manager_bridge.h" #include "chrome/browser/lacros/screen_orientation_delegate_lacros.h" #include "chrome/browser/lacros/standalone_browser_test_controller.h" @@ -212,6 +213,11 @@ smart_reader_client_ = std::make_unique<smart_reader::SmartReaderClientImpl>(); + + if (chromeos::BrowserParamsProxy::Get()->IsWindowLayoutMenuEnabled()) { + multitask_menu_nudge_delegate_ = + std::make_unique<MultitaskMenuNudgeDelegateLacros>(); + } } void ChromeBrowserMainExtraPartsLacros::PostProfileInit(
diff --git a/chrome/browser/lacros/chrome_browser_main_extra_parts_lacros.h b/chrome/browser/lacros/chrome_browser_main_extra_parts_lacros.h index 8d2cbe87..719e4d5 100644 --- a/chrome/browser/lacros/chrome_browser_main_extra_parts_lacros.h +++ b/chrome/browser/lacros/chrome_browser_main_extra_parts_lacros.h
@@ -34,6 +34,7 @@ class UiMetricRecorderLacros; class VpnExtensionTrackerLacros; class WebAuthnRequestRegistrarLacros; +class MultitaskMenuNudgeDelegateLacros; namespace arc { class ArcIconCacheDelegateProvider; @@ -185,6 +186,10 @@ // Controls sync-related Crosapi clients. SyncCrosapiManagerLacros sync_crosapi_manager_; + + // Handles getting and setting multitask menu nudge related prefs from ash. + std::unique_ptr<MultitaskMenuNudgeDelegateLacros> + multitask_menu_nudge_delegate_; }; #endif // CHROME_BROWSER_LACROS_CHROME_BROWSER_MAIN_EXTRA_PARTS_LACROS_H_
diff --git a/chrome/browser/lacros/desk_template_client_lacros.cc b/chrome/browser/lacros/desk_template_client_lacros.cc index a638ebd..0d2870c 100644 --- a/chrome/browser/lacros/desk_template_client_lacros.cc +++ b/chrome/browser/lacros/desk_template_client_lacros.cc
@@ -61,20 +61,21 @@ return true; } -// Creates a callback for when a favicon image is retrieved which creates a -// standard icon image and then calls `callback` with the standardized image. -base::OnceCallback<void(const favicon_base::FaviconImageResult&)> -CreateFaviconResultCallback( - base::OnceCallback<void(const gfx::ImageSkia&)> callback) { - return base::BindOnce( - [](base::OnceCallback<void(const gfx::ImageSkia&)> image_skia_callback, - const favicon_base::FaviconImageResult& result) { - auto image = result.image.AsImageSkia(); - image.EnsureRepsForSupportedScales(); - std::move(image_skia_callback) - .Run(apps::CreateStandardIconImage(image)); - }, - std::move(callback)); +// Creates a standard icon image via `result`, and then calls `callback` with +// the standardized image. +void ImageResultToImageSkia( + base::OnceCallback<void(const gfx::ImageSkia&)> callback, + const favicon_base::FaviconRawBitmapResult& result) { + if (!result.is_valid()) { + std::move(callback).Run(gfx::ImageSkia()); + return; + } + + auto image = gfx::Image::CreateFrom1xPNGBytes(result.bitmap_data->front(), + result.bitmap_data->size()) + .AsImageSkia(); + image.EnsureRepsForSupportedScales(); + std::move(callback).Run(apps::CreateStandardIconImage(image)); } void AddTabGroupToBrowser(TabStripModel* browser_tab_model, @@ -247,6 +248,9 @@ ProfileManager::GetActiveUserProfile(), ServiceAccessType::EXPLICIT_ACCESS); - favicon_service->GetFaviconImageForPageURL( - url, CreateFaviconResultCallback(std::move(callback)), &task_tracker_); + favicon_service->GetRawFaviconForPageURL( + url, {favicon_base::IconType::kFavicon}, 0, + /*fallback_to_host=*/false, + base::BindOnce(&ImageResultToImageSkia, std::move(callback)), + &task_tracker_); }
diff --git a/chrome/browser/lacros/multitask_menu_nudge_delegate_lacros.cc b/chrome/browser/lacros/multitask_menu_nudge_delegate_lacros.cc new file mode 100644 index 0000000..71e4ded --- /dev/null +++ b/chrome/browser/lacros/multitask_menu_nudge_delegate_lacros.cc
@@ -0,0 +1,122 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/lacros/multitask_menu_nudge_delegate_lacros.h" + +#include "base/barrier_callback.h" +#include "base/json/values_util.h" +#include "chromeos/lacros/lacros_service.h" +#include "multitask_menu_nudge_delegate_lacros.h" + +namespace { + +// If we can't get the pref, run the callback with the max nudge show count +// value so that no nudge gets shown. +// TODO(b/267787811): The callback should instead be updated to provide a +// success parameter. +constexpr int kMaxNudgeShowCount = 3; + +chromeos::LacrosService* GetLacrosService() { + auto* lacros_service = chromeos::LacrosService::Get(); + if (lacros_service && lacros_service->IsAvailable<crosapi::mojom::Prefs>()) { + return lacros_service; + } + return nullptr; +} + +} // namespace + +MultitaskMenuNudgeDelegateLacros::MultitaskMenuNudgeDelegateLacros() = default; + +MultitaskMenuNudgeDelegateLacros::~MultitaskMenuNudgeDelegateLacros() = default; + +int MultitaskMenuNudgeDelegateLacros::GetTabletNudgeYOffset() const { + // Tablet nudge is handled by ash. + NOTREACHED(); + return 0; +} + +void MultitaskMenuNudgeDelegateLacros::GetNudgePreferences( + bool tablet_mode, + GetPreferencesCallback callback) { + // These prefs should be read from ash, as they are also used by frames + // created and maintained in ash. + auto* lacros_service = GetLacrosService(); + if (!lacros_service) { + std::move(callback).Run(/*tablet_mode=*/false, kMaxNudgeShowCount, + base::Time()); + return; + } + + auto barrier = base::BarrierCallback<PrefPair>( + /*num_callbacks=*/2u, /*done_callback=*/base::BindOnce( + &MultitaskMenuNudgeDelegateLacros::OnGotAllPreferences, + weak_ptr_factory_.GetWeakPtr(), std::move(callback))); + + lacros_service->GetRemote<crosapi::mojom::Prefs>()->GetPref( + crosapi::mojom::PrefPath::kMultitaskMenuNudgeClamshellShownCount, + base::BindOnce( + &MultitaskMenuNudgeDelegateLacros::OnGetPreference, + weak_ptr_factory_.GetWeakPtr(), barrier, + crosapi::mojom::PrefPath::kMultitaskMenuNudgeClamshellShownCount)); + lacros_service->GetRemote<crosapi::mojom::Prefs>()->GetPref( + crosapi::mojom::PrefPath::kMultitaskMenuNudgeClamshellLastShown, + base::BindOnce( + &MultitaskMenuNudgeDelegateLacros::OnGetPreference, + weak_ptr_factory_.GetWeakPtr(), barrier, + crosapi::mojom::PrefPath::kMultitaskMenuNudgeClamshellLastShown)); +} + +void MultitaskMenuNudgeDelegateLacros::SetNudgePreferences(bool tablet_mode, + int count, + base::Time time) { + auto* lacros_service = GetLacrosService(); + if (!lacros_service) { + return; + } + + lacros_service->GetRemote<crosapi::mojom::Prefs>()->SetPref( + crosapi::mojom::PrefPath::kMultitaskMenuNudgeClamshellShownCount, + base::Value(count), base::DoNothing()); + lacros_service->GetRemote<crosapi::mojom::Prefs>()->SetPref( + crosapi::mojom::PrefPath::kMultitaskMenuNudgeClamshellLastShown, + base::TimeToValue(time), base::DoNothing()); +} + +void MultitaskMenuNudgeDelegateLacros::OnGetPreference( + base::OnceCallback<void(PrefPair)> callback, + crosapi::mojom::PrefPath pref_path, + absl::optional<base::Value> value) { + // If `value` is empty just pass a default `base::Value`; the other callback + // (`OnGotAllPreferences()`) function will handle it properly. + PrefPair pref_pair{pref_path, value ? std::move(*value) : base::Value()}; + std::move(callback).Run(std::move(pref_pair)); +} + +void MultitaskMenuNudgeDelegateLacros::OnGotAllPreferences( + GetPreferencesCallback callback, + std::vector<PrefPair> pref_values) { + DCHECK_EQ(2u, pref_values.size()); + + // The values in the array could be in any order. Parse them into the + // `shown_count` and `last_shown_time`. + absl::optional<int> shown_count; + absl::optional<base::Time> last_shown_time; + for (const auto& pair : pref_values) { + if (pair.first == + crosapi::mojom::PrefPath::kMultitaskMenuNudgeClamshellShownCount) { + shown_count = pair.second.GetIfInt().value_or(kMaxNudgeShowCount); + } else { + DCHECK_EQ( + pair.first, + crosapi::mojom::PrefPath::kMultitaskMenuNudgeClamshellLastShown); + last_shown_time = base::ValueToTime(pair.second).value_or(base::Time()); + } + } + + DCHECK(shown_count.has_value()); + DCHECK(last_shown_time.has_value()); + std::move(callback).Run(/*tablet_mode=*/false, *shown_count, + *last_shown_time); +}
diff --git a/chrome/browser/lacros/multitask_menu_nudge_delegate_lacros.h b/chrome/browser/lacros/multitask_menu_nudge_delegate_lacros.h new file mode 100644 index 0000000..ded06f37 --- /dev/null +++ b/chrome/browser/lacros/multitask_menu_nudge_delegate_lacros.h
@@ -0,0 +1,55 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_LACROS_MULTITASK_MENU_NUDGE_DELEGATE_LACROS_ +#define CHROME_BROWSER_LACROS_MULTITASK_MENU_NUDGE_DELEGATE_LACROS_ + +#include "base/values.h" +#include "chromeos/crosapi/mojom/prefs.mojom.h" +#include "chromeos/ui/frame/multitask_menu/multitask_menu_nudge_controller.h" + +// Lacros implementation of the nudge controller delegate that lets us get and +// set pref values from the ash active profile via mojo. +class MultitaskMenuNudgeDelegateLacros + : public chromeos::MultitaskMenuNudgeController::Delegate { + public: + using GetPreferencesCallback = + chromeos::MultitaskMenuNudgeController::GetPreferencesCallback; + + static constexpr int kTabletNudgeAdditionalYOffset = 6; + + MultitaskMenuNudgeDelegateLacros(); + MultitaskMenuNudgeDelegateLacros(const MultitaskMenuNudgeDelegateLacros&) = + delete; + MultitaskMenuNudgeDelegateLacros& operator=( + const MultitaskMenuNudgeDelegateLacros&) = delete; + ~MultitaskMenuNudgeDelegateLacros() override; + + // chromeos::MultitaskMenuNudgeController::Delegate: + int GetTabletNudgeYOffset() const override; + void GetNudgePreferences(bool tablet_mode, + GetPreferencesCallback callback) override; + void SetNudgePreferences(bool tablet_mode, + int count, + base::Time time) override; + + private: + using PrefPair = std::pair<crosapi::mojom::PrefPath, base::Value>; + + // Callback ran when we got either pref from the pref service. Runs + // `callback`, which is part of a barrier callback. + void OnGetPreference(base::OnceCallback<void(PrefPair)> callback, + crosapi::mojom::PrefPath pref_path, + absl::optional<base::Value> value); + + // Callback ran when we got both our prefs from the pref service. Parses the + // values and then uses `callback` to send them to the prefs requester. + void OnGotAllPreferences(GetPreferencesCallback callback, + std::vector<PrefPair> pref_values); + + base::WeakPtrFactory<MultitaskMenuNudgeDelegateLacros> weak_ptr_factory_{ + this}; +}; + +#endif // CHROME_BROWSER_LACROS_MULTITASK_MENU_NUDGE_DELEGATE_LACROS_
diff --git a/chrome/browser/lacros/multitask_menu_nudge_delegate_lacros_browsertest.cc b/chrome/browser/lacros/multitask_menu_nudge_delegate_lacros_browsertest.cc new file mode 100644 index 0000000..03b9df8 --- /dev/null +++ b/chrome/browser/lacros/multitask_menu_nudge_delegate_lacros_browsertest.cc
@@ -0,0 +1,55 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/lacros/multitask_menu_nudge_delegate_lacros.h" + +#include "base/json/values_util.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chromeos/crosapi/mojom/prefs.mojom-test-utils.h" +#include "chromeos/crosapi/mojom/prefs.mojom.h" +#include "chromeos/lacros/lacros_service.h" +#include "content/public/test/browser_test.h" + +using MultitaskMenuNudgeDelegateLacrosBrowserTest = InProcessBrowserTest; + +IN_PROC_BROWSER_TEST_F(MultitaskMenuNudgeDelegateLacrosBrowserTest, Basics) { + auto* lacros_service = chromeos::LacrosService::Get(); + ASSERT_TRUE(lacros_service); + ASSERT_TRUE(lacros_service->IsAvailable<crosapi::mojom::Prefs>()); + + crosapi::mojom::PrefsAsyncWaiter async_waiter( + chromeos::LacrosService::Get()->GetRemote<crosapi::mojom::Prefs>().get()); + + absl::optional<base::Value> int_value; + async_waiter.GetPref( + crosapi::mojom::PrefPath::kMultitaskMenuNudgeClamshellShownCount, + &int_value); + + // If the pref cannot be fetched, the ash version may be too old. + if (!int_value.has_value()) { + GTEST_SKIP() << "Skipping as the nudge prefs are not available in the " + "current version of Ash"; + } + + base::Time expected_time = base::Time(); + async_waiter.SetPref( + crosapi::mojom::PrefPath::kMultitaskMenuNudgeClamshellShownCount, + base::Value(2)); + async_waiter.SetPref( + crosapi::mojom::PrefPath::kMultitaskMenuNudgeClamshellLastShown, + base::TimeToValue(expected_time)); + + absl::optional<base::Value> time_value; + async_waiter.GetPref( + crosapi::mojom::PrefPath::kMultitaskMenuNudgeClamshellShownCount, + &int_value); + async_waiter.GetPref( + crosapi::mojom::PrefPath::kMultitaskMenuNudgeClamshellLastShown, + &time_value); + ASSERT_TRUE(int_value.has_value()); + EXPECT_EQ(2, int_value.value()); + + ASSERT_TRUE(time_value.has_value()); + EXPECT_EQ(expected_time, base::ValueToTime(*time_value).value()); +}
diff --git a/chrome/browser/media/webrtc/get_display_media_set_browsertest.cc b/chrome/browser/media/webrtc/get_display_media_set_browsertest.cc index 17153740..a86d804 100644 --- a/chrome/browser/media/webrtc/get_display_media_set_browsertest.cc +++ b/chrome/browser/media/webrtc/get_display_media_set_browsertest.cc
@@ -138,7 +138,7 @@ // Each entry in this comma separated list corresponds to a screen // specification following the format defined in // |ManagedDisplayInfo::CreateFromSpec|. - // The used specficiation simulatoes screens with resolution 800x800 + // The used specification simulates screens with resolution 800x800 // at the host coordinates (screen_index * 800, 0). screens << screen_index * 640 << "+0-640x480,"; }
diff --git a/chrome/browser/metrics/metrics_reporting_state.h b/chrome/browser/metrics/metrics_reporting_state.h index b486801..60aeb036 100644 --- a/chrome/browser/metrics/metrics_reporting_state.h +++ b/chrome/browser/metrics/metrics_reporting_state.h
@@ -16,10 +16,14 @@ // TODO(crbug.com/1296618): Make all call sites pass an appropriate value, and // remove |kUnknown|. Right now, |kUnknown| is used as a placeholder value while // call sites are being migrated. +// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.metrics enum class ChangeMetricsReportingStateCalledFrom { kUnknown, kUiSettings, + // The user opted out of metrics reporting in the First Run Experience. + kUiFirstRun, + // Called from Chrome OS settings change. Chrome OS manages settings // externally and metrics service listens for changes. kCrosMetricsSettingsChange,
diff --git a/chrome/browser/metrics/metrics_reporting_state_browsertest.cc b/chrome/browser/metrics/metrics_reporting_state_browsertest.cc index 345af57b..c350a7a3 100644 --- a/chrome/browser/metrics/metrics_reporting_state_browsertest.cc +++ b/chrome/browser/metrics/metrics_reporting_state_browsertest.cc
@@ -311,6 +311,7 @@ testing::ValuesIn<ChangeMetricsReportingStateCalledFrom>( {ChangeMetricsReportingStateCalledFrom::kUnknown, ChangeMetricsReportingStateCalledFrom::kUiSettings, + ChangeMetricsReportingStateCalledFrom::kUiFirstRun, ChangeMetricsReportingStateCalledFrom::kCrosMetricsSettingsChange})); #if BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/metrics/process_memory_metrics_emitter_unittest.cc b/chrome/browser/metrics/process_memory_metrics_emitter_unittest.cc index 718068c..db0772cb 100644 --- a/chrome/browser/metrics/process_memory_metrics_emitter_unittest.cc +++ b/chrome/browser/metrics/process_memory_metrics_emitter_unittest.cc
@@ -124,9 +124,8 @@ using memory_instrumentation::mojom::VmRegion; return memory_instrumentation::mojom::OSMemDump::New( - resident_set_kb, resident_set_kb /* peak_resident_set_kb */, - true /* is_peak_rss_resettable */, private_footprint_kb, - shared_footprint_kb + resident_set_kb, /*peak_resident_set_kb=*/resident_set_kb, + /*is_peak_rss_resettable=*/true, private_footprint_kb, shared_footprint_kb #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) , private_swap_footprint_kb @@ -134,6 +133,21 @@ ); } +OSMemDumpPtr GetFakeOSMemDump(MetricMap& metrics_mb) { + return GetFakeOSMemDump( + /*resident_set_kb=*/GetResidentValue(metrics_mb) * 1024, + /*private_footprint_kb=*/metrics_mb["PrivateMemoryFootprint"] * 1024, + /*shared_footprint_kb=*/metrics_mb["SharedMemoryFootprint"] * 1024 +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) + // accessing PrivateSwapFootprint on other OSes will + // modify metrics_mb to create the value, which leads + // to expectation failures. + , + /*private_swap_footprint_kb=*/metrics_mb["PrivateSwapFootprint"] * 1024 +#endif + ); +} + constexpr uint64_t kGpuSharedImagesSizeMB = 32; constexpr uint64_t kGpuSkiaGpuResourcesMB = 87; constexpr uint64_t kGpuCommandBufferMB = 240; @@ -155,19 +169,7 @@ kGpuSharedImagesSizeMB * 1024 * 1024); SetAllocatorDumpMetric(pmd, "skia/gpu_resources", "effective_size", kGpuSkiaGpuResourcesMB * 1024 * 1024); - OSMemDumpPtr os_dump = - GetFakeOSMemDump(GetResidentValue(metrics_mb) * 1024, - metrics_mb["PrivateMemoryFootprint"] * 1024, -#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) - // accessing PrivateSwapFootprint on other OSes will - // modify metrics_mb to create the value, which leads to - // expectation failures. - metrics_mb["SharedMemoryFootprint"] * 1024, - metrics_mb["PrivateSwapFootprint"] * 1024 -#else - metrics_mb["SharedMemoryFootprint"] * 1024 -#endif - ); + OSMemDumpPtr os_dump = GetFakeOSMemDump(metrics_mb); pmd->os_dump = std::move(os_dump); global_dump->process_dumps.push_back(std::move(pmd)); } @@ -316,19 +318,7 @@ metrics_mb_or_count["PartitionAlloc.Partitions.ArrayBuffer"] * 1024 * 1024); - OSMemDumpPtr os_dump = - GetFakeOSMemDump(GetResidentValue(metrics_mb_or_count) * 1024, - metrics_mb_or_count["PrivateMemoryFootprint"] * 1024, -#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) - // accessing PrivateSwapFootprint on other OSes will - // modify metrics_mb_or_count to create the value, which - // leads to expectation failures. - metrics_mb_or_count["SharedMemoryFootprint"] * 1024, - metrics_mb_or_count["PrivateSwapFootprint"] * 1024 -#else - metrics_mb_or_count["SharedMemoryFootprint"] * 1024 -#endif - ); + OSMemDumpPtr os_dump = GetFakeOSMemDump(metrics_mb_or_count); pmd->os_dump = std::move(os_dump); pmd->pid = pid; global_dump->process_dumps.push_back(std::move(pmd)); @@ -404,19 +394,7 @@ kGpuSharedImagesSizeMB * 1024 * 1024); SetAllocatorDumpMetric(pmd, "skia/gpu_resources", "effective_size", kGpuSkiaGpuResourcesMB * 1024 * 1024); - OSMemDumpPtr os_dump = - GetFakeOSMemDump(GetResidentValue(metrics_mb) * 1024, - metrics_mb["PrivateMemoryFootprint"] * 1024, -#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) - // accessing PrivateSwapFootprint on other OSes will - // modify metrics_mb to create the value, which leads to - // expectation failures. - metrics_mb["SharedMemoryFootprint"] * 1024, - metrics_mb["PrivateSwapFootprint"] * 1024 -#else - metrics_mb["SharedMemoryFootprint"] * 1024 -#endif - ); + OSMemDumpPtr os_dump = GetFakeOSMemDump(metrics_mb); pmd->os_dump = std::move(os_dump); global_dump->process_dumps.push_back(std::move(pmd)); } @@ -433,26 +411,18 @@ }); } -void PopulateAudioServiceMetrics(GlobalMemoryDumpPtr& global_dump, - MetricMap& metrics_mb) { - ProcessMemoryDumpPtr pmd( - memory_instrumentation::mojom::ProcessMemoryDump::New()); +void PopulateUtilityMetrics(GlobalMemoryDumpPtr& global_dump, + MetricMap& metrics_mb, + const absl::optional<std::string>& service_name) { + auto pmd(memory_instrumentation::mojom::ProcessMemoryDump::New()); pmd->process_type = ProcessType::UTILITY; + if (service_name.has_value()) { + pmd->service_name = service_name.value(); + } + SetAllocatorDumpMetric(pmd, "malloc", "effective_size", metrics_mb["Malloc"] * 1024 * 1024); - OSMemDumpPtr os_dump = - GetFakeOSMemDump(GetResidentValue(metrics_mb) * 1024, - metrics_mb["PrivateMemoryFootprint"] * 1024, -#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) - // accessing PrivateSwapFootprint on other OSes will - // modify metrics_mb to create the value, which leads to - // expectation failures. - metrics_mb["SharedMemoryFootprint"] * 1024, - metrics_mb["PrivateSwapFootprint"] * 1024 -#else - metrics_mb["SharedMemoryFootprint"] * 1024 -#endif - ); + OSMemDumpPtr os_dump = GetFakeOSMemDump(metrics_mb); pmd->os_dump = std::move(os_dump); global_dump->process_dumps.push_back(std::move(pmd)); } @@ -468,30 +438,6 @@ }); } -void PopulatePaintPreviewCompositorMetrics(GlobalMemoryDumpPtr& global_dump, - MetricMap& metrics_mb) { - auto process_memory_dump = - memory_instrumentation::mojom::ProcessMemoryDump::New(); - process_memory_dump->service_name = - paint_preview::mojom::PaintPreviewCompositorCollection::Name_; - ProcessMemoryDumpPtr pmd(std::move(process_memory_dump)); - pmd->process_type = ProcessType::UTILITY; - OSMemDumpPtr os_dump = - GetFakeOSMemDump(GetResidentValue(metrics_mb) * 1024, - metrics_mb["PrivateMemoryFootprint"] * 1024, - metrics_mb["SharedMemoryFootprint"] * 1024 -#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) - // accessing PrivateSwapFootprint on other OSes will - // modify metrics_mb to create the value, which leads to - // expectation failures. - , - metrics_mb["PrivateSwapFootprint"] * 1024 -#endif - ); - pmd->os_dump = std::move(os_dump); - global_dump->process_dumps.push_back(std::move(pmd)); -} - MetricMap GetExpectedPaintPreviewCompositorMetrics() { return MetricMap({ {"ProcessType", static_cast<int64_t>(ProcessType::UTILITY)}, @@ -508,7 +454,8 @@ MetricMap& metrics_mb) { switch (ptype) { case HistogramProcessType::kAudioService: - PopulateAudioServiceMetrics(global_dump, metrics_mb); + PopulateUtilityMetrics(global_dump, metrics_mb, + /*service_name=*/absl::nullopt); return; case HistogramProcessType::kBrowser: PopulateBrowserMetrics(global_dump, metrics_mb); @@ -517,7 +464,9 @@ PopulateGpuMetrics(global_dump, metrics_mb); return; case HistogramProcessType::kPaintPreviewCompositor: - PopulatePaintPreviewCompositorMetrics(global_dump, metrics_mb); + PopulateUtilityMetrics( + global_dump, metrics_mb, + paint_preview::mojom::PaintPreviewCompositorCollection::Name_); return; case HistogramProcessType::kRenderer: PopulateRendererMetrics(global_dump, metrics_mb, 101); @@ -619,14 +568,14 @@ class ProcessMemoryMetricsEmitterTest : public testing::TestWithParam<HistogramProcessType> { public: - ProcessMemoryMetricsEmitterTest() {} + ProcessMemoryMetricsEmitterTest() = default; ProcessMemoryMetricsEmitterTest(const ProcessMemoryMetricsEmitterTest&) = delete; ProcessMemoryMetricsEmitterTest& operator=( const ProcessMemoryMetricsEmitterTest&) = delete; - ~ProcessMemoryMetricsEmitterTest() override {} + ~ProcessMemoryMetricsEmitterTest() override = default; protected: void CheckMemoryUkmEntryMetrics(const std::vector<MetricMap>& expected,
diff --git a/chrome/browser/new_tab_page/modules/new_tab_page_modules.cc b/chrome/browser/new_tab_page/modules/new_tab_page_modules.cc index 40089f6c..43eaec9ee 100644 --- a/chrome/browser/new_tab_page/modules/new_tab_page_modules.cc +++ b/chrome/browser/new_tab_page/modules/new_tab_page_modules.cc
@@ -59,7 +59,7 @@ } if (base::FeatureList::IsEnabled(ntp_features::kNtpHistoryClustersModule)) { - details.emplace_back("history-clusters", + details.emplace_back("history_clusters", IDS_HISTORY_CLUSTERS_JOURNEYS_TAB_LABEL); }
diff --git a/chrome/browser/page_load_metrics/observers/foreground_duration_ukm_observer.cc b/chrome/browser/page_load_metrics/observers/foreground_duration_ukm_observer.cc index 9424428b..ee0dc385 100644 --- a/chrome/browser/page_load_metrics/observers/foreground_duration_ukm_observer.cc +++ b/chrome/browser/page_load_metrics/observers/foreground_duration_ukm_observer.cc
@@ -125,7 +125,10 @@ void ForegroundDurationUKMObserver::DidActivatePrerenderedPage( content::NavigationHandle* navigation_handle) { - DCHECK(GetDelegate().WasPrerenderedThenActivatedInForeground()); - last_time_shown_ = base::TimeTicks::Now(); - currently_in_foreground_ = true; + if (GetDelegate().WasPrerenderedThenActivatedInForeground()) { + last_time_shown_ = base::TimeTicks::Now(); + currently_in_foreground_ = true; + } else { + currently_in_foreground_ = false; + } }
diff --git a/chrome/browser/page_load_metrics/observers/foreground_duration_ukm_observer.h b/chrome/browser/page_load_metrics/observers/foreground_duration_ukm_observer.h index 58fb3939..1c6049d 100644 --- a/chrome/browser/page_load_metrics/observers/foreground_duration_ukm_observer.h +++ b/chrome/browser/page_load_metrics/observers/foreground_duration_ukm_observer.h
@@ -44,7 +44,10 @@ content::NavigationHandle* navigation_handle) override; private: + // True when the visibility of WebContents is Visibility::VISIBLE (not + // OCCLUDED or HIDDEN). bool currently_in_foreground_ = false; + base::TimeTicks last_time_shown_; page_load_metrics::mojom::InputTimingPtr last_page_input_timing_; void RecordUkmIfInForeground(base::TimeTicks end_time);
diff --git a/chrome/browser/page_load_metrics/observers/foreground_duration_ukm_observer_browsertest.cc b/chrome/browser/page_load_metrics/observers/foreground_duration_ukm_observer_browsertest.cc index 3250840..1cedb7e1 100644 --- a/chrome/browser/page_load_metrics/observers/foreground_duration_ukm_observer_browsertest.cc +++ b/chrome/browser/page_load_metrics/observers/foreground_duration_ukm_observer_browsertest.cc
@@ -109,25 +109,56 @@ } IN_PROC_BROWSER_TEST_F(ForegroundDurationUKMObserverBrowserTest, - PrerenderSimple) { + PrerenderActivationInForeground) { StartHttpsServer(net::EmbeddedTestServer::CERT_OK); GURL empty = https_test_server()->GetURL("/empty.html"); GURL simple = https_test_server()->GetURL("/simple.html"); prerender_helper().NavigatePrimaryPage(empty); int host_id = prerender_helper().AddPrerender(simple); prerender_helper().WaitForPrerenderLoadCompletion(host_id); + ExpectMetricCountForUrl(simple, "ForegroundDuration", 0); ExpectMetricCountForUrl(simple, "ForegroundNumInputEvents", 0); ExpectMetricCountForUrl(simple, "ForegroundTotalInputDelay", 0); ExpectMetricCountForUrl(simple, "ForegroundTotalAdjustedInputDelay", 0); prerender_helper().NavigatePrimaryPage(simple); CloseAllTabs(); + + // The page was activated in foreground. The metrics should be recorded. ExpectMetricCountForUrl(simple, "ForegroundDuration", 1); ExpectMetricCountForUrl(simple, "ForegroundNumInputEvents", 1); ExpectMetricCountForUrl(simple, "ForegroundTotalInputDelay", 1); ExpectMetricCountForUrl(simple, "ForegroundTotalAdjustedInputDelay", 1); } +IN_PROC_BROWSER_TEST_F(ForegroundDurationUKMObserverBrowserTest, + PrerenderActivationInBackground) { + StartHttpsServer(net::EmbeddedTestServer::CERT_OK); + GURL empty = https_test_server()->GetURL("/empty.html"); + GURL simple = https_test_server()->GetURL("/simple.html"); + prerender_helper().NavigatePrimaryPage(empty); + int host_id = prerender_helper().AddPrerender(simple); + prerender_helper().WaitForPrerenderLoadCompletion(host_id); + + // Make the initiator page occluded. This will be treated as a background + // page. Note that we cannot make the initiator page hidden here as a hidden + // page cannot activate a prerendered page. + web_contents()->WasOccluded(); + + ExpectMetricCountForUrl(simple, "ForegroundDuration", 0); + ExpectMetricCountForUrl(simple, "ForegroundNumInputEvents", 0); + ExpectMetricCountForUrl(simple, "ForegroundTotalInputDelay", 0); + ExpectMetricCountForUrl(simple, "ForegroundTotalAdjustedInputDelay", 0); + prerender_helper().NavigatePrimaryPage(simple); + CloseAllTabs(); + + // The page was activated in background. The metrics should not be recorded. + ExpectMetricCountForUrl(simple, "ForegroundDuration", 0); + ExpectMetricCountForUrl(simple, "ForegroundNumInputEvents", 0); + ExpectMetricCountForUrl(simple, "ForegroundTotalInputDelay", 0); + ExpectMetricCountForUrl(simple, "ForegroundTotalAdjustedInputDelay", 0); +} + IN_PROC_BROWSER_TEST_F(ForegroundDurationUKMObserverBrowserTest, TabSwitching) { StartHttpsServer(net::EmbeddedTestServer::CERT_OK); GURL url1 = https_test_server()->GetURL("/simple.html");
diff --git a/chrome/browser/performance_manager/policies/page_discarding_helper.cc b/chrome/browser/performance_manager/policies/page_discarding_helper.cc index e4cd392..731cef75 100644 --- a/chrome/browser/performance_manager/policies/page_discarding_helper.cc +++ b/chrome/browser/performance_manager/policies/page_discarding_helper.cc
@@ -68,8 +68,9 @@ // Initialize the result map in one shot for time complexity O(n * log(n)). NodeRssMap::container_type result_container; result_container.reserve(candidates.size()); - for (auto candidate : candidates) + for (auto candidate : candidates) { result_container.emplace_back(candidate.page_node(), 0); + } NodeRssMap result(std::move(result_container)); // TODO(crbug/1240994): Use visitor to accumulate the result to avoid @@ -88,8 +89,9 @@ for (const ProcessNode* process_node : process_nodes) { base::flat_set<const FrameNode*> process_frames = process_node->GetFrameNodes(); - if (!process_frames.size()) + if (!process_frames.size()) { continue; + } // Get the resident set of the process and split it equally across its // frames. const uint64_t frame_rss_kb = @@ -98,8 +100,9 @@ // Check if the frame belongs to a discardable page, if so update the // resident set of the page. auto iter = result.find(frame_node->GetPageNode()); - if (iter == result.end()) + if (iter == result.end()) { continue; + } iter->second += frame_rss_kb; } } @@ -137,12 +140,14 @@ std::vector<PageNodeSortProxy> candidates; for (const auto* page_node : page_nodes) { CanUrgentlyDiscardResult can_discard_result = CanUrgentlyDiscard(page_node); - if (can_discard_result == CanUrgentlyDiscardResult::kMarked) + if (can_discard_result == CanUrgentlyDiscardResult::kMarked) { continue; + } bool is_protected = (can_discard_result == CanUrgentlyDiscardResult::kProtected); - if (!discard_protected_tabs && is_protected) + if (!discard_protected_tabs && is_protected) { continue; + } candidates.emplace_back(page_node, false, is_protected, page_node->GetTimeSinceLastVisibilityChange()); } @@ -167,8 +172,9 @@ uint64_t total_reclaim_kb = 0; NodeRssMap page_node_rss_kb = GetPageNodeRssEstimateKb(candidates); for (auto& candidate : candidates) { - if (total_reclaim_kb >= reclaim_target_kb_value) + if (total_reclaim_kb >= reclaim_target_kb_value) { break; + } const PageNode* node = candidate.page_node(); discard_attempts.emplace_back(node); // The node RSS value is updated by ProcessMetricsDecorator periodically. @@ -222,8 +228,9 @@ void PageDiscardingHelper::OnIsAudibleChanged(const PageNode* page_node) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!page_node->IsAudible()) + if (!page_node->IsAudible()) { last_change_to_non_audible_time_[page_node] = base::TimeTicks::Now(); + } } void PageDiscardingHelper::SetNoDiscardPatternsForProfile( @@ -284,19 +291,23 @@ PageDiscardingHelper::CanUrgentlyDiscard( const PageNode* page_node, bool consider_minimum_protection_time) const { - if (DiscardAttemptMarker::Get(PageNodeImpl::FromNode(page_node))) + if (DiscardAttemptMarker::Get(PageNodeImpl::FromNode(page_node))) { return CanUrgentlyDiscardResult::kMarked; + } - if (page_node->IsVisible()) + if (page_node->IsVisible()) { return CanUrgentlyDiscardResult::kProtected; - if (page_node->IsAudible()) + } + if (page_node->IsAudible()) { return CanUrgentlyDiscardResult::kProtected; + } // Don't discard tabs that have recently played audio. auto it = last_change_to_non_audible_time_.find(page_node); if (it != last_change_to_non_audible_time_.end()) { - if (base::TimeTicks::Now() - it->second < kTabAudioProtectionTime) + if (base::TimeTicks::Now() - it->second < kTabAudioProtectionTime) { return CanUrgentlyDiscardResult::kProtected; + } } #if !BUILDFLAG(IS_CHROMEOS) @@ -310,24 +321,28 @@ // Do not discard PDFs as they might contain entry that is not saved and they // don't remember their scrolling positions. See crbug.com/547286 and // crbug.com/65244. - if (page_node->GetContentsMimeType() == "application/pdf") + if (page_node->GetContentsMimeType() == "application/pdf") { return CanUrgentlyDiscardResult::kProtected; + } // Don't discard tabs that don't have a main frame yet. auto* main_frame = page_node->GetMainFrameNode(); - if (!main_frame) + if (!main_frame) { return CanUrgentlyDiscardResult::kProtected; + } // Only discard http(s) pages and internal pages to make sure that we don't // discard extensions or other PageNode that don't correspond to a tab. bool is_web_page_or_internal_page = main_frame->GetURL().SchemeIsHTTPOrHTTPS() || main_frame->GetURL().SchemeIs("chrome"); - if (!is_web_page_or_internal_page) + if (!is_web_page_or_internal_page) { return CanUrgentlyDiscardResult::kProtected; + } - if (!main_frame->GetURL().is_valid() || main_frame->GetURL().is_empty()) + if (!main_frame->GetURL().is_valid() || main_frame->GetURL().is_empty()) { return CanUrgentlyDiscardResult::kProtected; + } if (IsPageOptedOutOfDiscarding(page_node->GetBrowserContextID(), main_frame->GetURL())) { @@ -339,24 +354,33 @@ // The live state data won't be available if none of these events ever // happened on the page. if (live_state_data) { - if (!live_state_data->IsAutoDiscardable()) + if (!live_state_data->IsAutoDiscardable()) { return CanUrgentlyDiscardResult::kProtected; - if (live_state_data->IsCapturingVideo()) + } + if (live_state_data->IsCapturingVideo()) { return CanUrgentlyDiscardResult::kProtected; - if (live_state_data->IsCapturingAudio()) + } + if (live_state_data->IsCapturingAudio()) { return CanUrgentlyDiscardResult::kProtected; - if (live_state_data->IsBeingMirrored()) + } + if (live_state_data->IsBeingMirrored()) { return CanUrgentlyDiscardResult::kProtected; - if (live_state_data->IsCapturingWindow()) + } + if (live_state_data->IsCapturingWindow()) { return CanUrgentlyDiscardResult::kProtected; - if (live_state_data->IsCapturingDisplay()) + } + if (live_state_data->IsCapturingDisplay()) { return CanUrgentlyDiscardResult::kProtected; - if (live_state_data->IsConnectedToBluetoothDevice()) + } + if (live_state_data->IsConnectedToBluetoothDevice()) { return CanUrgentlyDiscardResult::kProtected; - if (live_state_data->IsConnectedToUSBDevice()) + } + if (live_state_data->IsConnectedToUSBDevice()) { return CanUrgentlyDiscardResult::kProtected; - if (live_state_data->IsActiveTab()) + } + if (live_state_data->IsActiveTab()) { return CanUrgentlyDiscardResult::kProtected; + } if (live_state_data->IsPinnedTab()) { return CanUrgentlyDiscardResult::kProtected; } @@ -369,16 +393,18 @@ } #if !BUILDFLAG(IS_CHROMEOS) // TODO(sebmarchand): Skip this check if the Entreprise memory limit is set. - if (live_state_data->WasDiscarded()) + if (live_state_data->WasDiscarded()) { return CanUrgentlyDiscardResult::kProtected; - // TODO(sebmarchand): Consider resetting the |WasDiscarded| value when the - // main frame document changes, also remove the DiscardAttemptMarker in - // this case. + } + // TODO(sebmarchand): Consider resetting the |WasDiscarded| value when the + // main frame document changes, also remove the DiscardAttemptMarker in + // this case. #endif } - if (page_node->HadFormInteraction()) + if (page_node->HadFormInteraction()) { return CanUrgentlyDiscardResult::kProtected; + } // TODO(sebmarchand): Do not discard crashed tabs. @@ -407,8 +433,9 @@ base::Value::Dict PageDiscardingHelper::DescribePageNodeData( const PageNode* node) const { auto* data = DiscardAttemptMarker::Get(PageNodeImpl::FromNode(node)); - if (data == nullptr) + if (data == nullptr) { return base::Value::Dict(); + } base::Value::Dict ret; ret.Set("has_discard_attempt_marker", base::Value("true"));
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc index e0d7724..b6031a6a 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -72,6 +72,7 @@ #include "chrome/browser/sharing/click_to_call/click_to_call_metrics.h" #include "chrome/browser/sharing/click_to_call/click_to_call_utils.h" #include "chrome/browser/sharing/features.h" +#include "chrome/browser/sharing_hub/sharing_hub_features.h" #include "chrome/browser/spellchecker/spellcheck_service.h" #include "chrome/browser/sync/send_tab_to_self_sync_service_factory.h" #include "chrome/browser/translate/chrome_translate_client.h" @@ -3360,8 +3361,15 @@ } bool RenderViewContextMenu::IsQRCodeGeneratorEnabled() const { - if (!GetBrowser()) + if (!GetBrowser() || !GetProfile()) { return false; + } + + if (sharing_hub::SharingIsDisabledByPolicy(GetProfile())) { + // If the sharing hub is disabled, clicking the QR code item (which tries to + // show the sharing hub) won't work. + return false; + } if (params_.media_type == ContextMenuDataMediaType::kImage) { return qrcode_generator::QRCodeGeneratorBubbleController::
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu_unittest.cc b/chrome/browser/renderer_context_menu/render_view_context_menu_unittest.cc index 95c06f1..f713e059 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu_unittest.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu_unittest.cc
@@ -1060,7 +1060,7 @@ testing::Bool()); // Verify that Autofill context menu items are displayed on a plain text field. -TEST_P(RenderViewContestMenuAutofillTest, ShowAutofillOptions) { +TEST_P(RenderViewContestMenuAutofillTest, DISABLED_ShowAutofillOptions) { autofill::PersonalDataManager* pdm = autofill::PersonalDataManagerFactory::GetForProfile( profile()->GetOriginalProfile());
diff --git a/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc b/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc index 0cc6cc5..e83205b 100644 --- a/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc +++ b/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc
@@ -313,6 +313,7 @@ // session restore is handled by LifecycleManager. web_contents()->GetController().SetNeedsReload(); web_contents()->GetController().LoadIfNecessary(); + web_contents()->Focus(); return true; }
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/BUILD.gn b/chrome/browser/resources/chromeos/accessibility/select_to_speak/BUILD.gn index 00aa4e9..7d980d7 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/BUILD.gn +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/BUILD.gn
@@ -24,18 +24,18 @@ ] } -tsc_output_dir = "$target_gen_dir/tsc" -select_to_speak_tsc_output_folder = "$tsc_output_dir/select_to_speak" +tsc_out_dir = "$target_gen_dir/tsc" +select_to_speak_tsc_out_dir = "$tsc_out_dir/select_to_speak" # Add typescript files to compile here. -ts_modules = [] +ts_modules = [ "select_to_speak/select_to_speak_main.ts" ] # Root dir must be the parent directory so it can reach common. ts_library("ts_build") { allow_js = true root_dir = "../" in_files = ts_modules - out_dir = tsc_output_dir + out_dir = tsc_out_dir definitions = [] } @@ -47,6 +47,7 @@ dest_dir = select_to_speak_out_dir deps = [ ":ts_build" ] sources = [ + "$select_to_speak_tsc_out_dir/select_to_speak_main.js", "background.html", "checked.png", "earcons/null_selection.ogg", @@ -58,7 +59,6 @@ "select_to_speak-2x.svg", "select_to_speak.js", "select_to_speak_constants.js", - "select_to_speak_main.js", "select_to_speak_options.js", "sts-icon-128.png", "sts-icon-16.png", @@ -68,7 +68,7 @@ "unchecked.png", ] rewrite_rules = [ - rebase_path(select_to_speak_tsc_output_folder, root_build_dir) + ":", + rebase_path(select_to_speak_tsc_out_dir, root_build_dir) + ":", rebase_path(".", root_build_dir) + ":", rebase_path(closure_library_dir, root_build_dir) + ":closure", ]
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_main.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_main.ts similarity index 88% rename from chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_main.js rename to chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_main.ts index 7b44a80..781b1c1e 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_main.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_main.ts
@@ -6,7 +6,7 @@ import {SelectToSpeak} from './select_to_speak.js'; -export let selectToSpeak; +export let selectToSpeak: SelectToSpeak; if (InstanceChecker.isActiveInstance()) { selectToSpeak = new SelectToSpeak();
diff --git a/chrome/browser/resources/new_tab_page/lazy_load.ts b/chrome/browser/resources/new_tab_page/lazy_load.ts index 91644b2..072eab2 100644 --- a/chrome/browser/resources/new_tab_page/lazy_load.ts +++ b/chrome/browser/resources/new_tab_page/lazy_load.ts
@@ -38,7 +38,7 @@ export {FeedProxy} from './modules/feed/feed_module_proxy.js'; export {feedDescriptor, FeedModuleElement, feedV2Descriptor} from './modules/feed/module.js'; export {HistoryClustersProxy, HistoryClustersProxyImpl} from './modules/history_clusters/history_clusters_proxy.js'; -export {historyClustersDescriptor, HistoryClustersModuleElement} from './modules/history_clusters/module.js'; +export {HistoryClusterLayoutType, historyClustersDescriptor, HistoryClustersModuleElement} from './modules/history_clusters/module.js'; export {InfoDialogElement} from './modules/info_dialog.js'; export {InitializeModuleCallback, Module, ModuleDescriptor, ModuleDescriptorV2, ModuleHeight} from './modules/module_descriptor.js'; export {counterfactualLoad} from './modules/module_descriptors.js';
diff --git a/chrome/browser/resources/new_tab_page/modules/history_clusters/layout_1.html b/chrome/browser/resources/new_tab_page/modules/history_clusters/layout_1.html deleted file mode 100644 index fd95f3f..0000000 --- a/chrome/browser/resources/new_tab_page/modules/history_clusters/layout_1.html +++ /dev/null
@@ -1,4 +0,0 @@ -<style> -</style> -<div> -</div>
diff --git a/chrome/browser/resources/new_tab_page/modules/history_clusters/layout_2.html b/chrome/browser/resources/new_tab_page/modules/history_clusters/layout_2.html deleted file mode 100644 index fd95f3f..0000000 --- a/chrome/browser/resources/new_tab_page/modules/history_clusters/layout_2.html +++ /dev/null
@@ -1,4 +0,0 @@ -<style> -</style> -<div> -</div>
diff --git a/chrome/browser/resources/new_tab_page/modules/history_clusters/layout_3.html b/chrome/browser/resources/new_tab_page/modules/history_clusters/layout_3.html deleted file mode 100644 index fd95f3f..0000000 --- a/chrome/browser/resources/new_tab_page/modules/history_clusters/layout_3.html +++ /dev/null
@@ -1,4 +0,0 @@ -<style> -</style> -<div> -</div>
diff --git a/chrome/browser/resources/new_tab_page/modules/history_clusters/module.html b/chrome/browser/resources/new_tab_page/modules/history_clusters/module.html index 0447b3e..33e453f 100644 --- a/chrome/browser/resources/new_tab_page/modules/history_clusters/module.html +++ b/chrome/browser/resources/new_tab_page/modules/history_clusters/module.html
@@ -21,4 +21,13 @@ <ntp-history-clusters-tile id="main-tile" large-format visit="[[cluster.visits.0]]"> </ntp-history-clusters-tile> + <template is="dom-if" if="[[isLayout_('layout_1', layoutType)]]" restamp> + <div id="layout1" class="layout">Layout 1</div> + </template> + <template is="dom-if" if="[[isLayout_('layout_2', layoutType)]]" restamp> + <div id="layout2" class="layout">Layout 2</div> + </template> + <template is="dom-if" if="[[isLayout_('layout_3', layoutType)]]" restamp> + <div id="layout3" class="layout">Layout 3</div> + </template> </div>
diff --git a/chrome/browser/resources/new_tab_page/modules/history_clusters/module.ts b/chrome/browser/resources/new_tab_page/modules/history_clusters/module.ts index 297335a..5c80de02 100644 --- a/chrome/browser/resources/new_tab_page/modules/history_clusters/module.ts +++ b/chrome/browser/resources/new_tab_page/modules/history_clusters/module.ts
@@ -14,6 +14,17 @@ import {HistoryClustersProxyImpl} from './history_clusters_proxy.js'; import {getTemplate} from './module.html.js'; +export const LAYOUT_1_3_MIN_IMAGE_VISITS = 2; +export const LAYOUT_2_IMAGE_VISITS = 1; +export const LAYOUT_2_MIN_VISITS = 3; +export const LAYOUT_3_MIN_VISITS = 4; + +export enum HistoryClusterLayoutType { + LAYOUT_1 = 'layout_1', // 2 image visits + LAYOUT_2 = 'layout_2', // 1 image visit & 2 non-image visits + LAYOUT_3 = 'layout_3', // 2 image visits & 2 non-image visits +} + // TODO:(crbug.com/1410808): Add module UI logic. export class HistoryClustersModuleElement extends I18nMixin (PolymerElement) { @@ -27,18 +38,24 @@ static get properties() { return { + layoutType: String, /** The cluster displayed by this element. */ cluster: Object, }; } cluster: Cluster; + layoutType: HistoryClusterLayoutType; + + private isLayout_(type: HistoryClusterLayoutType): boolean { + return type === this.layoutType; + } } customElements.define( HistoryClustersModuleElement.is, HistoryClustersModuleElement); -async function createElement(): Promise<HTMLElement|null> { +async function createElement(): Promise<HistoryClustersModuleElement|null> { const data = await HistoryClustersProxyImpl.getInstance().handler.getCluster(); if (!data.cluster) { @@ -47,8 +64,39 @@ const element = new HistoryClustersModuleElement(); element.cluster = data.cluster!; + + const visits = element.cluster.visits; + // Count number of visits with images. + const imageCount = visits + .filter((visit) => { + return !!visit.imageUrl; + }) + .length; + // Subtract the SRP from the visit count. + // The SRP is a visit that is included to be used in the module header + // and for opening the cluster in tab group. + const visitCount = visits.length - 1; + + // Calculate which layout to use. + if (imageCount >= LAYOUT_1_3_MIN_IMAGE_VISITS) { + // Layout 1 and 3 require the same number of images. + // Decide which one to use by checking if there are enough total + // visits for layout 3. + if (visitCount >= LAYOUT_3_MIN_VISITS) { + element.layoutType = HistoryClusterLayoutType.LAYOUT_3; + } else { + element.layoutType = HistoryClusterLayoutType.LAYOUT_1; + } + } else if (imageCount === LAYOUT_2_IMAGE_VISITS && + visitCount >= LAYOUT_2_MIN_VISITS) { + element.layoutType = HistoryClusterLayoutType.LAYOUT_2; + } else { + // If the data doesn't fit any layout, don't show the module. + return null; + } + return element; } export const historyClustersDescriptor: ModuleDescriptor = new ModuleDescriptor( - /*id=*/ 'history-clusters', createElement); + /*id=*/ 'history_clusters', createElement);
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/os_people_page.html b/chrome/browser/resources/settings/chromeos/os_people_page/os_people_page.html index 5329dd3..d7880f1 100644 --- a/chrome/browser/resources/settings/chromeos/os_people_page/os_people_page.html +++ b/chrome/browser/resources/settings/chromeos/os_people_page/os_people_page.html
@@ -107,8 +107,3 @@ </os-settings-subpage> </template> </os-settings-animated-pages> -<template is="dom-if" if="[[showSignoutDialog_]]" restamp> - <os-settings-signout-dialog sync-status="[[syncStatus]]" - on-close="onDisconnectDialogClosed_"> - </os-settings-signout-dialog> -</template>
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/os_people_page.ts b/chrome/browser/resources/settings/chromeos/os_people_page/os_people_page.ts index 7288bbd..4051cb03 100644 --- a/chrome/browser/resources/settings/chromeos/os_people_page/os_people_page.ts +++ b/chrome/browser/resources/settings/chromeos/os_people_page/os_people_page.ts
@@ -22,11 +22,9 @@ import './lock_screen.js'; import './lock_screen_password_prompt_dialog.js'; import './os_sync_controls.js'; -import './os_signout_dialog.js'; import './os_sync_page.js'; import {convertImageSequenceToPng} from 'chrome://resources/ash/common/cr_picture/png.js'; -import {focusWithoutInk} from 'chrome://resources/ash/common/focus_without_ink_js.js'; import {sendWithPromise} from 'chrome://resources/js/cr.js'; import {getImage} from 'chrome://resources/js/icon.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; @@ -35,7 +33,6 @@ import {Setting} from '../../mojom-webui/setting.mojom-webui.js'; import {ProfileInfo, ProfileInfoBrowserProxyImpl} from '../../people_page/profile_info_browser_proxy.js'; import {SyncBrowserProxy, SyncBrowserProxyImpl, SyncStatus} from '../../people_page/sync_browser_proxy.js'; -import {castExists} from '../assert_extras.js'; import {DeepLinkingMixin} from '../deep_linking_mixin.js'; import {LockStateMixin} from '../lock_state_mixin.js'; import {OsPageVisibility} from '../os_page_visibility.js'; @@ -90,8 +87,6 @@ profileLabel_: String, - showSignoutDialog_: Boolean, - fingerprintUnlockEnabled_: { type: Boolean, value() { @@ -178,7 +173,6 @@ private profileName_: string; private profileEmail_: string; private profileLabel_: string; - private showSignoutDialog_: boolean; private fingerprintUnlockEnabled_: boolean; private isAccountManagerEnabled_: boolean; private showParentalControls_: boolean; @@ -314,17 +308,6 @@ } override currentRouteChanged(route: Route): void { - if (Router.getInstance().currentRoute === routes.OS_SIGN_OUT) { - // If the sync status has not been fetched yet, optimistically display - // the sign-out dialog. There is another check when the sync status is - // fetched. The dialog will be closed when the user is not signed in. - if (this.syncStatus && !this.syncStatus.signedIn) { - Router.getInstance().navigateToPreviousRoute(); - } else { - this.showSignoutDialog_ = true; - } - } - // The old sync page is a shared subpage, so we handle deep links for // both this page and the sync page. Not ideal. if (route === routes.SYNC || route === routes.OS_PEOPLE) { @@ -399,22 +382,6 @@ } } - private onDisconnectDialogClosed_(): void { - this.showSignoutDialog_ = false; - focusWithoutInk( - castExists(this.shadowRoot!.querySelector<HTMLButtonElement>( - '#disconnectButton')), - ); - - if (Router.getInstance().currentRoute === routes.OS_SIGN_OUT) { - Router.getInstance().navigateToPreviousRoute(); - } - } - - private onDisconnectTap_(): void { - Router.getInstance().navigateTo(routes.OS_SIGN_OUT); - } - private onSyncTap_(): void { // Users can go to sync subpage regardless of sync status. Router.getInstance().navigateTo(routes.SYNC);
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/os_signout_dialog.html b/chrome/browser/resources/settings/chromeos/os_people_page/os_signout_dialog.html deleted file mode 100644 index 7b5c7bf..0000000 --- a/chrome/browser/resources/settings/chromeos/os_people_page/os_signout_dialog.html +++ /dev/null
@@ -1,43 +0,0 @@ -<style include="cr-shared-style settings-shared iron-flex"> - .delete-profile-warning { - padding-bottom: 10px; - padding-inline-end: var(--cr-section-padding); - /* In order to line up with the checkbox text. */ - padding-inline-start: calc(var(--cr-section-padding) + 32px); - padding-top: 10px; - } - - #wideFooter { - /* Override the cr-dialog footer padding. */ - padding: 0; - } - - #dialog-body { - /* Add space for the link focus ring. See https://crbug.com/916939. */ - padding-bottom: 2px; - } -</style> - -<cr-dialog id="dialog" ignore-enter-key close-text="$i18n{close}"> - <div slot="title">$i18n{syncDisconnectTitle}</div> - <div id="dialog-body" slot="body"> - <div inner-h-t-m-l="[[ - getDisconnectExplanationHtml_(syncStatus.domain)]]"> - </div> - </div> - <div slot="button-container"> - <cr-button id="disconnectCancel" class="cancel-button" - on-click="onDisconnectCancel_"> - $i18n{cancel} - </cr-button> - <cr-button id="disconnectConfirm" class="action-button" - hidden="[[syncStatus.domain]]" on-click="onDisconnectConfirm_"> - $i18n{syncDisconnect} - </cr-button> - <cr-button id="disconnectManagedProfileConfirm" - class="action-button" hidden="[[!syncStatus.domain]]" - on-click="onDisconnectConfirm_"> - $i18n{syncDisconnectConfirm} - </cr-button> - </div> -</cr-dialog>
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/os_signout_dialog.ts b/chrome/browser/resources/settings/chromeos/os_people_page/os_signout_dialog.ts deleted file mode 100644 index de454d85..0000000 --- a/chrome/browser/resources/settings/chromeos/os_people_page/os_signout_dialog.ts +++ /dev/null
@@ -1,149 +0,0 @@ -// Copyright 2018 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * @fileoverview 'settings-signout-dialog' is a dialog that allows the - * user to turn off sync and sign out of Chromium. - */ -import '//resources/cr_elements/cr_button/cr_button.js'; -import '//resources/cr_elements/cr_dialog/cr_dialog.js'; -import '//resources/cr_elements/cr_shared_style.css.js'; -import '//resources/cr_elements/cr_shared_vars.css.js'; -import '//resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js'; -import '../../settings_shared.css.js'; - -import {CrDialogElement} from '//resources/cr_elements/cr_dialog/cr_dialog.js'; -import {WebUiListenerMixin} from '//resources/cr_elements/web_ui_listener_mixin.js'; -import {sanitizeInnerHtml} from '//resources/js/parse_html_subset.js'; -import {microTask, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; - -import {SyncBrowserProxyImpl, SyncStatus} from '../../people_page/sync_browser_proxy.js'; - -import {getTemplate} from './os_signout_dialog.html.js'; - -export interface OsSettingsSignoutDialogElement { - $: { - dialog: CrDialogElement, - disconnectConfirm: HTMLElement, - }; -} - -const OsSettingsSignoutDialogElementBase = WebUiListenerMixin(PolymerElement); - -export class OsSettingsSignoutDialogElement extends - OsSettingsSignoutDialogElementBase { - static get is() { - return 'os-settings-signout-dialog'; - } - - static get template() { - return getTemplate(); - } - - static get properties() { - return { - /** - * The current sync status, supplied by the parent. - */ - syncStatus: { - type: Object, - observer: 'syncStatusChanged_', - }, - - /** - * True if the checkbox to delete the profile has been checked. - */ - deleteProfile_: Boolean, - - /** - * True if the profile deletion warning is visible. - */ - deleteProfileWarningVisible_: Boolean, - - /** - * The profile deletion warning. The message indicates the number of - * profile stats that will be deleted if a non-zero count for the profile - * stats is returned from the browser. - */ - deleteProfileWarning_: String, - }; - } - - syncStatus: SyncStatus|null; - private deleteProfile_: boolean; - private deleteProfileWarningVisible_: boolean; - private deleteProfileWarning_: string; - - override connectedCallback() { - super.connectedCallback(); - - this.addWebUiListener( - 'profile-stats-count-ready', this.handleProfileStatsCount_.bind(this)); - microTask.run(() => { - this.$.dialog.showModal(); - }); - } - - /** - * @return true when the user selected 'Confirm'. - */ - wasConfirmed(): boolean { - return this.$.dialog.getNative().returnValue === 'success'; - } - - /** - * Handler for when the profile stats count is pushed from the browser. - */ - private handleProfileStatsCount_(count: number) { - const username = this.syncStatus!.signedInUsername || ''; - if (count === 0) { - this.deleteProfileWarning_ = loadTimeData.getStringF( - 'deleteProfileWarningWithoutCounts', username); - } else if (count === 1) { - this.deleteProfileWarning_ = loadTimeData.getStringF( - 'deleteProfileWarningWithCountsSingular', username); - } else { - this.deleteProfileWarning_ = loadTimeData.getStringF( - 'deleteProfileWarningWithCountsPlural', count, username); - } - } - - /** - * Polymer observer for syncStatus. - */ - private syncStatusChanged_() { - if (!this.syncStatus!.signedIn && this.$.dialog.open) { - this.$.dialog.close(); - } - } - - private getDisconnectExplanationHtml_(_domain: string): TrustedHTML { - return sanitizeInnerHtml( - loadTimeData.getString('syncDisconnectExplanation')); - } - - private onDisconnectCancel_() { - this.$.dialog.cancel(); - } - - private onDisconnectConfirm_() { - this.$.dialog.close(); - // Chrome OS users are always signed-in, so just turn off sync. - SyncBrowserProxyImpl.getInstance().turnOffSync(); - } - - private isDeleteProfileFooterVisible_(): boolean { - return !this.syncStatus!.domain; - } -} - -declare global { - interface HTMLElementTagNameMap { - 'os-settings-signout-dialog': OsSettingsSignoutDialogElement; - } -} - -customElements.define( - OsSettingsSignoutDialogElement.is, OsSettingsSignoutDialogElement);
diff --git a/chrome/browser/resources/settings/chromeos/os_settings.gni b/chrome/browser/resources/settings/chromeos/os_settings.gni index be5d341..310d898 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings.gni +++ b/chrome/browser/resources/settings/chromeos/os_settings.gni
@@ -193,7 +193,6 @@ "chromeos/os_people_page/lock_screen_password_prompt_dialog.ts", "chromeos/os_people_page/os_people_page.ts", "chromeos/os_people_page/os_personalization_options.ts", - "chromeos/os_people_page/os_signout_dialog.ts", "chromeos/os_people_page/os_sync_controls.ts", "chromeos/os_people_page/os_sync_encryption_options.ts", "chromeos/os_people_page/os_sync_page.ts",
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_routes.ts b/chrome/browser/resources/settings/chromeos/os_settings_routes.ts index b89a7b33..8c0e87d 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings_routes.ts +++ b/chrome/browser/resources/settings/chromeos/os_settings_routes.ts
@@ -178,7 +178,6 @@ OS_PRIVACY: Route; OS_RESET: Route; OS_SEARCH: Route; - OS_SIGN_OUT: Route; OS_SYNC: Route; OS_PEOPLE: Route; PER_DEVICE_KEYBOARD: Route; @@ -220,13 +219,12 @@ const r: Partial<OsSettingsRoutes> = {}; const {Section, Subpage} = routesMojomWebui; - // Special routes: BASIC is the main page which loads if no path is - // provided, ADVANCED is the bottom section of the main page which is not - // visible unless the user enables it, and OS_SIGN_OUT is a sign out dialog. + // Special routes: + // - BASIC is the main page which loads if no path is provided + // - ADVANCED is the bottom section of the main page which is not + // visible unless the user enables it r.BASIC = new Route('/'); r.ADVANCED = new Route('/advanced'); - r.OS_SIGN_OUT = r.BASIC.createChild('/osSignOut'); - r.OS_SIGN_OUT.isNavigableDialog = true; // Network section. r.INTERNET = createSection(
diff --git a/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_list.html b/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_list.html index 04ba9123..1be2271 100644 --- a/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_list.html +++ b/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_list.html
@@ -13,7 +13,7 @@ cr-icon-button { --cr-icon-button-icon-size: 16px; - --cr-icon-button-size: 20px; + --cr-icon-button-size: 24px; margin: 0; } @@ -82,6 +82,10 @@ margin: 8px 14px; } + :host-context([chrome-refresh-2023]) sp-heading { + margin: 8px 16px; + } + .icon-button-row { align-items: center; color: var(--cr-secondary-text-color); @@ -149,12 +153,15 @@ activeFolderPath_.*, editing_)]]"> <h1 slot="heading">[[getActiveFolderLabel_(activeFolderPath_.*)]]</h1> - <cr-button slot="buttons" class="sort-menu-button" - aria-label="$i18n{sortMenuA11yLabel}" - on-click="onShowSortMenuClicked_"> + <div aria-hidden="true" slot="metadata"> [[getSortLabel_(activeSortIndex_)]] - <iron-icon icon="sp:filter-list"></iron-icon> - </cr-button> + </div> + <cr-icon-button slot="buttons" class="sort-menu-button" + iron-icon="sp:filter-list" + aria-label="$i18n{sortMenuA11yLabel}" + aria-description="[[getSortLabel_(activeSortIndex_)]]" + on-click="onShowSortMenuClicked_"> + </cr-icon-button> <cr-icon-button slot="buttons" iron-icon="bookmarks:create-new-folder" disabled="[[editing_]]" aria-label="$i18n{createNewFolderA11yLabel}"
diff --git a/chrome/browser/resources/side_panel/shared/sp_heading.html b/chrome/browser/resources/side_panel/shared/sp_heading.html index dcd237fe..b681044 100644 --- a/chrome/browser/resources/side_panel/shared/sp_heading.html +++ b/chrome/browser/resources/side_panel/shared/sp_heading.html
@@ -16,10 +16,12 @@ #backButton, ::slotted(cr-icon-button[slot=buttons]) { - --cr-icon-button-margin-start: -2px; - --cr-icon-button-margin-end: -2px; --cr-icon-button-icon-size: 16px; - --cr-icon-button-size: 20px; + --cr-icon-button-size: 24px; + } + + #backButton { + margin: 0 -4px; } :host-context([chrome-refresh-2023]) #backButton { @@ -70,35 +72,22 @@ font-weight: 400; line-height: 20px; overflow: hidden; + padding-inline-end: 4px; text-overflow: ellipsis; white-space: nowrap; } :host-context([chrome-refresh-2023]) ::slotted([slot=metadata]) { line-height: 16px; - padding-inline-end: 4px; } #suffixButtons { align-items: center; - display: flex; + display: grid; gap: 8px; - } - - ::slotted(cr-button[slot=buttons]) { - --hover-bg-color: var(--cr-hover-background-color); - --ripple-opacity: 0; - border: none; - color: var(--cr-secondary-text-color); - font-weight: 400; - gap: 4px; - height: 20px; - padding: 0; - } - - ::slotted(cr-button[slot=buttons]:active) { - background-color: var(--cr-active-background-color); - box-shadow: none; + grid-auto-columns: 16px; + grid-auto-flow: column; + justify-items: center; } </style>
diff --git a/chrome/browser/resources/side_panel/user_notes/user_notes_api_proxy.ts b/chrome/browser/resources/side_panel/user_notes/user_notes_api_proxy.ts index da91ab83..51d7e8a 100644 --- a/chrome/browser/resources/side_panel/user_notes/user_notes_api_proxy.ts +++ b/chrome/browser/resources/side_panel/user_notes/user_notes_api_proxy.ts
@@ -66,6 +66,10 @@ this.handler.setSortOrder(sortByNewest); } + hasNotesOnAnyPages() { + return this.handler.hasNotesInAnyPages(); + } + getCallbackRouter() { return this.callbackRouter; }
diff --git a/chrome/browser/resources/tab_strip/tab.ts b/chrome/browser/resources/tab_strip/tab.ts index cb713b94..4f77247c 100644 --- a/chrome/browser/resources/tab_strip/tab.ts +++ b/chrome/browser/resources/tab_strip/tab.ts
@@ -260,49 +260,6 @@ this.toggleAttribute('touch_pressed_', isTouchPressed); } - slideIn(): Promise<void> { - const paddingInlineEnd = getPaddingInlineEndProperty(); - - // If this TabElement is the last tab, there needs to be enough space for - // the view to scroll to it. Therefore, immediately take up all the space - // it needs to and only animate the scale. - const isLastChild = this.nextElementSibling === null; - - const startState = { - maxWidth: isLastChild ? 'var(--tabstrip-tab-width)' : 0, - transform: `scale(0)`, - [paddingInlineEnd]: isLastChild ? 'var(--tabstrip-tab-spacing)' : 0, - }; - - const finishState = { - maxWidth: `var(--tabstrip-tab-width)`, - transform: `scale(1)`, - [paddingInlineEnd]: 'var(--tabstrip-tab-spacing)', - }; - - return new Promise(resolve => { - const animation = this.animate([startState, finishState], { - duration: 300, - easing: 'cubic-bezier(.4, 0, 0, 1)', - }); - animation.onfinish = () => { - resolve(); - }; - - // TODO(crbug.com/1035678) By the next animation frame, the animation - // should start playing. By the time another animation frame happens, - // force play the animation if the animation has not yet begun. Remove - // if/when the Blink issue has been fixed. - requestAnimationFrame(() => { - requestAnimationFrame(() => { - if (animation.pending) { - animation.play(); - } - }); - }); - }); - } - slideOut(): Promise<void> { if (!this.tabsApi_.isVisible() || this.tab_.pinned || this.tabSwiper_.wasSwiping()) {
diff --git a/chrome/browser/resources/tab_strip/tab_list.ts b/chrome/browser/resources/tab_strip/tab_list.ts index be1db0f..6e903bd 100644 --- a/chrome/browser/resources/tab_strip/tab_list.ts +++ b/chrome/browser/resources/tab_strip/tab_list.ts
@@ -556,7 +556,6 @@ const tabElement = this.createTabElement_(tab); this.placeTabElement(tabElement, tab.index, tab.pinned, tab.groupId); - this.addAnimationPromise_(tabElement.slideIn()); if (tab.active) { this.updatePreviouslyActiveTabs_(tab.id); this.scrollToTab_(tabElement);
diff --git a/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service.cc b/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service.cc index 3ac1299..cc0bdc7 100644 --- a/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service.cc +++ b/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service.cc
@@ -85,6 +85,7 @@ constexpr char kFileDataProcessTimestampPref[] = "last_processed_timestamp"; constexpr char kFileDataDictPref[] = "file_data"; +constexpr char kManifestFile[] = "manifest.json"; // Delay before the Telemetry Service checks its last upload time. base::TimeDelta kStartupUploadCheckDelaySeconds = base::Seconds(15); @@ -95,6 +96,17 @@ persisted_at_write_interval); } +void RecordNumOffstoreExtensions(int num_extensions) { + base::UmaHistogramCounts100( + "SafeBrowsing.ExtensionTelemetry.FileData.NumOffstoreExtensions", + num_extensions); +} + +void RecordCollectionDuration(base::TimeDelta duration) { + base::UmaHistogramMediumTimes( + "SafeBrowsing.ExtensionTelemetry.FileData.CollectionDuration", duration); +} + static_assert(extensions::Manifest::NUM_LOAD_TYPES == 10, "ExtensionTelemetryReportRequest::ExtensionInfo::Type " "needs to match extensions::Manifest::Type."); @@ -226,8 +238,9 @@ void ExtensionTelemetryService::SetEnabled(bool enable) { // Make call idempotent. - if (enabled_ == enable) + if (enabled_ == enable) { return; + } enabled_ = enable; if (enabled_) { @@ -417,8 +430,9 @@ void ExtensionTelemetryService::CreateAndUploadReport() { DCHECK(enabled_); active_report_ = CreateReport(); - if (!active_report_) + if (!active_report_) { return; + } auto upload_data = std::make_unique<std::string>(); if (!active_report_->SerializeToString(upload_data.get())) { @@ -490,8 +504,9 @@ // This check is performed as a delayed task after enabling the service. The // service may become disabled between the time this task is scheduled and it // actually runs. So make sure service is enabled before performing the check. - if (!enabled_) + if (!enabled_) { return; + } if ((GetLastUploadTimeForExtensionTelemetry(*pref_service_) + current_reporting_interval_) <= base::Time::Now()) { @@ -510,8 +525,9 @@ } else { // Otherwise persist data gathered so far. active_report_ = CreateReport(); - if (!active_report_) + if (!active_report_) { return; + } std::string write_string; if (!active_report_->SerializeToString(&write_string)) { active_report_.reset(); @@ -529,8 +545,9 @@ // extension store is empty) AND there are no installed extensions currently. std::unique_ptr<extensions::ExtensionSet> installed_extensions = extension_registry_->GenerateInstalledExtensionsSet(); - if (extension_store_.empty() && installed_extensions->is_empty()) + if (extension_store_.empty() && installed_extensions->is_empty()) { return nullptr; + } auto telemetry_report_pb = std::make_unique<ExtensionTelemetryReportRequest>(); @@ -666,6 +683,46 @@ DVLOG(1) << "Telemetry Report: " << ss.str(); } +ExtensionTelemetryService::OffstoreExtensionFileData:: + OffstoreExtensionFileData() = default; +ExtensionTelemetryService::OffstoreExtensionFileData:: + ~OffstoreExtensionFileData() = default; +ExtensionTelemetryService::OffstoreExtensionFileData:: + OffstoreExtensionFileData::OffstoreExtensionFileData( + const OffstoreExtensionFileData& src) = default; + +absl::optional<ExtensionTelemetryService::OffstoreExtensionFileData> +ExtensionTelemetryService::RetrieveOffstoreFileDataForReport( + const extensions::ExtensionId& extension_id) { + const auto& pref_dict = GetExtensionTelemetryFileData(*pref_service_); + const base::Value::Dict* extension_dict = pref_dict.FindDict(extension_id); + if (!extension_dict) { + return absl::nullopt; + } + + const base::Value::Dict* file_data_dict = + extension_dict->FindDict(kFileDataDictPref); + if (!file_data_dict || file_data_dict->empty()) { + return absl::nullopt; + } + + OffstoreExtensionFileData offstore_extension_file_data; + base::Value::Dict dict = file_data_dict->Clone(); + absl::optional<base::Value> manifest_value = dict.Extract(kManifestFile); + if (manifest_value.has_value()) { + offstore_extension_file_data.manifest = + std::move(manifest_value.value().GetString()); + } + + for (auto&& [file_name, file_hash] : dict) { + ExtensionTelemetryReportRequest_ExtensionInfo_FileInfo file_info; + file_info.set_name(std::move(file_name)); + file_info.set_hash(std::move(file_hash.GetString())); + offstore_extension_file_data.file_infos.emplace_back(std::move(file_info)); + } + return absl::make_optional(offstore_extension_file_data); +} + std::unique_ptr<ExtensionInfo> ExtensionTelemetryService::GetExtensionInfoForReport( const extensions::Extension& extension) { @@ -692,6 +749,19 @@ extension_info->set_disable_reasons( extension_prefs_->GetDisableReasons(extension.id())); + if (base::FeatureList::IsEnabled(kExtensionTelemetryFileData)) { + absl::optional<OffstoreExtensionFileData> offstore_file_data = + RetrieveOffstoreFileDataForReport(extension.id()); + + if (offstore_file_data.has_value()) { + extension_info->set_manifest_json( + std::move(offstore_file_data.value().manifest)); + for (auto& file_info : offstore_file_data.value().file_infos) { + extension_info->mutable_file_infos()->Add(std::move(file_info)); + } + } + } + return extension_info; } @@ -722,6 +792,7 @@ return; } + offstore_file_data_collection_start_time_ = base::TimeTicks::Now(); offstore_extension_dirs_.clear(); offstore_extension_file_data_contexts_.clear(); GetOffstoreExtensionDirs(); @@ -765,6 +836,7 @@ offstore_extension_dirs_[extension->id()] = extension->path(); } } + RecordNumOffstoreExtensions(offstore_extension_dirs_.size()); } void ExtensionTelemetryService::RemoveUninstalledExtensionsFileDataFromPref() { @@ -773,10 +845,10 @@ base::Value::Dict& pref_dict = pref_update.Get(); std::vector<extensions::ExtensionId> uninstalled_extensions; - for (auto offstore : pref_dict) { + for (auto&& offstore : pref_dict) { if (offstore_extension_dirs_.find(offstore.first) == offstore_extension_dirs_.end()) { - uninstalled_extensions.push_back(offstore.first); + uninstalled_extensions.emplace_back(offstore.first); } } @@ -798,6 +870,12 @@ base::Seconds( kExtensionTelemetryFileDataCollectionIntervalSeconds.Get()), this, &ExtensionTelemetryService::StartOffstoreFileDataCollection); + + // Record only if there are off-store extensions installed. + if (!offstore_extension_dirs_.empty()) { + RecordCollectionDuration(base::TimeTicks::Now() - + offstore_file_data_collection_start_time_); + } return; }
diff --git a/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service.h b/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service.h index 79beac2..73c8ce97 100644 --- a/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service.h +++ b/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service.h
@@ -44,6 +44,7 @@ class ExtensionTelemetryPersister; class ExtensionTelemetryReportRequest; class ExtensionTelemetryReportRequest_ExtensionInfo; +class ExtensionTelemetryReportRequest_ExtensionInfo_FileInfo; class ExtensionTelemetryUploader; class SafeBrowsingTokenFetcher; @@ -190,6 +191,22 @@ // Stops and clears any offstore file data collection objects/contexts. void StopOffstoreFileDataCollection(); + // Stores offstore extension file data retrieved from PrefService. + struct OffstoreExtensionFileData { + OffstoreExtensionFileData(); + ~OffstoreExtensionFileData(); + OffstoreExtensionFileData(const OffstoreExtensionFileData&); + + std::string manifest; + std::vector<ExtensionTelemetryReportRequest_ExtensionInfo_FileInfo> + file_infos; + }; + + // Given an |extension_id|, retrieves the collected file data from PrefService + // if available. + absl::optional<OffstoreExtensionFileData> RetrieveOffstoreFileDataForReport( + const extensions::ExtensionId& extension_id); + // The persister object is bound to the threadpool. This prevents the // the read/write operations the `persister_` runs from blocking // the UI thread. It also allows the `persister_` object to be @@ -254,6 +271,7 @@ // Then repeat the collection based on // |kExtensionTelemetryFileDataProcessIntervalSeconds| - default: 2 hours. base::OneShotTimer offstore_file_data_collection_timer_; + base::TimeTicks offstore_file_data_collection_start_time_; using SignalProcessors = base::flat_map<ExtensionSignalType,
diff --git a/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service_unittest.cc b/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service_unittest.cc index 03d38025..8e1644a 100644 --- a/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service_unittest.cc +++ b/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service_unittest.cc
@@ -103,8 +103,9 @@ const ExtensionInfo* GetExtensionInfoFromExtensionStore( const ExtensionId& extension_id) { auto iter = telemetry_service_->extension_store_.find(extension_id); - if (iter == telemetry_service_->extension_store_.end()) + if (iter == telemetry_service_->extension_store_.end()) { return nullptr; + } return iter->second.get(); } @@ -864,4 +865,114 @@ EXPECT_TRUE(actual_extension_1->FindDict(kFileDataDictPref)); } +TEST_F(ExtensionTelemetryServiceTest, + FileData_AttachesOffstoreFileDataToReport) { + // Enable |kExtensionTelemetryFileData| feature and starts collection. + telemetry_service_->SetEnabled(false); + scoped_feature_list.InitAndEnableFeatureWithParameters( + {kExtensionTelemetryFileData}, + {{"StartupDelaySeconds", + base::NumberToString(kFileDataStartUpDelaySeconds)}}); + telemetry_service_->SetEnabled(true); + task_environment_.FastForwardBy(base::Seconds(kFileDataStartUpDelaySeconds)); + task_environment_.RunUntilIdle(); + + std::unique_ptr<TelemetryReport> telemetry_report_pb = GetTelemetryReport(); + const auto& file_data_dict = + profile_.GetPrefs()->GetDict(prefs::kExtensionTelemetryFileData); + + const base::Value::Dict* extension_0_dict = + file_data_dict.FindDict(kExtensionId[0])->FindDict(kFileDataDictPref); + EXPECT_EQ(telemetry_report_pb->reports(0).extension().id(), kExtensionId[0]); + EXPECT_EQ(telemetry_report_pb->reports(0).extension().manifest_json(), + *(extension_0_dict->FindString(kManifestFile))); + EXPECT_EQ(telemetry_report_pb->reports(0).extension().file_infos_size(), 1); + EXPECT_EQ(telemetry_report_pb->reports(0).extension().file_infos(0).name(), + kJavaScriptFile); + EXPECT_EQ(telemetry_report_pb->reports(0).extension().file_infos(0).hash(), + *(extension_0_dict->FindString(kJavaScriptFile))); + + const base::Value::Dict* extension_1_dict = + file_data_dict.FindDict(kExtensionId[1])->FindDict(kFileDataDictPref); + EXPECT_EQ(telemetry_report_pb->reports(1).extension().id(), kExtensionId[1]); + EXPECT_EQ(telemetry_report_pb->reports(1).extension().manifest_json(), + *(extension_1_dict->FindString(kManifestFile))); + EXPECT_EQ(telemetry_report_pb->reports(1).extension().file_infos_size(), 1); + EXPECT_EQ(telemetry_report_pb->reports(1).extension().file_infos(0).name(), + kJavaScriptFile); + EXPECT_EQ(telemetry_report_pb->reports(1).extension().file_infos(0).hash(), + *(extension_1_dict->FindString(kJavaScriptFile))); +} + +TEST_F(ExtensionTelemetryServiceTest, + FileData_DoesNotAttachFileDataForNonOffstoreExtensions) { + // Register webstore extension 2. + RegisterExtensionWithExtensionService(kExtensionId[2], kExtensionName[2], + ManifestLocation::kInternal, + Extension::FROM_WEBSTORE); + // Enable |kExtensionTelemetryFileData| feature and starts collection. + telemetry_service_->SetEnabled(false); + scoped_feature_list.InitAndEnableFeatureWithParameters( + {kExtensionTelemetryFileData}, + {{"StartupDelaySeconds", + base::NumberToString(kFileDataStartUpDelaySeconds)}}); + telemetry_service_->SetEnabled(true); + task_environment_.FastForwardBy(base::Seconds(kFileDataStartUpDelaySeconds)); + task_environment_.RunUntilIdle(); + + std::unique_ptr<TelemetryReport> telemetry_report_pb = GetTelemetryReport(); + + // Verify that Extension 0 has offstore file data. + EXPECT_EQ(telemetry_report_pb->reports(0).extension().id(), kExtensionId[0]); + EXPECT_FALSE( + telemetry_report_pb->reports(0).extension().manifest_json().empty()); + EXPECT_EQ(telemetry_report_pb->reports(0).extension().file_infos_size(), 1); + + // Verify Extension 1 has offstore file data. + EXPECT_EQ(telemetry_report_pb->reports(1).extension().id(), kExtensionId[1]); + EXPECT_FALSE( + telemetry_report_pb->reports(1).extension().manifest_json().empty()); + EXPECT_EQ(telemetry_report_pb->reports(1).extension().file_infos_size(), 1); + + // Verify Extension 2 does not have offstore file data. + EXPECT_EQ(telemetry_report_pb->reports(2).extension().id(), kExtensionId[2]); + EXPECT_FALSE(telemetry_report_pb->reports(2).extension().has_manifest_json()); + EXPECT_EQ(telemetry_report_pb->reports(2).extension().file_infos_size(), 0); +} + +TEST_F(ExtensionTelemetryServiceTest, FileData_HandlesEmptyFileDataInPrefs) { + // Enable |kExtensionTelemetryFileData| feature and starts collection. + telemetry_service_->SetEnabled(false); + scoped_feature_list.InitAndEnableFeatureWithParameters( + {kExtensionTelemetryFileData}, + {{"StartupDelaySeconds", + base::NumberToString(kFileDataStartUpDelaySeconds)}}); + telemetry_service_->SetEnabled(true); + task_environment_.FastForwardBy(base::Seconds(kFileDataStartUpDelaySeconds)); + task_environment_.RunUntilIdle(); + + // Set up pref dict: + // extension 0 - empty file data dict + // extension 1 - missing file data dict key + base::Value::Dict extension_0_dict; + extension_0_dict.Set(kFileDataDictPref, base::Value::Dict()); + base::Value::Dict empty_file_data_dicts; + empty_file_data_dicts.Set(kExtensionId[0], std::move(extension_0_dict)); + empty_file_data_dicts.Set(kExtensionId[1], base::Value::Dict()); + profile_.GetPrefs()->SetDict(prefs::kExtensionTelemetryFileData, + std::move(empty_file_data_dicts)); + + std::unique_ptr<TelemetryReport> telemetry_report_pb = GetTelemetryReport(); + + // Verify Extension 0 does not have offstore file data. + EXPECT_EQ(telemetry_report_pb->reports(0).extension().id(), kExtensionId[0]); + EXPECT_FALSE(telemetry_report_pb->reports(0).extension().has_manifest_json()); + EXPECT_EQ(telemetry_report_pb->reports(0).extension().file_infos_size(), 0); + + // Verify Extension 1 does not have offstore file data. + EXPECT_EQ(telemetry_report_pb->reports(1).extension().id(), kExtensionId[1]); + EXPECT_FALSE(telemetry_report_pb->reports(1).extension().has_manifest_json()); + EXPECT_EQ(telemetry_report_pb->reports(1).extension().file_infos_size(), 0); +} + } // namespace safe_browsing
diff --git a/chrome/browser/search_engines/android/BUILD.gn b/chrome/browser/search_engines/android/BUILD.gn index 0b573c6..59f2c7f 100644 --- a/chrome/browser/search_engines/android/BUILD.gn +++ b/chrome/browser/search_engines/android/BUILD.gn
@@ -31,6 +31,7 @@ "//chrome/browser/omaha/android:java", "//chrome/browser/preferences:java", "//chrome/browser/profiles/android:java", + "//chrome/browser/settings:java", "//chrome/browser/ui/messages/android:java", "//components/browser_ui/settings/android:java", "//components/browser_ui/site_settings/android:java",
diff --git a/chrome/browser/search_engines/android/java/src/org/chromium/chrome/browser/search_engines/settings/SearchEngineAdapter.java b/chrome/browser/search_engines/android/java/src/org/chromium/chrome/browser/search_engines/settings/SearchEngineAdapter.java index 919020f..11aae72d 100644 --- a/chrome/browser/search_engines/android/java/src/org/chromium/chrome/browser/search_engines/settings/SearchEngineAdapter.java +++ b/chrome/browser/search_engines/android/java/src/org/chromium/chrome/browser/search_engines/settings/SearchEngineAdapter.java
@@ -73,7 +73,8 @@ } /** The current context. */ - private Context mContext; + private final Context mContext; + private final Profile mProfile; /** The layout inflater to use for the custom views. */ private LayoutInflater mLayoutInflater; @@ -107,9 +108,11 @@ /** * Construct a SearchEngineAdapter. * @param context The current context. + * @param profile The Profile associated with these settings. */ - public SearchEngineAdapter(Context context) { + public SearchEngineAdapter(Context context, Profile profile) { mContext = context; + mProfile = profile; mLayoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } @@ -119,7 +122,7 @@ */ public void start() { refreshData(); - TemplateUrlServiceFactory.get().addObserver(this); + TemplateUrlServiceFactory.getForProfile(mProfile).addObserver(this); } /** @@ -127,11 +130,11 @@ */ public void stop() { if (mHasLoadObserver) { - TemplateUrlServiceFactory.get().unregisterLoadListener(this); + TemplateUrlServiceFactory.getForProfile(mProfile).unregisterLoadListener(this); mHasLoadObserver = false; } - TemplateUrlServiceFactory.get().removeObserver(this); + TemplateUrlServiceFactory.getForProfile(mProfile).removeObserver(this); } @VisibleForTesting @@ -153,7 +156,7 @@ * Initialize the search engine list. */ private void refreshData() { - TemplateUrlService templateUrlService = TemplateUrlServiceFactory.get(); + TemplateUrlService templateUrlService = TemplateUrlServiceFactory.getForProfile(mProfile); if (!templateUrlService.isLoaded()) { mHasLoadObserver = true; templateUrlService.registerLoadListener(this); @@ -201,11 +204,11 @@ } if (mSelectedSearchEnginePosition == -1) { - throw new IllegalStateException( - String.format("Default search engine is not found in available search engines:" - + " DSE is valid=%b, is managed=%b", - defaultSearchEngineTemplateUrl != null, - TemplateUrlServiceFactory.get().isDefaultSearchManaged())); + throw new IllegalStateException(String.format( + "Default search engine is not found in available search engines:" + + " DSE is valid=%b, is managed=%b", + defaultSearchEngineTemplateUrl != null, + TemplateUrlServiceFactory.getForProfile(mProfile).isDefaultSearchManaged())); } mInitialEnginePosition = mSelectedSearchEnginePosition; @@ -409,7 +412,7 @@ @Override public void onTemplateUrlServiceLoaded() { - TemplateUrlServiceFactory.get().unregisterLoadListener(this); + TemplateUrlServiceFactory.getForProfile(mProfile).unregisterLoadListener(this); mHasLoadObserver = false; refreshData(); } @@ -431,7 +434,7 @@ mSelectedSearchEnginePosition = position; String keyword = toKeyword(mSelectedSearchEnginePosition); - TemplateUrlServiceFactory.get().setSearchEngine(keyword); + TemplateUrlServiceFactory.getForProfile(mProfile).setSearchEngine(keyword); // If the user has manually set the default search engine, disable auto switching. boolean manualSwitch = mSelectedSearchEnginePosition != mInitialEnginePosition; @@ -450,8 +453,9 @@ return ""; } - String url = TemplateUrlServiceFactory.get().getSearchEngineUrlFromTemplateUrl( - templateUrl.getKeyword()); + String url = + TemplateUrlServiceFactory.getForProfile(mProfile).getSearchEngineUrlFromTemplateUrl( + templateUrl.getKeyword()); if (url == null) { Log.e(TAG, "Invalid template URL found: %s", templateUrl); assert false; @@ -467,8 +471,7 @@ PermissionInfo locationSettings = new PermissionInfo(ContentSettingsType.GEOLOCATION, url, null, false); - return locationSettings.getContentSetting(Profile.getLastUsedRegularProfile()) - == ContentSettingValues.ALLOW; + return locationSettings.getContentSetting(mProfile) == ContentSettingValues.ALLOW; } private int computeStartIndexForRecentSearchEngines() {
diff --git a/chrome/browser/search_engines/android/java/src/org/chromium/chrome/browser/search_engines/settings/SearchEngineSettings.java b/chrome/browser/search_engines/android/java/src/org/chromium/chrome/browser/search_engines/settings/SearchEngineSettings.java index a6efb82d..b83645b 100644 --- a/chrome/browser/search_engines/android/java/src/org/chromium/chrome/browser/search_engines/settings/SearchEngineSettings.java +++ b/chrome/browser/search_engines/android/java/src/org/chromium/chrome/browser/search_engines/settings/SearchEngineSettings.java
@@ -11,7 +11,9 @@ import androidx.annotation.VisibleForTesting; import androidx.fragment.app.ListFragment; +import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.search_engines.R; +import org.chromium.chrome.browser.settings.ProfileDependentSetting; import org.chromium.components.browser_ui.settings.SettingsLauncher; /** @@ -21,8 +23,9 @@ * * TODO(crbug.com/988877): Add on scroll shadow to action bar. */ -public class SearchEngineSettings extends ListFragment { +public class SearchEngineSettings extends ListFragment implements ProfileDependentSetting { private SearchEngineAdapter mSearchEngineAdapter; + private Profile mProfile; @VisibleForTesting String getValueForTesting() { @@ -88,6 +91,12 @@ private void createAdapterIfNecessary() { if (mSearchEngineAdapter != null) return; - mSearchEngineAdapter = new SearchEngineAdapter(getActivity()); + assert mProfile != null; + mSearchEngineAdapter = new SearchEngineAdapter(getActivity(), mProfile); + } + + @Override + public void setProfile(Profile profile) { + mProfile = profile; } }
diff --git a/chrome/browser/sharing_hub/sharing_hub_features.cc b/chrome/browser/sharing_hub/sharing_hub_features.cc index 8a3b38e..8f2719dd 100644 --- a/chrome/browser/sharing_hub/sharing_hub_features.cc +++ b/chrome/browser/sharing_hub/sharing_hub_features.cc
@@ -16,17 +16,15 @@ namespace { -#if !BUILDFLAG(IS_CHROMEOS) // Whether the sharing hub feature should be disabled by policy. bool SharingHubDisabledByPolicy(content::BrowserContext* context) { -#if !BUILDFLAG(IS_ANDROID) +#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS) const PrefService* prefs = Profile::FromBrowserContext(context)->GetPrefs(); return !prefs->GetBoolean(prefs::kDesktopSharingHubEnabled); #else return false; #endif } -#endif // !BUILDFLAG(IS_CHROMEOS) // Whether screenshots-related features should be disabled by policy. // Currently used by desktop. @@ -56,6 +54,12 @@ !ScreenshotsDisabledByPolicy(context); } +bool SharingIsDisabledByPolicy(content::BrowserContext* context) { + // TODO(ellyjones): should we separate out sharing hub from generic sharing? + // Or should we rename the policy to be more general? + return SharingHubDisabledByPolicy(context); +} + bool HasPageAction(content::BrowserContext* context, bool is_popup_mode) { #if BUILDFLAG(IS_CHROMEOS) return true;
diff --git a/chrome/browser/sharing_hub/sharing_hub_features.h b/chrome/browser/sharing_hub/sharing_hub_features.h index 69271f16..3df8cbbe6 100644 --- a/chrome/browser/sharing_hub/sharing_hub_features.h +++ b/chrome/browser/sharing_hub/sharing_hub_features.h
@@ -33,6 +33,10 @@ // image editor before sharing. bool DesktopScreenshotsFeatureEnabled(content::BrowserContext* context); +// Returns whether sharing is disabled altogether, in which case entry points +// for sharing should be hidden. +bool SharingIsDisabledByPolicy(content::BrowserContext* context); + // Feature flag to enable the screenshots feature, currently accessed only // through the sharing hub. BASE_DECLARE_FEATURE(kDesktopScreenshots);
diff --git a/chrome/browser/signin/signin_features.cc b/chrome/browser/signin/signin_features.cc index d26c0eb..e84c69e 100644 --- a/chrome/browser/signin/signin_features.cc +++ b/chrome/browser/signin/signin_features.cc
@@ -31,16 +31,20 @@ /*default_value=*/SigninPromoVariant::kSignIn, /*options=*/&kSignInPromoVariantOptions}; -// Feature that indicates that we should put the client in a study group to -// be able to look at metrics in the long term. Does not affect the client's -// behavior by itself, instead this is done through the `kForYouFre` feature. -BASE_FEATURE(kForYouFreStudy, - "ForYouFreStudy", +// Feature that indicates that we should put the client in a study group +// (provided through `kForYouFreStudyGroup`) to be able to look at metrics in +// the long term. Does not affect the client's behavior by itself, instead this +// is done through the `kForYouFre` feature. +BASE_FEATURE(kForYouFreSyntheticTrialRegistration, + "ForYouFreSyntheticTrialRegistration", base::FEATURE_DISABLED_BY_DEFAULT); + // String that refers to the study group in which this install was enrolled. -// Used to implement the sticky experiment tracking. +// Used to implement the sticky experiment tracking. If the value is an empty +// string, we don't register the client. const base::FeatureParam<std::string> kForYouFreStudyGroup{ - &kForYouFreStudy, /*name=*/"group_name", /*default_value=*/""}; + &kForYouFreSyntheticTrialRegistration, /*name=*/"group_name", + /*default_value=*/""}; #endif // BUILDFLAG(ENABLE_DICE_SUPPORT) #endif // !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_ANDROID)
diff --git a/chrome/browser/signin/signin_features.h b/chrome/browser/signin/signin_features.h index 1c6f04a..6b86c40 100644 --- a/chrome/browser/signin/signin_features.h +++ b/chrome/browser/signin/signin_features.h
@@ -19,7 +19,7 @@ extern const base::FeatureParam<SigninPromoVariant> kForYouFreSignInPromoVariant; -BASE_DECLARE_FEATURE(kForYouFreStudy); +BASE_DECLARE_FEATURE(kForYouFreSyntheticTrialRegistration); extern const base::FeatureParam<std::string> kForYouFreStudyGroup; #endif // BUILDFLAG(ENABLE_DICE_SUPPORT)
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 7faa95e8..d3511bd 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -2318,6 +2318,10 @@ "ash/fwupd_download_client_impl.h", "ash/glanceables/chrome_glanceables_delegate.cc", "ash/glanceables/chrome_glanceables_delegate.h", + "ash/glanceables/glanceables_keyed_service.cc", + "ash/glanceables/glanceables_keyed_service.h", + "ash/glanceables/glanceables_keyed_service_factory.cc", + "ash/glanceables/glanceables_keyed_service_factory.h", "ash/global_media_controls/cast_media_notification_producer_keyed_service.cc", "ash/global_media_controls/cast_media_notification_producer_keyed_service.h", "ash/global_media_controls/cast_media_notification_producer_keyed_service_factory.cc", @@ -3349,8 +3353,8 @@ "//components/assist_ranker/proto", "//components/captive_portal/core", "//components/consent_auditor:consent_auditor", + "//components/content_relationship_verification", "//components/desks_storage", - "//components/digital_asset_links", "//components/endpoint_fetcher", "//components/exo", "//components/login", @@ -3996,15 +4000,15 @@ "views/chrome_cleaner_reboot_dialog_win.h", "views/critical_notification_bubble_view.cc", "views/critical_notification_bubble_view.h", + "views/frame/browser_caption_button_container_win.cc", + "views/frame/browser_caption_button_container_win.h", "views/frame/browser_desktop_window_tree_host.h", "views/frame/browser_desktop_window_tree_host_win.cc", "views/frame/browser_desktop_window_tree_host_win.h", + "views/frame/browser_frame_view_win.cc", + "views/frame/browser_frame_view_win.h", "views/frame/browser_window_property_manager_win.cc", "views/frame/browser_window_property_manager_win.h", - "views/frame/glass_browser_caption_button_container.cc", - "views/frame/glass_browser_caption_button_container.h", - "views/frame/glass_browser_frame_view.cc", - "views/frame/glass_browser_frame_view.h", "views/frame/minimize_button_metrics_win.cc", "views/frame/minimize_button_metrics_win.h", "views/frame/native_browser_frame_factory_aura.cc",
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalSuggestionProcessor.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalSuggestionProcessor.java index c038242..a09cbbe 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalSuggestionProcessor.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalSuggestionProcessor.java
@@ -105,18 +105,18 @@ final List<ListItem> modelList = new ArrayList<>(pedalsCount); for (OmniboxPedal chip : omniboxPedalList) { - final var chipModel = new PropertyModel.Builder(ChipProperties.ALL_KEYS) - .with(ChipProperties.TEXT, chip.getHint()) - .build(); - - // Apply changes manually to investigate bizarre CQ finding. final var chipIcon = mOmniboxPedalDelegate.getIcon(chip); - chipModel.set(ChipProperties.CONTENT_DESCRIPTION, - mContext.getString(R.string.accessibility_omnibox_pedal, chip.getHint())); - chipModel.set(ChipProperties.ENABLED, true); - chipModel.set(ChipProperties.CLICK_HANDLER, m -> executeAction(chip, position)); - chipModel.set(ChipProperties.ICON, chipIcon.iconRes); - chipModel.set(ChipProperties.APPLY_ICON_TINT, chipIcon.tintWithTextColor); + final var chipModel = + new PropertyModel.Builder(ChipProperties.ALL_KEYS) + .with(ChipProperties.TEXT, chip.getHint()) + .with(ChipProperties.CONTENT_DESCRIPTION, + mContext.getString( + R.string.accessibility_omnibox_pedal, chip.getHint())) + .with(ChipProperties.ENABLED, true) + .with(ChipProperties.CLICK_HANDLER, m -> executeAction(chip, position)) + .with(ChipProperties.ICON, chipIcon.iconRes) + .with(ChipProperties.APPLY_ICON_TINT, chipIcon.tintWithTextColor) + .build(); modelList.add( new ListItem(PedalSuggestionViewProperties.ViewType.PEDAL_VIEW, chipModel));
diff --git a/chrome/browser/ui/ash/desks/chrome_saved_desk_delegate.cc b/chrome/browser/ui/ash/desks/chrome_saved_desk_delegate.cc index 822e8b4c..21dc7d3 100644 --- a/chrome/browser/ui/ash/desks/chrome_saved_desk_delegate.cc +++ b/chrome/browser/ui/ash/desks/chrome_saved_desk_delegate.cc
@@ -4,8 +4,6 @@ #include "chrome/browser/ui/ash/desks/chrome_saved_desk_delegate.h" -#include "ash/constants/app_types.h" -#include "ash/constants/ash_features.h" #include "ash/constants/notifier_catalogs.h" #include "ash/public/cpp/desk_template.h" #include "ash/public/cpp/system/toast_data.h" @@ -13,7 +11,6 @@ #include "ash/strings/grit/ash_strings.h" #include "base/check.h" #include "base/functional/bind.h" -#include "base/strings/string_number_conversions.h" #include "chrome/app/vector_icons/vector_icons.h" #include "chrome/browser/apps/app_service/app_service_proxy.h" #include "chrome/browser/apps/app_service/app_service_proxy_factory.h" @@ -29,28 +26,22 @@ #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/ash/desks/chrome_desks_util.h" #include "chrome/browser/ui/ash/desks/desks_client.h" -#include "chrome/browser/ui/browser_commands.h" -#include "chrome/browser/ui/browser_tabstrip.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/common/webui_url_constants.h" #include "chrome/grit/theme_resources.h" #include "components/app_constants/constants.h" #include "components/app_restore/app_launch_info.h" #include "components/app_restore/app_restore_data.h" -#include "components/app_restore/app_restore_utils.h" #include "components/app_restore/full_restore_save_handler.h" #include "components/app_restore/full_restore_utils.h" #include "components/app_restore/restore_data.h" #include "components/app_restore/window_properties.h" #include "components/favicon/core/favicon_service.h" -#include "components/favicon_base/favicon_util.h" #include "components/services/app_service/public/cpp/app_registry_cache.h" #include "components/services/app_service/public/cpp/app_types.h" #include "components/services/app_service/public/cpp/intent.h" #include "components/services/app_service/public/cpp/types_util.h" #include "components/user_manager/user_manager.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/window.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/models/image_model.h" #include "ui/base/resource/resource_bundle.h" @@ -58,7 +49,6 @@ #include "ui/color/color_id.h" #include "ui/color/color_provider.h" #include "ui/gfx/image/image_skia.h" -#include "ui/gfx/paint_vector_icon.h" #include "url/gurl.h" namespace { @@ -167,22 +157,23 @@ ash::ToastManager::Get()->Show(std::move(toast_data)); } -// Creates a callback for when a favicon image is retrieved which creates a -// standard icon image and then calls `callback` with the standardized image. +// Creates a standard icon image via `result`, and then calls `callback` with +// the standardized image. // TODO(crbug.com/1318250): Remove this once non-lacros browser is not // supported. -base::OnceCallback<void(const favicon_base::FaviconImageResult&)> -ImageResultToImageSkia( - base::OnceCallback<void(const gfx::ImageSkia&)> callback) { - return base::BindOnce( - [](base::OnceCallback<void(const gfx::ImageSkia&)> image_skia_callback, - const favicon_base::FaviconImageResult& result) { - auto image = result.image.AsImageSkia(); - image.EnsureRepsForSupportedScales(); - std::move(image_skia_callback) - .Run(apps::CreateStandardIconImage(image)); - }, - std::move(callback)); +void ImageResultToImageSkia( + base::OnceCallback<void(const gfx::ImageSkia&)> callback, + const favicon_base::FaviconRawBitmapResult& result) { + if (!result.is_valid()) { + std::move(callback).Run(gfx::ImageSkia()); + return; + } + + auto image = gfx::Image::CreateFrom1xPNGBytes(result.bitmap_data->front(), + result.bitmap_data->size()) + .AsImageSkia(); + image.EnsureRepsForSupportedScales(); + std::move(callback).Run(apps::CreateStandardIconImage(image)); } // Creates a callback for when a app icon image is retrieved which creates a @@ -378,8 +369,10 @@ ProfileManager::GetActiveUserProfile(), ServiceAccessType::EXPLICIT_ACCESS); - favicon_service->GetFaviconImageForPageURL( - GURL(page_url), ImageResultToImageSkia(std::move(callback)), tracker); + favicon_service->GetRawFaviconForPageURL( + GURL(page_url), {favicon_base::IconType::kFavicon}, 0, + /*fallback_to_host=*/false, + base::BindOnce(&ImageResultToImageSkia, std::move(callback)), tracker); } void ChromeSavedDeskDelegate::GetIconForAppId(
diff --git a/chrome/browser/ui/ash/desks/chrome_saved_desk_delegate.h b/chrome/browser/ui/ash/desks/chrome_saved_desk_delegate.h index b2b8448e..6a821491 100644 --- a/chrome/browser/ui/ash/desks/chrome_saved_desk_delegate.h +++ b/chrome/browser/ui/ash/desks/chrome_saved_desk_delegate.h
@@ -11,8 +11,10 @@ #include "base/functional/callback_forward.h" #include "base/memory/weak_ptr.h" #include "chromeos/crosapi/mojom/desk_template.mojom-forward.h" -#include "components/favicon_base/favicon_types.h" -#include "components/services/app_service/public/cpp/icon_types.h" + +namespace aura { +class Window; +} // namespace aura namespace base { class CancelableTaskTracker;
diff --git a/chrome/browser/ui/ash/glanceables/glanceables_keyed_service.cc b/chrome/browser/ui/ash/glanceables/glanceables_keyed_service.cc new file mode 100644 index 0000000..af3f3e2 --- /dev/null +++ b/chrome/browser/ui/ash/glanceables/glanceables_keyed_service.cc
@@ -0,0 +1,15 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/ash/glanceables/glanceables_keyed_service.h" + +namespace ash { + +GlanceablesKeyedService::GlanceablesKeyedService() = default; + +GlanceablesKeyedService::~GlanceablesKeyedService() = default; + +void GlanceablesKeyedService::Shutdown() {} + +} // namespace ash
diff --git a/chrome/browser/ui/ash/glanceables/glanceables_keyed_service.h b/chrome/browser/ui/ash/glanceables/glanceables_keyed_service.h new file mode 100644 index 0000000..f02347a --- /dev/null +++ b/chrome/browser/ui/ash/glanceables/glanceables_keyed_service.h
@@ -0,0 +1,28 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_ASH_GLANCEABLES_GLANCEABLES_KEYED_SERVICE_H_ +#define CHROME_BROWSER_UI_ASH_GLANCEABLES_GLANCEABLES_KEYED_SERVICE_H_ + +#include "components/keyed_service/core/keyed_service.h" + +namespace ash { + +// Browser context keyed service that owns implementations of interfaces from +// ash/ needed to communicate with different Google services as part of +// Glanceables project. +class GlanceablesKeyedService : public KeyedService { + public: + GlanceablesKeyedService(); + GlanceablesKeyedService(const GlanceablesKeyedService&) = delete; + GlanceablesKeyedService& operator=(const GlanceablesKeyedService&) = delete; + ~GlanceablesKeyedService() override; + + // KeyedService: + void Shutdown() override; +}; + +} // namespace ash + +#endif // CHROME_BROWSER_UI_ASH_GLANCEABLES_GLANCEABLES_KEYED_SERVICE_H_
diff --git a/chrome/browser/ui/ash/glanceables/glanceables_keyed_service_factory.cc b/chrome/browser/ui/ash/glanceables/glanceables_keyed_service_factory.cc new file mode 100644 index 0000000..09229d0 --- /dev/null +++ b/chrome/browser/ui/ash/glanceables/glanceables_keyed_service_factory.cc
@@ -0,0 +1,40 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/ash/glanceables/glanceables_keyed_service_factory.h" + +#include <memory> + +#include "ash/constants/ash_features.h" +#include "base/no_destructor.h" +#include "chrome/browser/profiles/profile_selections.h" +#include "chrome/browser/ui/ash/glanceables/glanceables_keyed_service.h" +#include "content/public/browser/browser_context.h" + +namespace ash { + +// static +GlanceablesKeyedServiceFactory* GlanceablesKeyedServiceFactory::GetInstance() { + static base::NoDestructor<GlanceablesKeyedServiceFactory> factory; + return factory.get(); +} + +GlanceablesKeyedServiceFactory::GlanceablesKeyedServiceFactory() + : ProfileKeyedServiceFactory("GlanceablesKeyedService", + ProfileSelections::BuildForRegularProfile()) {} + +GlanceablesKeyedService* GlanceablesKeyedServiceFactory::GetService( + content::BrowserContext* context) { + return static_cast<GlanceablesKeyedService*>( + GetInstance()->GetServiceForBrowserContext( + context, /*create=*/features::AreGlanceablesV2Enabled())); +} + +std::unique_ptr<KeyedService> +GlanceablesKeyedServiceFactory::BuildServiceInstanceForBrowserContext( + content::BrowserContext* context) const { + return std::make_unique<GlanceablesKeyedService>(); +} + +} // namespace ash
diff --git a/chrome/browser/ui/ash/glanceables/glanceables_keyed_service_factory.h b/chrome/browser/ui/ash/glanceables/glanceables_keyed_service_factory.h new file mode 100644 index 0000000..721f2485 --- /dev/null +++ b/chrome/browser/ui/ash/glanceables/glanceables_keyed_service_factory.h
@@ -0,0 +1,46 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_ASH_GLANCEABLES_GLANCEABLES_KEYED_SERVICE_FACTORY_H_ +#define CHROME_BROWSER_UI_ASH_GLANCEABLES_GLANCEABLES_KEYED_SERVICE_FACTORY_H_ + +#include <memory> + +#include "base/no_destructor.h" +#include "chrome/browser/profiles/profile_keyed_service_factory.h" + +namespace content { +class BrowserContext; +} // namespace content + +namespace ash { + +class GlanceablesKeyedService; + +// Factory class for `GlanceablesKeyedService`. Creates instances of that +// service for regular profiles only. +class GlanceablesKeyedServiceFactory : public ProfileKeyedServiceFactory { + public: + GlanceablesKeyedServiceFactory(const GlanceablesKeyedServiceFactory&) = + delete; + GlanceablesKeyedServiceFactory& operator=( + const GlanceablesKeyedServiceFactory&) = delete; + + static GlanceablesKeyedServiceFactory* GetInstance(); + + GlanceablesKeyedService* GetService(content::BrowserContext* context); + + protected: + // BrowserContextKeyedServiceFactory: + std::unique_ptr<KeyedService> BuildServiceInstanceForBrowserContext( + content::BrowserContext* context) const override; + + private: + friend base::NoDestructor<GlanceablesKeyedServiceFactory>; + GlanceablesKeyedServiceFactory(); +}; + +} // namespace ash + +#endif // CHROME_BROWSER_UI_ASH_GLANCEABLES_GLANCEABLES_KEYED_SERVICE_FACTORY_H_
diff --git a/chrome/browser/ui/ash/glanceables/glanceables_keyed_service_factory_unittest.cc b/chrome/browser/ui/ash/glanceables/glanceables_keyed_service_factory_unittest.cc new file mode 100644 index 0000000..24b205e6 --- /dev/null +++ b/chrome/browser/ui/ash/glanceables/glanceables_keyed_service_factory_unittest.cc
@@ -0,0 +1,101 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/ash/glanceables/glanceables_keyed_service_factory.h" + +#include <memory> + +#include "ash/constants/ash_features.h" +#include "base/test/scoped_feature_list.h" +#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" +#include "chrome/browser/ui/ash/glanceables/glanceables_keyed_service.h" +#include "chrome/test/base/browser_with_test_window_test.h" +#include "chrome/test/base/testing_profile.h" +#include "chrome/test/base/testing_profile_manager.h" +#include "components/sync_preferences/pref_service_syncable.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace ash { + +class GlanceablesKeyedServiceFactoryTest : public BrowserWithTestWindowTest { + public: + GlanceablesKeyedServiceFactoryTest() + : user_manager_(std::make_unique<FakeChromeUserManager>()) {} + + TestingProfileManager* profile_manager() { + return BrowserWithTestWindowTest::profile_manager(); + } + + protected: + base::test::ScopedFeatureList feature_list_{features::kGlanceablesV2}; + std::unique_ptr<FakeChromeUserManager> user_manager_; +}; + +TEST_F(GlanceablesKeyedServiceFactoryTest, NoSupportWhenFeatureIsDisabled) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndDisableFeature(features::kGlanceablesV2); + + EXPECT_FALSE( + GlanceablesKeyedServiceFactory::GetInstance()->GetService(GetProfile())); +} + +TEST_F(GlanceablesKeyedServiceFactoryTest, NoSupportForGuestProfile) { + std::unique_ptr<TestingProfile> guest_profile = + TestingProfile::Builder() + .SetGuestSession() + .SetProfileName("guest_profile") + .AddTestingFactories({}) + .Build(); + ASSERT_TRUE(guest_profile); + + auto* service = GlanceablesKeyedServiceFactory::GetInstance()->GetService( + guest_profile.get()); + EXPECT_FALSE(service); +} + +TEST_F(GlanceablesKeyedServiceFactoryTest, NoSupportForOffTheRecordProfile) { + auto* service_for_primary_profile = + GlanceablesKeyedServiceFactory::GetInstance()->GetService(GetProfile()); + EXPECT_TRUE(service_for_primary_profile); + + TestingProfile* incognito_profile = + TestingProfile::Builder() + .SetProfileName(GetProfile()->GetProfileUserName()) + .BuildIncognito(GetProfile()); + ASSERT_TRUE(incognito_profile); + ASSERT_TRUE(incognito_profile->IsOffTheRecord()); + + auto* service_for_incognito_profile = + GlanceablesKeyedServiceFactory::GetInstance()->GetService( + incognito_profile); + EXPECT_FALSE(service_for_incognito_profile); +} + +TEST_F(GlanceablesKeyedServiceFactoryTest, SupportsMultipleUserProfiles) { + auto* service_1 = + GlanceablesKeyedServiceFactory::GetInstance()->GetService(GetProfile()); + + // Returns the same instance for the same profile. + EXPECT_EQ( + service_1, + GlanceablesKeyedServiceFactory::GetInstance()->GetService(GetProfile())); + + const std::string second_profile_name = "second_profile"; + const AccountId account_id(AccountId::FromUserEmail(second_profile_name)); + user_manager_->AddUser(account_id); + user_manager_->LoginUser(account_id); + TestingProfile* second_profile = profile_manager()->CreateTestingProfile( + second_profile_name, + std::unique_ptr<sync_preferences::PrefServiceSyncable>(), + u"Test profile 2", + /*avatar_id=*/1, + /*testing_factories=*/{}); + + // Returns different instances for different profiles. + EXPECT_NE(service_1, + GlanceablesKeyedServiceFactory::GetInstance()->GetService( + second_profile)); +} + +} // namespace ash
diff --git a/chrome/browser/ui/ash/projector/projector_app_client_impl.cc b/chrome/browser/ui/ash/projector/projector_app_client_impl.cc index 398c8415..3c5b06b 100644 --- a/chrome/browser/ui/ash/projector/projector_app_client_impl.cc +++ b/chrome/browser/ui/ash/projector/projector_app_client_impl.cc
@@ -9,7 +9,7 @@ #include "ash/constants/ash_features.h" #include "ash/constants/ash_pref_names.h" #include "ash/public/cpp/projector/annotator_tool.h" -#include "ash/webui/projector_app/annotator_message_handler.h" +#include "ash/webui/projector_app/annotator_page_handler_impl.h" #include "ash/webui/projector_app/public/cpp/projector_app_constants.h" #include "base/functional/bind.h" #include "chrome/browser/ash/profiles/profile_helper.h" @@ -155,26 +155,26 @@ std::move(callback)); } -void ProjectorAppClientImpl::SetAnnotatorMessageHandler( - ash::AnnotatorMessageHandler* handler) { - annotator_message_handler_ = handler; +void ProjectorAppClientImpl::SetAnnotatorPageHandler( + ash::AnnotatorPageHandlerImpl* handler) { + annotator_handler_ = handler; } -void ProjectorAppClientImpl::ResetAnnotatorMessageHandler( - ash::AnnotatorMessageHandler* handler) { - if (annotator_message_handler_ == handler) { - annotator_message_handler_ = nullptr; +void ProjectorAppClientImpl::ResetAnnotatorPageHandler( + ash::AnnotatorPageHandlerImpl* handler) { + if (annotator_handler_ == handler) { + annotator_handler_ = nullptr; } } void ProjectorAppClientImpl::SetTool(const ash::AnnotatorTool& tool) { - DCHECK(annotator_message_handler_); - annotator_message_handler_->SetTool(tool); + DCHECK(annotator_handler_); + annotator_handler_->SetTool(tool); } void ProjectorAppClientImpl::Clear() { - DCHECK(annotator_message_handler_); - annotator_message_handler_->Clear(); + DCHECK(annotator_handler_); + annotator_handler_->Clear(); } void ProjectorAppClientImpl::NotifyAppUIActive(bool active) {
diff --git a/chrome/browser/ui/ash/projector/projector_app_client_impl.h b/chrome/browser/ui/ash/projector/projector_app_client_impl.h index ffa0731..a25a270 100644 --- a/chrome/browser/ui/ash/projector/projector_app_client_impl.h +++ b/chrome/browser/ui/ash/projector/projector_app_client_impl.h
@@ -8,7 +8,7 @@ #include <memory> #include "ash/public/cpp/projector/projector_annotator_controller.h" -#include "ash/webui/projector_app/annotator_message_handler.h" +#include "ash/webui/projector_app/annotator_page_handler_impl.h" #include "ash/webui/projector_app/projector_app_client.h" #include "base/observer_list.h" #include "chrome/browser/ui/ash/projector/pending_screencast_manager.h" @@ -24,10 +24,6 @@ class PrefRegistrySyncable; } // namespace user_prefs -namespace ash { -class AnnotatorMessageHandler; -} // namespace ash - // Implements the interface for Projector App. class ProjectorAppClientImpl : public ash::ProjectorAppClient { public: @@ -56,10 +52,9 @@ const std::string& video_file_id, const std::string& resource_key, ash::ProjectorAppClient::OnGetVideoCallback callback) const override; - void SetAnnotatorMessageHandler( - ash::AnnotatorMessageHandler* handler) override; - void ResetAnnotatorMessageHandler( - ash::AnnotatorMessageHandler* handler) override; + void SetAnnotatorPageHandler(ash::AnnotatorPageHandlerImpl* handler) override; + void ResetAnnotatorPageHandler( + ash::AnnotatorPageHandlerImpl* handler) override; void SetTool(const ash::AnnotatorTool& tool) override; void Clear() override; void NotifyAppUIActive(bool active) override; @@ -67,8 +62,8 @@ const std::vector<base::FilePath>& screencast_paths, bool suppress) override; - ash::AnnotatorMessageHandler* get_annotator_message_handler_for_test() { - return annotator_message_handler_; + ash::AnnotatorPageHandlerImpl* get_annotator_handler_for_test() { + return annotator_handler_; } PendingScreencastManager* get_pending_screencast_manager_for_test() { return &pending_screencast_manager_; @@ -85,7 +80,7 @@ ash::ScreencastManager screencast_manager_; - ash::AnnotatorMessageHandler* annotator_message_handler_ = nullptr; + ash::AnnotatorPageHandlerImpl* annotator_handler_ = nullptr; }; #endif // CHROME_BROWSER_UI_ASH_PROJECTOR_PROJECTOR_APP_CLIENT_IMPL_H_
diff --git a/chrome/browser/ui/autofill/autofill_context_menu_manager_unittest.cc b/chrome/browser/ui/autofill/autofill_context_menu_manager_unittest.cc index 7ae98b87..a73044b 100644 --- a/chrome/browser/ui/autofill/autofill_context_menu_manager_unittest.cc +++ b/chrome/browser/ui/autofill/autofill_context_menu_manager_unittest.cc
@@ -153,7 +153,7 @@ }; // Tests that the Autofill context menu is correctly set up. -TEST_F(AutofillContextMenuManagerTest, AutofillContextMenuContents) { +TEST_F(AutofillContextMenuManagerTest, DISABLED_AutofillContextMenuContents) { autofill_context_menu_manager()->AppendItems(); std::vector<std::u16string> all_added_strings; @@ -260,7 +260,7 @@ // For all the command ids that are used to set up the context menu, initiating // filling for each one of them results in the call to // `RendererShouldFillFieldWithValue`. -TEST_F(AutofillContextMenuManagerTest, ExecuteCommand) { +TEST_F(AutofillContextMenuManagerTest, DISABLED_ExecuteCommand) { DCHECK(driver()); autofill_context_menu_manager()->AppendItems(); auto mapper = autofill_context_menu_manager() @@ -289,7 +289,8 @@ // Tests that the Autofill's ContentAutofillDriver is called to record metrics // when the context menu is triggered on a field. -TEST_F(AutofillContextMenuManagerTest, RecordContextMenuIsShownOnField) { +TEST_F(AutofillContextMenuManagerTest, + DISABLED_RecordContextMenuIsShownOnField) { FormRendererId form_renderer_id(test::MakeFormRendererId()); FieldRendererId field_renderer_id(test::MakeFieldRendererId()); autofill_context_menu_manager()->set_params_for_testing(
diff --git a/chrome/browser/ui/autofill/payments/save_card_bubble_controller.h b/chrome/browser/ui/autofill/payments/save_card_bubble_controller.h index 1fe849e..7036eb0 100644 --- a/chrome/browser/ui/autofill/payments/save_card_bubble_controller.h +++ b/chrome/browser/ui/autofill/payments/save_card_bubble_controller.h
@@ -22,7 +22,6 @@ namespace autofill { class CreditCard; -class AutofillBubbleBase; enum class BubbleType; // Interface that exposes controller functionality to save card bubbles. @@ -64,10 +63,6 @@ // Returns the card that will be uploaded if the user accepts. virtual const CreditCard& GetCard() const = 0; - // Returns the currently active save card bubble view. Can be nullptr if no - // bubble is visible. - virtual AutofillBubbleBase* GetSaveCardBubbleView() const = 0; - // Returns whether the dialog should include a textfield requesting the user // to confirm/provide cardholder name. virtual bool ShouldRequestNameFromUser() const = 0;
diff --git a/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl.cc b/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl.cc index 98e1f9b..c1dccd0 100644 --- a/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl.cc +++ b/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl.cc
@@ -259,16 +259,6 @@ return card_; } -AutofillBubbleBase* SaveCardBubbleControllerImpl::GetSaveCardBubbleView() - const { - return bubble_view(); -} - -SavePaymentIconController::PaymentBubbleType -SaveCardBubbleControllerImpl::GetPaymentBubbleType() const { - return PaymentBubbleType::kCreditCard; -} - bool SaveCardBubbleControllerImpl::ShouldRequestNameFromUser() const { return options_.should_request_name_from_user; } @@ -471,7 +461,12 @@ } AutofillBubbleBase* SaveCardBubbleControllerImpl::GetPaymentBubbleView() const { - return GetSaveCardBubbleView(); + return bubble_view(); +} + +SavePaymentIconController::PaymentBubbleType +SaveCardBubbleControllerImpl::GetPaymentBubbleType() const { + return PaymentBubbleType::kCreditCard; } PageActionIconType SaveCardBubbleControllerImpl::GetPageActionIconType() {
diff --git a/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl.h b/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl.h index d416b487..2a368cb 100644 --- a/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl.h +++ b/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl.h
@@ -118,7 +118,6 @@ const AccountInfo& GetAccountInfo() override; Profile* GetProfile() const override; const CreditCard& GetCard() const override; - AutofillBubbleBase* GetSaveCardBubbleView() const override; bool ShouldRequestNameFromUser() const override; bool ShouldRequestExpirationDateFromUser() const override;
diff --git a/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl_browsertest.cc b/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl_browsertest.cc index 8109fd1a..29c42e6 100644 --- a/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl_browsertest.cc +++ b/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl_browsertest.cc
@@ -170,14 +170,14 @@ // Tests that opening a new tab will hide the save card bubble. IN_PROC_BROWSER_TEST_F(SaveCardBubbleControllerImplTest, NewTabHidesDialog) { ShowUi("Local"); - EXPECT_NE(nullptr, controller()->GetSaveCardBubbleView()); + EXPECT_NE(nullptr, controller()->GetPaymentBubbleView()); // Open a new tab page in the foreground. ui_test_utils::NavigateToURLWithDisposition( browser(), GURL(chrome::kChromeUINewTabURL), WindowOpenDisposition::NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB | ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP); - EXPECT_EQ(nullptr, controller()->GetSaveCardBubbleView()); + EXPECT_EQ(nullptr, controller()->GetPaymentBubbleView()); } } // namespace autofill
diff --git a/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl_unittest.cc b/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl_unittest.cc index e0d0f2de..50bc11d6 100644 --- a/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl_unittest.cc +++ b/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl_unittest.cc
@@ -498,7 +498,7 @@ // After closing the sign-in promo, clicking the icon should bring // up the Manage cards bubble. EXPECT_EQ(BubbleType::MANAGE_CARDS, controller()->GetBubbleType()); - EXPECT_NE(nullptr, controller()->GetSaveCardBubbleView()); + EXPECT_NE(nullptr, controller()->GetPaymentBubbleView()); } TEST_F(SaveCardBubbleControllerImplTest, @@ -570,7 +570,7 @@ // Icon should disappear after an upload save, // even when this flag is enabled. EXPECT_FALSE(controller()->IsIconVisible()); - EXPECT_EQ(nullptr, controller()->GetSaveCardBubbleView()); + EXPECT_EQ(nullptr, controller()->GetPaymentBubbleView()); } TEST_F(SaveCardBubbleControllerImplTest,
diff --git a/chrome/browser/ui/blocked_content/chrome_popup_navigation_delegate.cc b/chrome/browser/ui/blocked_content/chrome_popup_navigation_delegate.cc index 3bf775a4..d6be84f 100644 --- a/chrome/browser/ui/blocked_content/chrome_popup_navigation_delegate.cc +++ b/chrome/browser/ui/blocked_content/chrome_popup_navigation_delegate.cc
@@ -37,7 +37,7 @@ return original_user_gesture_; } -const GURL& ChromePopupNavigationDelegate::GetURL() { +GURL ChromePopupNavigationDelegate::GetURL() { return params_.url; }
diff --git a/chrome/browser/ui/blocked_content/chrome_popup_navigation_delegate.h b/chrome/browser/ui/blocked_content/chrome_popup_navigation_delegate.h index f98d11d..a9f63d4fb 100644 --- a/chrome/browser/ui/blocked_content/chrome_popup_navigation_delegate.h +++ b/chrome/browser/ui/blocked_content/chrome_popup_navigation_delegate.h
@@ -16,7 +16,7 @@ // blocked_content::PopupNavigationDelegate: content::RenderFrameHost* GetOpener() override; bool GetOriginalUserGesture() override; - const GURL& GetURL() override; + GURL GetURL() override; NavigateResult NavigateWithGesture( const blink::mojom::WindowFeatures& window_features, absl::optional<WindowOpenDisposition> updated_disposition) override;
diff --git a/chrome/browser/ui/location_bar/location_bar.h b/chrome/browser/ui/location_bar/location_bar.h index ed7124e..23299773 100644 --- a/chrome/browser/ui/location_bar/location_bar.h +++ b/chrome/browser/ui/location_bar/location_bar.h
@@ -33,14 +33,6 @@ virtual base::TimeTicks GetMatchSelectionTimestamp() const = 0; virtual bool IsInputTypedUrlWithoutScheme() const = 0; - // Accepts the current string of text entered in the location bar. - virtual void AcceptInput() = 0; - - // Accepts the current string of text entered in the location bar. If - // |match_selection_timestamp| is not null, uses this value to track - // latency of page loads starting at user input. - virtual void AcceptInput(base::TimeTicks match_selection_timestamp) = 0; - // Focuses the location bar. User-initiated focuses (like pressing Ctrl+L) // should have |is_user_initiated| set to true. In those cases, we want to // take some extra steps, like selecting everything and maybe uneliding.
diff --git a/chrome/browser/ui/search/instant_extended_interactive_uitest.cc b/chrome/browser/ui/search/instant_extended_interactive_uitest.cc index 3e46b69bc..9c7c61e 100644 --- a/chrome/browser/ui/search/instant_extended_interactive_uitest.cc +++ b/chrome/browser/ui/search/instant_extended_interactive_uitest.cc
@@ -70,7 +70,12 @@ void PressEnterAndWaitForLoadStop() { content::TestNavigationObserver observer( browser()->tab_strip_model()->GetActiveWebContents()); - browser()->window()->GetLocationBar()->AcceptInput(); + browser() + ->window() + ->GetLocationBar() + ->GetOmniboxView() + ->model() + ->OpenSelection(); observer.Wait(); }
diff --git a/chrome/browser/ui/startup/first_run_service.cc b/chrome/browser/ui/startup/first_run_service.cc index 47a8efc..9d59da1a 100644 --- a/chrome/browser/ui/startup/first_run_service.cc +++ b/chrome/browser/ui/startup/first_run_service.cc
@@ -453,7 +453,7 @@ } #if BUILDFLAG(ENABLE_DICE_SUPPORT) - if (base::FeatureList::IsEnabled(kForYouFreStudy)) { + if (base::FeatureList::IsEnabled(kForYouFreSyntheticTrialRegistration)) { // We use this point to register for the study as it can give us a good // counterfactual, before checking the state of the feature itself. The // service is created on demand so we are in a code path that will require
diff --git a/chrome/browser/ui/startup/first_run_service_browsertest.cc b/chrome/browser/ui/startup/first_run_service_browsertest.cc index 8bc9022..f937c63 100644 --- a/chrome/browser/ui/startup/first_run_service_browsertest.cc +++ b/chrome/browser/ui/startup/first_run_service_browsertest.cc
@@ -408,7 +408,8 @@ scoped_feature_list_.InitWithFeaturesAndParameters( { - {kForYouFreStudy, {{"group_name", kStudyTestGroupName1}}}, + {kForYouFreSyntheticTrialRegistration, + {{"group_name", kStudyTestGroupName1}}}, {kForYouFre, {}}, }, {});
diff --git a/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_model_listener.cc b/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_model_listener.cc index ce8784d..320c61b 100644 --- a/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_model_listener.cc +++ b/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_model_listener.cc
@@ -84,7 +84,6 @@ void SavedTabGroupBrowserListener::StopTrackingWebContents( content::WebContents* web_contents) { - CHECK(web_contents_to_tab_id_map_.count(web_contents) > 0); web_contents_to_tab_id_map_.erase(web_contents); }
diff --git a/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_model_listener.h b/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_model_listener.h index 4cbf90b..13843fd 100644 --- a/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_model_listener.h +++ b/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_model_listener.h
@@ -51,8 +51,7 @@ base::Token GetOrCreateTrackedIDForWebContents( content::WebContents* web_contents); - // Stops tracking the webcontents for changes. CHECKS if not currently - // tracked. + // Stops tracking the webcontents for changes. void StopTrackingWebContents(content::WebContents* web_contents); // TabStripModelObserver:
diff --git a/chrome/browser/ui/toolbar/app_menu_icon_controller_unittest.cc b/chrome/browser/ui/toolbar/app_menu_icon_controller_unittest.cc index f977517..1f6da8f2 100644 --- a/chrome/browser/ui/toolbar/app_menu_icon_controller_unittest.cc +++ b/chrome/browser/ui/toolbar/app_menu_icon_controller_unittest.cc
@@ -157,14 +157,6 @@ // and severity when an upgrade is detected. TEST_P(AppMenuIconControllerTest, UpgradeNotification) { #if BUILDFLAG(IS_CHROMEOS_ASH) - // Forcibly enable Lacros Profile migration, so that IDC_LACROS_DATA_MIGRATION - // becomes visible. Note that profile migration is only enabled if Lacros is - // the only browser. - base::test::ScopedFeatureList feature_list; - feature_list.InitWithFeatures( - {ash::features::kLacrosSupport, ash::features::kLacrosPrimary, - ash::features::kLacrosOnly}, - {}); auto set_lacros_enabled = crosapi::browser_util::SetLacrosEnabledForTest(true); #endif
diff --git a/chrome/browser/ui/toolbar/app_menu_model_unittest.cc b/chrome/browser/ui/toolbar/app_menu_model_unittest.cc index 7e3f12e..a2c89853 100644 --- a/chrome/browser/ui/toolbar/app_menu_model_unittest.cc +++ b/chrome/browser/ui/toolbar/app_menu_model_unittest.cc
@@ -160,14 +160,6 @@ EXPECT_TRUE(detector->notify_upgrade()); #if BUILDFLAG(IS_CHROMEOS_ASH) - // Forcibly enable Lacros Profile migration, so that IDC_LACROS_DATA_MIGRATION - // becomes visible. Note that profile migration is only enabled if Lacros is - // the only browser. - base::test::ScopedFeatureList feature_list; - feature_list.InitWithFeatures( - {ash::features::kLacrosSupport, ash::features::kLacrosPrimary, - ash::features::kLacrosOnly}, - {}); auto set_lacros_enabled = crosapi::browser_util::SetLacrosEnabledForTest(true); #endif
diff --git a/chrome/browser/ui/ui_features.cc b/chrome/browser/ui/ui_features.cc index 3c12398..1c257eb2 100644 --- a/chrome/browser/ui/ui_features.cc +++ b/chrome/browser/ui/ui_features.cc
@@ -7,7 +7,6 @@ #include "base/feature_list.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" -#include "ui_features.h" namespace features {
diff --git a/chrome/browser/ui/views/autofill/payments/save_card_bubble_views_browsertest.cc b/chrome/browser/ui/views/autofill/payments/save_card_bubble_views_browsertest.cc index f67b645..19a19db 100644 --- a/chrome/browser/ui/views/autofill/payments/save_card_bubble_views_browsertest.cc +++ b/chrome/browser/ui/views/autofill/payments/save_card_bubble_views_browsertest.cc
@@ -699,12 +699,13 @@ } SaveCardBubbleViews* GetSaveCardBubbleViews() { - SaveCardBubbleController* save_card_bubble_controller = - SaveCardBubbleController::Get(GetActiveWebContents()); + SaveCardBubbleControllerImpl::CreateForWebContents(GetActiveWebContents()); + SaveCardBubbleControllerImpl* save_card_bubble_controller = + SaveCardBubbleControllerImpl::FromWebContents(GetActiveWebContents()); if (!save_card_bubble_controller) return nullptr; AutofillBubbleBase* save_card_bubble_view = - save_card_bubble_controller->GetSaveCardBubbleView(); + save_card_bubble_controller->GetPaymentBubbleView(); if (!save_card_bubble_view) return nullptr; return static_cast<SaveCardBubbleViews*>(save_card_bubble_view);
diff --git a/chrome/browser/ui/views/autofill/popup/popup_cell_view.cc b/chrome/browser/ui/views/autofill/popup/popup_cell_view.cc index 40cc7841..28efeb6e 100644 --- a/chrome/browser/ui/views/autofill/popup/popup_cell_view.cc +++ b/chrome/browser/ui/views/autofill/popup/popup_cell_view.cc
@@ -99,18 +99,37 @@ } void PopupCellView::OnMouseEntered(const ui::MouseEvent& event) { + // `OnMouseEntered()` does not imply that the mouse had been outside of the + // item's bounds before: `OnMouseEntered()` fires if the mouse moves just + // a little bit on the item. We don't want to show a preview in such a case. + if (!mouse_observed_outside_item_bounds_) { + return; + } + if (on_entered_callback_) { on_entered_callback_.Run(); } } void PopupCellView::OnMouseExited(const ui::MouseEvent& event) { + // `OnMouseExited()` does not imply that the mouse has left the item's screen + // bounds: `OnMouseExited()` fires (on Windows, at least) when another popup + // overlays this item and the mouse is above the new popup + // (crbug.com/1287364). + mouse_observed_outside_item_bounds_ |= !IsMouseInsideItemBounds(); + if (on_exited_callback_) { on_exited_callback_.Run(); } } void PopupCellView::OnMouseReleased(const ui::MouseEvent& event) { + // Ignore mouse clicks unless the user made the explicit choice to selected + // the current item. + if (!mouse_observed_outside_item_bounds_) { + return; + } + if (on_accepted_callback_ && event.IsOnlyLeftMouseButton() && HitTestPoint(event.location())) { on_accepted_callback_.Run(); @@ -154,6 +173,11 @@ } } +void PopupCellView::OnPaint(gfx::Canvas* canvas) { + views::View::OnPaint(canvas); + mouse_observed_outside_item_bounds_ |= !IsMouseInsideItemBounds(); +} + void PopupCellView::RefreshStyle() { ui::ColorId kBackgroundColorId = GetSelected() ? ui::kColorDropdownBackgroundSelected
diff --git a/chrome/browser/ui/views/autofill/popup/popup_cell_view.h b/chrome/browser/ui/views/autofill/popup/popup_cell_view.h index 93c7aed..ce9086c 100644 --- a/chrome/browser/ui/views/autofill/popup/popup_cell_view.h +++ b/chrome/browser/ui/views/autofill/popup/popup_cell_view.h
@@ -109,6 +109,8 @@ void GetAccessibleNodeData(ui::AXNodeData* node_data) override; bool HandleAccessibleAction(const ui::AXActionData& action_data) override; + void OnPaint(gfx::Canvas* canvas) override; + private: // Returns true if the mouse is within the bounds of this item. This is not // affected by whether or not the item is overlaid by another popup. @@ -132,6 +134,18 @@ // The labels whose style is updated when the cell's selection status changes. std::vector<raw_ptr<views::Label>> tracked_labels_; + + // We want a mouse click to accept a suggestion only if the user has made an + // explicit choice. Therefore, we shall ignore mouse clicks unless the mouse + // has been moved into the item's screen bounds. For example, if the item is + // hovered by the mouse at the time it's first shown, we want to ignore clicks + // until the mouse has left and re-entered the bounds of the item + // (crbug.com/1240472, crbug.com/1241585, crbug.com/1287364). + // This is particularly relevant because mouse click interactions may be + // processed with a delay, making it seem as if the two click interactions of + // a double click were executed at intervals larger than the threshold (500ms) + // checked in the controller (crbug.com/1418837). + bool mouse_observed_outside_item_bounds_ = false; }; BEGIN_VIEW_BUILDER(/* no export*/, PopupCellView, views::View)
diff --git a/chrome/browser/ui/views/autofill/popup/popup_cell_view_unittest.cc b/chrome/browser/ui/views/autofill/popup/popup_cell_view_unittest.cc index 4307875..9547ee6b 100644 --- a/chrome/browser/ui/views/autofill/popup/popup_cell_view_unittest.cc +++ b/chrome/browser/ui/views/autofill/popup/popup_cell_view_unittest.cc
@@ -230,4 +230,30 @@ } #endif // !BUILDFLAG(IS_MAC) +TEST_F(PopupCellViewTest, IgnoreClickIfMouseWasNotOutsideBefore) { + std::unique_ptr<PopupCellView> cell = + views::Builder<PopupCellView>() + .SetAccessibilityDelegate( + std::make_unique<TestAccessibilityDelegate>()) + .Build(); + views::Label* label = + cell->AddChildView(std::make_unique<views::Label>(u"Label text")); + ShowView(std::move(cell)); + + StrictMock<base::MockCallback<base::RepeatingClosure>> accept_callback; + + view().SetOnAcceptedCallback(accept_callback.Get()); + generator().MoveMouseTo(label->GetBoundsInScreen().CenterPoint()); + Paint(); + // No OnAccept callback is run. + generator().ClickLeftButton(); + + generator().MoveMouseTo(kOutOfBounds); + Paint(); + generator().MoveMouseTo(label->GetBoundsInScreen().CenterPoint()); + // If the mouse has been outside before, the accept click is passed through. + EXPECT_CALL(accept_callback, Run); + generator().ClickLeftButton(); +} + } // namespace autofill
diff --git a/chrome/browser/ui/views/autofill/popup/popup_view_views_unittest.cc b/chrome/browser/ui/views/autofill/popup/popup_view_views_unittest.cc index 47c0b74..9bdd2c2 100644 --- a/chrome/browser/ui/views/autofill/popup/popup_view_views_unittest.cc +++ b/chrome/browser/ui/views/autofill/popup/popup_view_views_unittest.cc
@@ -628,6 +628,39 @@ view().RemoveAllChildViews(); } +// Tests that if the mouse hovers a suggestion when the popup is displayed, +// clicking the suggestion triggers no AcceptSuggestion() event. +TEST_P(PopupViewViewsTestWithClickablePopupItemId, + IgnoreClickIfFocusedAtPaintWithoutExit) { + CreateAndShowView({popup_item_id()}); + EXPECT_CALL(controller(), AcceptSuggestion).Times(0); + generator().MoveMouseTo(GetCenterOfSuggestion(0)); + ASSERT_TRUE(view().IsMouseHovered()); + Paint(); + generator().ClickLeftButton(); + view().RemoveAllChildViews(); +} + +// Tests that if the mouse hovers a suggestion when the popup is displayed and +// moves around on this suggestion, clicking the suggestion triggers no +// AcceptSuggestion() event. +TEST_P(PopupViewViewsTestWithClickablePopupItemId, + IgnoreClickIfFocusedAtPaintWithSlightMouseMovement) { + CreateAndShowView({popup_item_id()}); + EXPECT_CALL(controller(), AcceptSuggestion).Times(0); + int width = GetRowViewAt(0).width(); + int height = GetRowViewAt(0).height(); + for (int x : {-width / 3, width / 3}) { + for (int y : {-height / 3, height / 3}) { + generator().MoveMouseTo(GetCenterOfSuggestion(0) + gfx::Vector2d(x, y)); + ASSERT_TRUE(view().IsMouseHovered()); + Paint(); + } + } + generator().ClickLeftButton(); + view().RemoveAllChildViews(); +} + INSTANTIATE_TEST_SUITE_P(All, PopupViewViewsTestWithAnyPopupItemId, testing::ValuesIn([] {
diff --git a/chrome/browser/ui/views/commerce/price_tracking_bubble_dialog_view.cc b/chrome/browser/ui/views/commerce/price_tracking_bubble_dialog_view.cc index 37c7ac0..d240768 100644 --- a/chrome/browser/ui/views/commerce/price_tracking_bubble_dialog_view.cc +++ b/chrome/browser/ui/views/commerce/price_tracking_bubble_dialog_view.cc
@@ -21,13 +21,18 @@ namespace { -const std::u16string& GetMostRecentlyModifiedUserBookmarkFolderName( - Profile* profile) { +const std::u16string& GetBookmarkParentNameOrDefault(Profile* profile, + const GURL& url) { bookmarks::BookmarkModel* const model = BookmarkModelFactory::GetForBrowserContext(profile); - const std::vector<const bookmarks::BookmarkNode*> nodes = - bookmarks::GetMostRecentlyModifiedUserFolders(model, 1); - return nodes[0]->GetTitle(); + + if (bookmarks::IsBookmarkedByUser(model, url)) { + const bookmarks::BookmarkNode* existing_node = + model->GetMostRecentlyAddedUserNodeForURL(url); + return existing_node->parent()->GetTitle(); + } + const bookmarks::BookmarkNode* node = model->other_node(); + return node->GetTitle(); } std::unique_ptr<views::StyledLabel> CreateBodyLabel(std::u16string& body_text) { @@ -59,7 +64,7 @@ set_fixed_width(views::LayoutProvider::Get()->GetDistanceMetric( views::DISTANCE_BUBBLE_PREFERRED_WIDTH)); - auto folder_name = GetMostRecentlyModifiedUserBookmarkFolderName(profile_); + auto folder_name = GetBookmarkParentNameOrDefault(profile_, url); if (type == PriceTrackingBubbleDialogView::Type::TYPE_FIRST_USE_EXPERIENCE) { SetTitle(l10n_util::GetStringUTF16(
diff --git a/chrome/browser/ui/views/commerce/price_tracking_bubble_dialog_view_unittest.cc b/chrome/browser/ui/views/commerce/price_tracking_bubble_dialog_view_unittest.cc index 610f2d5..471a84a 100644 --- a/chrome/browser/ui/views/commerce/price_tracking_bubble_dialog_view_unittest.cc +++ b/chrome/browser/ui/views/commerce/price_tracking_bubble_dialog_view_unittest.cc
@@ -10,6 +10,7 @@ #include "chrome/browser/ui/views/bookmarks/bookmark_editor_view.h" #include "chrome/test/base/browser_with_test_window_test.h" #include "chrome/test/views/chrome_test_widget.h" +#include "components/bookmarks/browser/bookmark_model.h" #include "components/bookmarks/browser/bookmark_utils.h" #include "components/bookmarks/test/bookmark_test_helpers.h" #include "components/strings/grit/components_strings.h" @@ -68,15 +69,6 @@ return factories; } - void SetUpDependencies() { - bookmarks::BookmarkModel* bookmark_model = - BookmarkModelFactory::GetForBrowserContext(profile()); - bookmarks::test::WaitForBookmarkModelToLoad(bookmark_model); - - bookmarks::AddIfNotBookmarked(bookmark_model, GURL(kTestURL), - kTestBookmarkTitle); - } - void CreateBubbleViewAndShow(PriceTrackingBubbleDialogView::Type type) { SkBitmap bitmap; bitmap.allocN32Pixels(1, 1); @@ -101,14 +93,14 @@ return bubble_coordinator_.get(); } - const std::u16string& GetMostRecentlyModifiedUserBookmarkFolderName() { - bookmarks::BookmarkModel* const model = - BookmarkModelFactory::GetForBrowserContext(profile()); - std::vector<const bookmarks::BookmarkNode*> nodes = - bookmarks::GetMostRecentlyModifiedUserFolders(model, 1); - return nodes[0]->GetTitle(); + protected: + virtual void SetUpDependencies() { + bookmark_model_ = BookmarkModelFactory::GetForBrowserContext(profile()); + bookmarks::test::WaitForBookmarkModelToLoad(bookmark_model_); } + bookmarks::BookmarkModel* bookmark_model_; + private: views::UniqueWidgetPtr anchor_widget_; base::MockCallback<PriceTrackingBubbleDialogView::OnTrackPriceCallback> @@ -117,7 +109,57 @@ base::MockCallback<base::OnceClosure> on_dialog_closing_callback_; }; -TEST_F(PriceTrackingBubbleDialogViewUnitTest, FUEBubble) { +class PriceTrackingBubbleDialogViewLayoutUnitTest + : public PriceTrackingBubbleDialogViewUnitTest, + public ::testing::WithParamInterface<bool> { + public: + bool BookmarkWasCreated() { return GetParam(); } + + static std::string DescribeParams( + const ::testing::TestParamInfo<ParamType>& info) { + if (info.param) { + return "TrackBookmarkedPage"; + } else { + return "TrackNonBookmarkedPage"; + } + } + + const std::u16string& GetFolderName() { + if (BookmarkWasCreated()) { + return bookmark_folder_name_; + } else { + return GetDefaultFolderName(); + } + } + + protected: + void SetUpDependencies() override { + PriceTrackingBubbleDialogViewUnitTest::SetUpDependencies(); + + EXPECT_FALSE( + bookmarks::IsBookmarkedByUser(bookmark_model_, GURL(kTestURL))); + + if (BookmarkWasCreated()) { + auto* node = bookmarks::AddIfNotBookmarked( + bookmark_model_, GURL(kTestURL), kTestBookmarkTitle); + EXPECT_TRUE( + bookmarks::IsBookmarkedByUser(bookmark_model_, GURL(kTestURL))); + bookmark_folder_name_ = node->parent()->GetTitle(); + } + } + + private: + const std::u16string& GetDefaultFolderName() { + bookmarks::BookmarkModel* const model = + BookmarkModelFactory::GetForBrowserContext(profile()); + const bookmarks::BookmarkNode* node = model->other_node(); + return node->GetTitle(); + } + + std::u16string bookmark_folder_name_; +}; + +TEST_P(PriceTrackingBubbleDialogViewLayoutUnitTest, FUEBubble) { CreateBubbleViewAndShow( PriceTrackingBubbleDialogView::Type::TYPE_FIRST_USE_EXPERIENCE); @@ -132,7 +174,7 @@ EXPECT_EQ(bubble->GetBodyLabelForTesting()->GetText(), l10n_util::GetStringFUTF16( IDS_OMNIBOX_TRACK_PRICE_DIALOG_DESCRIPTION_FIRST_RUN, - GetMostRecentlyModifiedUserBookmarkFolderName())); + GetFolderName())); EXPECT_EQ( bubble->GetDialogButtonLabel(ui::DIALOG_BUTTON_OK), @@ -142,7 +184,7 @@ l10n_util::GetStringUTF16(IDS_OMNIBOX_TRACK_PRICE_DIALOG_CANCEL_BUTTON)); } -TEST_F(PriceTrackingBubbleDialogViewUnitTest, NormalBubble) { +TEST_P(PriceTrackingBubbleDialogViewLayoutUnitTest, NormalBubble) { CreateBubbleViewAndShow(PriceTrackingBubbleDialogView::Type::TYPE_NORMAL); auto* bubble = BubbleCoordinator()->GetBubble(); @@ -152,10 +194,10 @@ l10n_util::GetStringUTF16(IDS_OMNIBOX_TRACKING_PRICE_DIALOG_TITLE)); EXPECT_TRUE(bubble->GetBodyLabelForTesting()); - EXPECT_EQ(bubble->GetBodyLabelForTesting()->GetText(), - l10n_util::GetStringFUTF16( - IDS_OMNIBOX_TRACKING_PRICE_DIALOG_DESCRIPTION, - GetMostRecentlyModifiedUserBookmarkFolderName())); + EXPECT_EQ( + bubble->GetBodyLabelForTesting()->GetText(), + l10n_util::GetStringFUTF16(IDS_OMNIBOX_TRACKING_PRICE_DIALOG_DESCRIPTION, + GetFolderName())); EXPECT_TRUE(bubble->GetBodyLabelForTesting()->GetFirstLinkForTesting()); EXPECT_EQ(bubble->GetDialogButtonLabel(ui::DIALOG_BUTTON_OK), @@ -166,7 +208,23 @@ IDS_OMNIBOX_TRACKING_PRICE_DIALOG_UNTRACK_BUTTON)); } -TEST_F(PriceTrackingBubbleDialogViewUnitTest, AcceptFUEBubble) { +INSTANTIATE_TEST_SUITE_P( + All, + PriceTrackingBubbleDialogViewLayoutUnitTest, + ::testing::Values(true, false), + &PriceTrackingBubbleDialogViewLayoutUnitTest::DescribeParams); + +class PriceTrackingBubbleDialogViewActionUnitTest + : public PriceTrackingBubbleDialogViewUnitTest { + protected: + void SetUpDependencies() override { + PriceTrackingBubbleDialogViewUnitTest::SetUpDependencies(); + bookmarks::AddIfNotBookmarked(bookmark_model_, GURL(kTestURL), + kTestBookmarkTitle); + } +}; + +TEST_F(PriceTrackingBubbleDialogViewActionUnitTest, AcceptFUEBubble) { CreateBubbleViewAndShow( PriceTrackingBubbleDialogView::Type::TYPE_FIRST_USE_EXPERIENCE); @@ -177,7 +235,7 @@ bubble->Accept(); } -TEST_F(PriceTrackingBubbleDialogViewUnitTest, CancelNormalBubble) { +TEST_F(PriceTrackingBubbleDialogViewActionUnitTest, CancelNormalBubble) { CreateBubbleViewAndShow(PriceTrackingBubbleDialogView::Type::TYPE_NORMAL); auto* bubble = BubbleCoordinator()->GetBubble(); @@ -187,7 +245,8 @@ bubble->Cancel(); } -TEST_F(PriceTrackingBubbleDialogViewUnitTest, ClickLinkInTheNormalBubble) { +TEST_F(PriceTrackingBubbleDialogViewActionUnitTest, + ClickLinkInTheNormalBubble) { CreateBubbleViewAndShow(PriceTrackingBubbleDialogView::Type::TYPE_NORMAL); auto* bubble = BubbleCoordinator()->GetBubble();
diff --git a/chrome/browser/ui/views/commerce/price_tracking_icon_view.cc b/chrome/browser/ui/views/commerce/price_tracking_icon_view.cc index 1d14c729..aaf3a3d3 100644 --- a/chrome/browser/ui/views/commerce/price_tracking_icon_view.cc +++ b/chrome/browser/ui/views/commerce/price_tracking_icon_view.cc
@@ -38,6 +38,25 @@ #include "ui/gfx/vector_icon_types.h" #include "ui/views/view_class_properties.h" +namespace { + +void AddIfNotBookmarkedToTheDefaultFolder(bookmarks::BookmarkModel* model, + content::WebContents* web_contents) { + GURL url; + std::u16string title; + + if (chrome::GetURLAndTitleToBookmark(web_contents, &url, &title)) { + if (bookmarks::IsBookmarkedByUser(model, url)) { + return; + } + + const bookmarks::BookmarkNode* other_node = model->other_node(); + model->AddNewURL(other_node, other_node->children().size(), title, url); + } +} + +} // namespace + PriceTrackingIconView::PriceTrackingIconView( IconLabelBubbleView::Delegate* parent_delegate, Delegate* delegate, @@ -195,11 +214,7 @@ bool is_new_bookmark = existing_node == nullptr; if (enable) { - GURL url; - std::u16string title; - if (chrome::GetURLAndTitleToBookmark(GetWebContents(), &url, &title)) { - bookmarks::AddIfNotBookmarked(model, url, title); - } + AddIfNotBookmarkedToTheDefaultFolder(model, GetWebContents()); base::RecordAction( base::UserMetricsAction("Commerce.PriceTracking.OmniboxChip.Tracked")); commerce::MaybeEnableEmailNotifications(profile_->GetPrefs());
diff --git a/chrome/browser/ui/views/commerce/price_tracking_icon_view_interactive_uitest.cc b/chrome/browser/ui/views/commerce/price_tracking_icon_view_interactive_uitest.cc index 9d4869b..0091344 100644 --- a/chrome/browser/ui/views/commerce/price_tracking_icon_view_interactive_uitest.cc +++ b/chrome/browser/ui/views/commerce/price_tracking_icon_view_interactive_uitest.cc
@@ -76,9 +76,6 @@ BookmarkModelFactory::GetForBrowserContext(browser()->profile()); bookmarks::test::WaitForBookmarkModelToLoad(bookmark_model); - bookmarks::AddIfNotBookmarked(bookmark_model, GURL(kTrackableUrl), - std::u16string()); - mock_shopping_service_ = static_cast<commerce::MockShoppingService*>( commerce::ShoppingServiceFactory::GetInstance() ->SetTestingFactoryAndUse( @@ -146,6 +143,13 @@ return matched_view ? views::AsViewClass<StarView>(matched_view) : nullptr; } + const std::u16string& GetDefaultFolderName() { + bookmarks::BookmarkModel* const model = + BookmarkModelFactory::GetForBrowserContext(browser()->profile()); + const bookmarks::BookmarkNode* node = model->other_node(); + return node->GetTitle(); + } + protected: base::UserActionTester user_action_tester_; raw_ptr<commerce::MockShoppingService, DanglingUntriaged> @@ -252,6 +256,26 @@ } IN_PROC_BROWSER_TEST_F(PriceTrackingIconViewInteractiveTest, + CreateBookmarkOnPressIfNotExist) { + browser()->profile()->GetPrefs()->SetBoolean( + prefs::kShouldShowPriceTrackFUEBubble, false); + auto* icon_view = GetChip(); + icon_view->ForceVisibleForTesting(/*is_tracking_price=*/false); + + GURL url = GURL(kTrackableUrl); + bookmarks::BookmarkModel* bookmark_model = + BookmarkModelFactory::GetForBrowserContext(browser()->profile()); + EXPECT_FALSE(bookmarks::IsBookmarkedByUser(bookmark_model, url)); + + ClickPriceTrackingIconView(); + EXPECT_TRUE(bookmarks::IsBookmarkedByUser(bookmark_model, url)); + + const bookmarks::BookmarkNode* node = + bookmark_model->GetMostRecentlyAddedUserNodeForURL(url); + EXPECT_EQ(node->parent()->GetTitle(), GetDefaultFolderName()); +} + +IN_PROC_BROWSER_TEST_F(PriceTrackingIconViewInteractiveTest, RecordOmniboxChipClicked) { EXPECT_EQ(user_action_tester_.GetActionCount( "Commerce.PriceTracking.OmniboxChipClicked"),
diff --git a/chrome/browser/ui/views/frame/glass_browser_caption_button_container.cc b/chrome/browser/ui/views/frame/browser_caption_button_container_win.cc similarity index 84% rename from chrome/browser/ui/views/frame/glass_browser_caption_button_container.cc rename to chrome/browser/ui/views/frame/browser_caption_button_container_win.cc index 5776851..02c3ed9 100644 --- a/chrome/browser/ui/views/frame/glass_browser_caption_button_container.cc +++ b/chrome/browser/ui/views/frame/browser_caption_button_container_win.cc
@@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/views/frame/glass_browser_caption_button_container.h" +#include "chrome/browser/ui/views/frame/browser_caption_button_container_win.h" #include <memory> #include "chrome/browser/ui/frame/window_frame_util.h" +#include "chrome/browser/ui/views/frame/browser_frame_view_win.h" #include "chrome/browser/ui/views/frame/browser_view.h" -#include "chrome/browser/ui/views/frame/glass_browser_frame_view.h" #include "chrome/browser/ui/views/frame/windows_caption_button.h" #include "chrome/browser/ui/views/frame/windows_tab_search_caption_button.h" #include "chrome/grit/generated_resources.h" @@ -22,7 +22,7 @@ std::unique_ptr<WindowsCaptionButton> CreateCaptionButton( views::Button::PressedCallback callback, - GlassBrowserFrameView* frame_view, + BrowserFrameViewWin* frame_view, ViewID button_type, int accessible_name_resource_id) { return std::make_unique<WindowsCaptionButton>( @@ -37,8 +37,8 @@ } // anonymous namespace -GlassBrowserCaptionButtonContainer::GlassBrowserCaptionButtonContainer( - GlassBrowserFrameView* frame_view) +BrowserCaptionButtonContainer::BrowserCaptionButtonContainer( + BrowserFrameViewWin* frame_view) : frame_view_(frame_view), minimize_button_(AddChildView(CreateCaptionButton( base::BindRepeating(&BrowserFrame::Minimize, @@ -87,18 +87,20 @@ /* adjust_width_for_height */ false, views::MinimumFlexSizeRule::kScaleToZero)); - if (frame_view_->browser_view()->AppUsesWindowControlsOverlay()) + if (frame_view_->browser_view()->AppUsesWindowControlsOverlay()) { UpdateButtonToolTipsForWindowControlsOverlay(); + } } -GlassBrowserCaptionButtonContainer::~GlassBrowserCaptionButtonContainer() {} +BrowserCaptionButtonContainer::~BrowserCaptionButtonContainer() = default; -int GlassBrowserCaptionButtonContainer::NonClientHitTest( +int BrowserCaptionButtonContainer::NonClientHitTest( const gfx::Point& point) const { DCHECK(HitTestPoint(point)) << "should only be called with a point inside this view's bounds"; - if (tab_search_button_ && HitTestCaptionButton(tab_search_button_, point)) + if (tab_search_button_ && HitTestCaptionButton(tab_search_button_, point)) { return HTCLIENT; + } // BrowserView covers the frame view when Window Controls Overlay is enabled. // The native window that encompasses Web Contents gets the mouse events meant // for the caption buttons, so returning HTClient allows these buttons to be @@ -107,21 +109,25 @@ (HitTestCaptionButton(minimize_button_, point) || HitTestCaptionButton(maximize_button_, point) || HitTestCaptionButton(restore_button_, point) || - HitTestCaptionButton(close_button_, point))) + HitTestCaptionButton(close_button_, point))) { return HTCLIENT; - if (HitTestCaptionButton(minimize_button_, point)) + } + if (HitTestCaptionButton(minimize_button_, point)) { return HTMINBUTTON; - if (HitTestCaptionButton(maximize_button_, point)) + } + if (HitTestCaptionButton(maximize_button_, point)) { return HTMAXBUTTON; - if (HitTestCaptionButton(restore_button_, point)) + } + if (HitTestCaptionButton(restore_button_, point)) { return HTMAXBUTTON; - if (HitTestCaptionButton(close_button_, point)) + } + if (HitTestCaptionButton(close_button_, point)) { return HTCLOSE; + } return HTCAPTION; } -void GlassBrowserCaptionButtonContainer:: - OnWindowControlsOverlayEnabledChanged() { +void BrowserCaptionButtonContainer::OnWindowControlsOverlayEnabledChanged() { if (frame_view_->browser_view()->IsWindowControlsOverlayEnabled()) { SetBackground( views::CreateSolidBackground(frame_view_->GetTitlebarColor())); @@ -136,13 +142,12 @@ UpdateButtonToolTipsForWindowControlsOverlay(); } -TabSearchBubbleHost* -GlassBrowserCaptionButtonContainer::GetTabSearchBubbleHost() { +TabSearchBubbleHost* BrowserCaptionButtonContainer::GetTabSearchBubbleHost() { return tab_search_button_ ? tab_search_button_->tab_search_bubble_host() : nullptr; } -void GlassBrowserCaptionButtonContainer::OnThemeChanged() { +void BrowserCaptionButtonContainer::OnThemeChanged() { if (frame_view_->browser_view()->IsWindowControlsOverlayEnabled()) { SetBackground( views::CreateSolidBackground(frame_view_->GetTitlebarColor())); @@ -150,9 +155,10 @@ views::View::OnThemeChanged(); } -void GlassBrowserCaptionButtonContainer::ResetWindowControls() { - if (tab_search_button_) +void BrowserCaptionButtonContainer::ResetWindowControls() { + if (tab_search_button_) { tab_search_button_->SetState(views::Button::STATE_NORMAL); + } minimize_button_->SetState(views::Button::STATE_NORMAL); maximize_button_->SetState(views::Button::STATE_NORMAL); restore_button_->SetState(views::Button::STATE_NORMAL); @@ -160,7 +166,7 @@ InvalidateLayout(); } -void GlassBrowserCaptionButtonContainer::AddedToWidget() { +void BrowserCaptionButtonContainer::AddedToWidget() { views::Widget* const widget = GetWidget(); DCHECK(!widget_observation_.IsObserving()); @@ -177,18 +183,18 @@ } } -void GlassBrowserCaptionButtonContainer::RemovedFromWidget() { +void BrowserCaptionButtonContainer::RemovedFromWidget() { DCHECK(widget_observation_.IsObserving()); widget_observation_.Reset(); } -void GlassBrowserCaptionButtonContainer::OnWidgetBoundsChanged( +void BrowserCaptionButtonContainer::OnWidgetBoundsChanged( views::Widget* widget, const gfx::Rect& new_bounds) { UpdateButtons(); } -void GlassBrowserCaptionButtonContainer::UpdateButtons() { +void BrowserCaptionButtonContainer::UpdateButtons() { minimize_button_->SetVisible(frame_view_->browser_view()->CanMinimize()); const bool is_maximized = frame_view_->IsMaximized(); @@ -205,7 +211,7 @@ InvalidateLayout(); } -void GlassBrowserCaptionButtonContainer:: +void BrowserCaptionButtonContainer:: UpdateButtonToolTipsForWindowControlsOverlay() { if (frame_view_->browser_view()->IsWindowControlsOverlayEnabled()) { minimize_button_->SetTooltipText(minimize_button_->GetAccessibleName()); @@ -220,5 +226,5 @@ } } -BEGIN_METADATA(GlassBrowserCaptionButtonContainer, views::View) +BEGIN_METADATA(BrowserCaptionButtonContainer, views::View) END_METADATA
diff --git a/chrome/browser/ui/views/frame/glass_browser_caption_button_container.h b/chrome/browser/ui/views/frame/browser_caption_button_container_win.h similarity index 75% rename from chrome/browser/ui/views/frame/glass_browser_caption_button_container.h rename to chrome/browser/ui/views/frame/browser_caption_button_container_win.h index 0a89e37..6a51710e 100644 --- a/chrome/browser/ui/views/frame/glass_browser_caption_button_container.h +++ b/chrome/browser/ui/views/frame/browser_caption_button_container_win.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_VIEWS_FRAME_GLASS_BROWSER_CAPTION_BUTTON_CONTAINER_H_ -#define CHROME_BROWSER_UI_VIEWS_FRAME_GLASS_BROWSER_CAPTION_BUTTON_CONTAINER_H_ +#ifndef CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_CAPTION_BUTTON_CONTAINER_WIN_H_ +#define CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_CAPTION_BUTTON_CONTAINER_WIN_H_ #include "base/memory/raw_ptr.h" #include "base/scoped_observation.h" @@ -14,7 +14,7 @@ #include "ui/views/widget/widget.h" #include "ui/views/widget/widget_observer.h" -class GlassBrowserFrameView; +class BrowserFrameViewWin; class TabSearchBubbleHost; class WindowsCaptionButton; class WindowsTabSearchCaptionButton; @@ -22,13 +22,12 @@ // Provides a container for Windows caption buttons that can be moved between // frame and browser window as needed. When extended horizontally, becomes a // grab bar for moving the window. -class GlassBrowserCaptionButtonContainer : public views::View, - public views::WidgetObserver { +class BrowserCaptionButtonContainer : public views::View, + public views::WidgetObserver { public: - METADATA_HEADER(GlassBrowserCaptionButtonContainer); - explicit GlassBrowserCaptionButtonContainer( - GlassBrowserFrameView* frame_view); - ~GlassBrowserCaptionButtonContainer() override; + METADATA_HEADER(BrowserCaptionButtonContainer); + explicit BrowserCaptionButtonContainer(BrowserFrameViewWin* frame_view); + ~BrowserCaptionButtonContainer() override; // Tests to see if the specified |point| (which is expressed in this view's // coordinates and which must be within this view's bounds) is within one of @@ -43,7 +42,7 @@ TabSearchBubbleHost* GetTabSearchBubbleHost(); private: - friend class GlassBrowserFrameView; + friend class BrowserFrameViewWin; // views::View: void AddedToWidget() override; @@ -67,7 +66,7 @@ // hwnd which prevent tooltips being shown for the caption buttons. void UpdateButtonToolTipsForWindowControlsOverlay(); - const raw_ptr<GlassBrowserFrameView> frame_view_; + const raw_ptr<BrowserFrameViewWin> frame_view_; raw_ptr<WindowsTabSearchCaptionButton> tab_search_button_ = nullptr; const raw_ptr<WindowsCaptionButton> minimize_button_; const raw_ptr<WindowsCaptionButton> maximize_button_; @@ -78,9 +77,9 @@ widget_observation_{this}; base::CallbackListSubscription subscription_ = - ui::TouchUiController::Get()->RegisterCallback(base::BindRepeating( - &GlassBrowserCaptionButtonContainer::UpdateButtons, - base::Unretained(this))); + ui::TouchUiController::Get()->RegisterCallback( + base::BindRepeating(&BrowserCaptionButtonContainer::UpdateButtons, + base::Unretained(this))); }; -#endif // CHROME_BROWSER_UI_VIEWS_FRAME_GLASS_BROWSER_CAPTION_BUTTON_CONTAINER_H_ +#endif // CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_CAPTION_BUTTON_CONTAINER_WIN_H_
diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view_browsertest_win.cc b/chrome/browser/ui/views/frame/browser_frame_view_browsertest_win.cc similarity index 65% rename from chrome/browser/ui/views/frame/glass_browser_frame_view_browsertest_win.cc rename to chrome/browser/ui/views/frame/browser_frame_view_browsertest_win.cc index 560b981..4ed411c6 100644 --- a/chrome/browser/ui/views/frame/glass_browser_frame_view_browsertest_win.cc +++ b/chrome/browser/ui/views/frame/browser_frame_view_browsertest_win.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/views/frame/glass_browser_frame_view.h" +#include "chrome/browser/ui/views/frame/browser_frame_view_win.h" #include <tuple> @@ -15,8 +15,8 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/views/frame/app_menu_button.h" +#include "chrome/browser/ui/views/frame/browser_caption_button_container_win.h" #include "chrome/browser/ui/views/frame/browser_view.h" -#include "chrome/browser/ui/views/frame/glass_browser_caption_button_container.h" #include "chrome/browser/ui/views/frame/windows_caption_button.h" #include "chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_test_helper.h" #include "chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_view.h" @@ -37,31 +37,32 @@ #include "ui/color/color_provider.h" #include "ui/views/view_utils.h" -class GlassBrowserFrameViewTest : public InProcessBrowserTest { +class BrowserFrameViewWinTest : public InProcessBrowserTest { public: - GlassBrowserFrameViewTest() = default; - GlassBrowserFrameViewTest(const GlassBrowserFrameViewTest&) = delete; - GlassBrowserFrameViewTest& operator=(const GlassBrowserFrameViewTest&) = - delete; - ~GlassBrowserFrameViewTest() override = default; + BrowserFrameViewWinTest() = default; + BrowserFrameViewWinTest(const BrowserFrameViewWinTest&) = delete; + BrowserFrameViewWinTest& operator=(const BrowserFrameViewWinTest&) = delete; + ~BrowserFrameViewWinTest() override = default; protected: - GlassBrowserFrameView* GetGlassBrowserFrameView() { + BrowserFrameViewWin* GetBrowserFrameViewWin() { auto* browser_view = BrowserView::GetBrowserViewForBrowser(browser()); views::NonClientFrameView* frame_view = browser_view->GetWidget()->non_client_view()->frame_view(); - if (!views::IsViewClass<GlassBrowserFrameView>(frame_view)) + if (!views::IsViewClass<BrowserFrameViewWin>(frame_view)) { return nullptr; - return static_cast<GlassBrowserFrameView*>(frame_view); + } + return static_cast<BrowserFrameViewWin*>(frame_view); } const WindowsCaptionButton* GetMaximizeButton() { - auto* glass_frame_view = GetGlassBrowserFrameView(); - if (!glass_frame_view) + auto* frame_view = GetBrowserFrameViewWin(); + if (!frame_view) { return nullptr; + } auto* caption_button_container = - glass_frame_view->caption_button_container_for_testing(); + frame_view->caption_button_container_for_testing(); return static_cast<const WindowsCaptionButton*>( caption_button_container->GetViewByID(VIEW_ID_MAXIMIZE_BUTTON)); } @@ -69,12 +70,13 @@ // Test that in touch mode, the maximize button is enabled for a non-maximized // window. -IN_PROC_BROWSER_TEST_F(GlassBrowserFrameViewTest, +IN_PROC_BROWSER_TEST_F(BrowserFrameViewWinTest, NonMaximizedTouchMaximizeButtonState) { ui::TouchUiController::TouchUiScoperForTesting touch_ui_scoper_{true}; auto* maximize_button = GetMaximizeButton(); - if (!maximize_button) + if (!maximize_button) { GTEST_SKIP(); + } EXPECT_TRUE(maximize_button->GetVisible()); EXPECT_TRUE(maximize_button->GetEnabled()); @@ -82,14 +84,15 @@ // Test that in touch mode, the maximize button is disabled and not visible for // a maximized window. -IN_PROC_BROWSER_TEST_F(GlassBrowserFrameViewTest, +IN_PROC_BROWSER_TEST_F(BrowserFrameViewWinTest, MaximizedTouchMaximizeButtonState) { ui::TouchUiController::TouchUiScoperForTesting touch_ui_scoper_{true}; - auto* glass_frame_view = GetGlassBrowserFrameView(); - if (!glass_frame_view) + auto* frame_view = GetBrowserFrameViewWin(); + if (!frame_view) { GTEST_SKIP(); + } - glass_frame_view->frame()->Maximize(); + frame_view->frame()->Maximize(); auto* maximize_button = GetMaximizeButton(); @@ -100,12 +103,13 @@ // Test that in non touch mode, the maximize button is enabled for a // non-maximized window. -IN_PROC_BROWSER_TEST_F(GlassBrowserFrameViewTest, +IN_PROC_BROWSER_TEST_F(BrowserFrameViewWinTest, NonTouchNonMaximizedMaximizeButtonState) { ui::TouchUiController::TouchUiScoperForTesting touch_ui_scoper_{false}; auto* maximize_button = GetMaximizeButton(); - if (!maximize_button) + if (!maximize_button) { GTEST_SKIP(); + } EXPECT_TRUE(maximize_button->GetVisible()); EXPECT_TRUE(maximize_button->GetEnabled()); @@ -113,28 +117,28 @@ // Test that in non touch mode, the maximize button is enabled and not visible // for a maximized window. -IN_PROC_BROWSER_TEST_F(GlassBrowserFrameViewTest, +IN_PROC_BROWSER_TEST_F(BrowserFrameViewWinTest, NonTouchMaximizedMaximizeButtonState) { ui::TouchUiController::TouchUiScoperForTesting touch_ui_scoper_{false}; - auto* glass_frame_view = GetGlassBrowserFrameView(); - if (!glass_frame_view) + auto* frame_view = GetBrowserFrameViewWin(); + if (!frame_view) { GTEST_SKIP(); + } - glass_frame_view->frame()->Maximize(); + frame_view->frame()->Maximize(); auto* maximize_button = GetMaximizeButton(); EXPECT_FALSE(maximize_button->GetVisible()); EXPECT_TRUE(maximize_button->GetEnabled()); } -class WebAppGlassBrowserFrameViewTest : public InProcessBrowserTest { +class WebAppBrowserFrameViewWinTest : public InProcessBrowserTest { public: - WebAppGlassBrowserFrameViewTest() = default; - WebAppGlassBrowserFrameViewTest(const WebAppGlassBrowserFrameViewTest&) = - delete; - WebAppGlassBrowserFrameViewTest& operator=( - const WebAppGlassBrowserFrameViewTest&) = delete; - ~WebAppGlassBrowserFrameViewTest() override = default; + WebAppBrowserFrameViewWinTest() = default; + WebAppBrowserFrameViewWinTest(const WebAppBrowserFrameViewWinTest&) = delete; + WebAppBrowserFrameViewWinTest& operator=( + const WebAppBrowserFrameViewWinTest&) = delete; + ~WebAppBrowserFrameViewWinTest() override = default; GURL GetStartURL() { return GURL("https://test.org"); } @@ -144,16 +148,13 @@ WebAppToolbarButtonContainer::DisableAnimationForTesting(); } - // Windows 7 does not use GlassBrowserFrameView when Aero glass is not - // enabled. Skip testing in this scenario. - // TODO(https://crbug.com/863278): Force Aero glass on Windows 7 for this - // test. - bool InstallAndLaunchWebApp() { + void InstallAndLaunchWebApp() { auto web_app_info = std::make_unique<WebAppInstallInfo>(); web_app_info->start_url = GetStartURL(); web_app_info->scope = GetStartURL().GetWithoutFilename(); - if (theme_color_) + if (theme_color_) { web_app_info->theme_color = *theme_color_; + } web_app::AppId app_id = web_app::test::InstallWebApp( browser()->profile(), std::move(web_app_info)); @@ -166,112 +167,98 @@ views::NonClientFrameView* frame_view = browser_view_->GetWidget()->non_client_view()->frame_view(); - if (!views::IsViewClass<GlassBrowserFrameView>(frame_view)) - return false; - glass_frame_view_ = static_cast<GlassBrowserFrameView*>(frame_view); + frame_view_ = static_cast<BrowserFrameViewWin*>(frame_view); web_app_frame_toolbar_ = browser_view_->web_app_frame_toolbar_for_testing(); DCHECK(web_app_frame_toolbar_); DCHECK(web_app_frame_toolbar_->GetVisible()); - return true; } absl::optional<SkColor> theme_color_ = SK_ColorBLUE; raw_ptr<Browser, DanglingUntriaged> app_browser_ = nullptr; raw_ptr<BrowserView, DanglingUntriaged> browser_view_ = nullptr; - raw_ptr<GlassBrowserFrameView, DanglingUntriaged> glass_frame_view_ = nullptr; + raw_ptr<BrowserFrameViewWin, DanglingUntriaged> frame_view_ = nullptr; raw_ptr<WebAppFrameToolbarView, DanglingUntriaged> web_app_frame_toolbar_ = nullptr; }; -IN_PROC_BROWSER_TEST_F(WebAppGlassBrowserFrameViewTest, ThemeColor) { - if (!InstallAndLaunchWebApp()) - return; +IN_PROC_BROWSER_TEST_F(WebAppBrowserFrameViewWinTest, ThemeColor) { + InstallAndLaunchWebApp(); - EXPECT_EQ(glass_frame_view_->GetTitlebarColor(), *theme_color_); + EXPECT_EQ(frame_view_->GetTitlebarColor(), *theme_color_); } -IN_PROC_BROWSER_TEST_F(WebAppGlassBrowserFrameViewTest, NoThemeColor) { +IN_PROC_BROWSER_TEST_F(WebAppBrowserFrameViewWinTest, NoThemeColor) { theme_color_ = absl::nullopt; - if (!InstallAndLaunchWebApp()) - return; + InstallAndLaunchWebApp(); EXPECT_EQ( - glass_frame_view_->GetTitlebarColor(), + frame_view_->GetTitlebarColor(), browser()->window()->GetColorProvider()->GetColor(ui::kColorFrameActive)); } -IN_PROC_BROWSER_TEST_F(WebAppGlassBrowserFrameViewTest, MaximizedLayout) { - if (!InstallAndLaunchWebApp()) - return; - - glass_frame_view_->frame()->Maximize(); +IN_PROC_BROWSER_TEST_F(WebAppBrowserFrameViewWinTest, MaximizedLayout) { + InstallAndLaunchWebApp(); + frame_view_->frame()->Maximize(); RunScheduledLayouts(); views::View* const window_title = - glass_frame_view_->GetViewByID(VIEW_ID_WINDOW_TITLE); + frame_view_->GetViewByID(VIEW_ID_WINDOW_TITLE); DCHECK_GT(window_title->x(), 0); DCHECK_GE(web_app_frame_toolbar_->y(), 0); } -IN_PROC_BROWSER_TEST_F(WebAppGlassBrowserFrameViewTest, RTLTopRightHitTest) { +IN_PROC_BROWSER_TEST_F(WebAppBrowserFrameViewWinTest, RTLTopRightHitTest) { base::i18n::SetRTLForTesting(true); - if (!InstallAndLaunchWebApp()) - return; - + InstallAndLaunchWebApp(); RunScheduledLayouts(); // Avoid the top right resize corner. constexpr int kInset = 10; - EXPECT_EQ(glass_frame_view_->NonClientHitTest( - gfx::Point(glass_frame_view_->width() - kInset, kInset)), + EXPECT_EQ(frame_view_->NonClientHitTest( + gfx::Point(frame_view_->width() - kInset, kInset)), HTCAPTION); } -IN_PROC_BROWSER_TEST_F(WebAppGlassBrowserFrameViewTest, Fullscreen) { - if (!InstallAndLaunchWebApp()) - return; - - glass_frame_view_->frame()->SetFullscreen(true); +IN_PROC_BROWSER_TEST_F(WebAppBrowserFrameViewWinTest, Fullscreen) { + InstallAndLaunchWebApp(); + frame_view_->frame()->SetFullscreen(true); browser_view_->GetWidget()->LayoutRootViewIfNecessary(); // Verify that all children except the ClientView are hidden when the window // is fullscreened. - for (views::View* child : glass_frame_view_->children()) { + for (views::View* child : frame_view_->children()) { EXPECT_EQ(views::IsViewClass<views::ClientView>(child), child->GetVisible()); } } -IN_PROC_BROWSER_TEST_F(WebAppGlassBrowserFrameViewTest, ContainerHeight) { - if (!InstallAndLaunchWebApp()) - return; +IN_PROC_BROWSER_TEST_F(WebAppBrowserFrameViewWinTest, ContainerHeight) { + InstallAndLaunchWebApp(); - static_cast<views::View*>(glass_frame_view_) + static_cast<views::View*>(frame_view_) ->GetWidget() ->LayoutRootViewIfNecessary(); - EXPECT_EQ( - web_app_frame_toolbar_->height(), - glass_frame_view_->caption_button_container_for_testing()->height()); + EXPECT_EQ(web_app_frame_toolbar_->height(), + frame_view_->caption_button_container_for_testing()->height()); - glass_frame_view_->frame()->Maximize(); + frame_view_->frame()->Maximize(); - EXPECT_EQ( - web_app_frame_toolbar_->height(), - glass_frame_view_->caption_button_container_for_testing()->height()); + EXPECT_EQ(web_app_frame_toolbar_->height(), + frame_view_->caption_button_container_for_testing()->height()); } -class WebAppGlassBrowserFrameViewWindowControlsOverlayTest +class WebAppBrowserFrameViewWinWindowControlsOverlayTest : public InProcessBrowserTest { public: - WebAppGlassBrowserFrameViewWindowControlsOverlayTest() = default; - WebAppGlassBrowserFrameViewWindowControlsOverlayTest( - const WebAppGlassBrowserFrameViewWindowControlsOverlayTest&) = delete; - WebAppGlassBrowserFrameViewWindowControlsOverlayTest& operator=( - const WebAppGlassBrowserFrameViewWindowControlsOverlayTest&) = delete; + WebAppBrowserFrameViewWinWindowControlsOverlayTest() = default; + WebAppBrowserFrameViewWinWindowControlsOverlayTest( + const WebAppBrowserFrameViewWinWindowControlsOverlayTest&) = delete; + WebAppBrowserFrameViewWinWindowControlsOverlayTest& operator=( + const WebAppBrowserFrameViewWinWindowControlsOverlayTest&) = delete; - ~WebAppGlassBrowserFrameViewWindowControlsOverlayTest() override = default; + ~WebAppBrowserFrameViewWinWindowControlsOverlayTest() override = default; void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); @@ -280,7 +267,7 @@ InProcessBrowserTest::SetUp(); } - bool InstallAndLaunchWebAppWithWindowControlsOverlay() { + void InstallAndLaunchWebAppWithWindowControlsOverlay() { GURL start_url = web_app_frame_toolbar_helper_ .LoadWindowControlsOverlayTestPageWithDataAndGetURL( embedded_test_server(), &temp_dir_); @@ -317,16 +304,12 @@ views::NonClientFrameView* frame_view = browser_view_->GetWidget()->non_client_view()->frame_view(); - if (!views::IsViewClass<GlassBrowserFrameView>(frame_view)) - return false; - - glass_frame_view_ = static_cast<GlassBrowserFrameView*>(frame_view); + frame_view_ = static_cast<BrowserFrameViewWin*>(frame_view); auto* web_app_frame_toolbar = browser_view_->web_app_frame_toolbar_for_testing(); DCHECK(web_app_frame_toolbar); DCHECK(web_app_frame_toolbar->GetVisible()); - return true; } void ToggleWindowControlsOverlayEnabledAndWait() { @@ -340,54 +323,46 @@ } raw_ptr<BrowserView, DanglingUntriaged> browser_view_ = nullptr; - raw_ptr<GlassBrowserFrameView, DanglingUntriaged> glass_frame_view_ = nullptr; + raw_ptr<BrowserFrameViewWin, DanglingUntriaged> frame_view_ = nullptr; WebAppFrameToolbarTestHelper web_app_frame_toolbar_helper_; private: base::ScopedTempDir temp_dir_; }; -IN_PROC_BROWSER_TEST_F(WebAppGlassBrowserFrameViewWindowControlsOverlayTest, +IN_PROC_BROWSER_TEST_F(WebAppBrowserFrameViewWinWindowControlsOverlayTest, ContainerHeight) { - if (!InstallAndLaunchWebAppWithWindowControlsOverlay()) - return; - + InstallAndLaunchWebAppWithWindowControlsOverlay(); ToggleWindowControlsOverlayEnabledAndWait(); - EXPECT_EQ( - browser_view_->web_app_frame_toolbar_for_testing()->height(), - glass_frame_view_->caption_button_container_for_testing()->height()); + EXPECT_EQ(browser_view_->web_app_frame_toolbar_for_testing()->height(), + frame_view_->caption_button_container_for_testing()->height()); - glass_frame_view_->frame()->Maximize(); + frame_view_->frame()->Maximize(); - EXPECT_EQ( - browser_view_->web_app_frame_toolbar_for_testing()->height(), - glass_frame_view_->caption_button_container_for_testing()->height()); + EXPECT_EQ(browser_view_->web_app_frame_toolbar_for_testing()->height(), + frame_view_->caption_button_container_for_testing()->height()); } -IN_PROC_BROWSER_TEST_F(WebAppGlassBrowserFrameViewWindowControlsOverlayTest, +IN_PROC_BROWSER_TEST_F(WebAppBrowserFrameViewWinWindowControlsOverlayTest, Fullscreen) { - if (!InstallAndLaunchWebAppWithWindowControlsOverlay()) - return; - + InstallAndLaunchWebAppWithWindowControlsOverlay(); ToggleWindowControlsOverlayEnabledAndWait(); - EXPECT_GT(glass_frame_view_->GetBoundsForClientView().y(), 0); + EXPECT_GT(frame_view_->GetBoundsForClientView().y(), 0); - glass_frame_view_->frame()->SetFullscreen(true); + frame_view_->frame()->SetFullscreen(true); browser_view_->GetWidget()->LayoutRootViewIfNecessary(); // ClientView should be covering the entire screen. - EXPECT_EQ(glass_frame_view_->GetBoundsForClientView().y(), 0); + EXPECT_EQ(frame_view_->GetBoundsForClientView().y(), 0); } -IN_PROC_BROWSER_TEST_F(WebAppGlassBrowserFrameViewWindowControlsOverlayTest, +IN_PROC_BROWSER_TEST_F(WebAppBrowserFrameViewWinWindowControlsOverlayTest, CaptionButtonsTooltip) { - if (!InstallAndLaunchWebAppWithWindowControlsOverlay()) - return; - + InstallAndLaunchWebAppWithWindowControlsOverlay(); auto* caption_button_container = - glass_frame_view_->caption_button_container_for_testing(); + frame_view_->caption_button_container_for_testing(); auto* minimize_button = static_cast<const WindowsCaptionButton*>( caption_button_container->GetViewByID(VIEW_ID_MINIMIZE_BUTTON)); auto* maximize_button = static_cast<const WindowsCaptionButton*>( @@ -423,39 +398,35 @@ EXPECT_EQ(close_button->GetTooltipText(), u""); } -IN_PROC_BROWSER_TEST_F(WebAppGlassBrowserFrameViewWindowControlsOverlayTest, +IN_PROC_BROWSER_TEST_F(WebAppBrowserFrameViewWinWindowControlsOverlayTest, CaptionButtonHitTest) { - if (!InstallAndLaunchWebAppWithWindowControlsOverlay()) - return; - - glass_frame_view_->GetWidget()->LayoutRootViewIfNecessary(); + InstallAndLaunchWebAppWithWindowControlsOverlay(); + frame_view_->GetWidget()->LayoutRootViewIfNecessary(); // Avoid the top right resize corner. constexpr int kInset = 10; - const gfx::Point kPoint(glass_frame_view_->width() - kInset, kInset); + const gfx::Point kPoint(frame_view_->width() - kInset, kInset); - EXPECT_EQ(glass_frame_view_->NonClientHitTest(kPoint), HTCLOSE); + EXPECT_EQ(frame_view_->NonClientHitTest(kPoint), HTCLOSE); ToggleWindowControlsOverlayEnabledAndWait(); // Verify the component updates on toggle. - EXPECT_EQ(glass_frame_view_->NonClientHitTest(kPoint), HTCLIENT); + EXPECT_EQ(frame_view_->NonClientHitTest(kPoint), HTCLIENT); ToggleWindowControlsOverlayEnabledAndWait(); // Verify the component clears when the feature is turned off. - EXPECT_EQ(glass_frame_view_->NonClientHitTest(kPoint), HTCLOSE); + EXPECT_EQ(frame_view_->NonClientHitTest(kPoint), HTCLOSE); } // Regression test for https://crbug.com/1286896. -IN_PROC_BROWSER_TEST_F(WebAppGlassBrowserFrameViewWindowControlsOverlayTest, +IN_PROC_BROWSER_TEST_F(WebAppBrowserFrameViewWinWindowControlsOverlayTest, TitlebarLayoutAfterUpdateWindowTitle) { - if (!InstallAndLaunchWebAppWithWindowControlsOverlay()) - return; - + InstallAndLaunchWebAppWithWindowControlsOverlay(); ToggleWindowControlsOverlayEnabledAndWait(); - glass_frame_view_->GetWidget()->LayoutRootViewIfNecessary(); - glass_frame_view_->UpdateWindowTitle(); + frame_view_->GetWidget()->LayoutRootViewIfNecessary(); + frame_view_->UpdateWindowTitle(); WebAppFrameToolbarView* web_app_frame_toolbar = browser_view_->web_app_frame_toolbar_for_testing();
diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc b/chrome/browser/ui/views/frame/browser_frame_view_win.cc similarity index 86% rename from chrome/browser/ui/views/frame/glass_browser_frame_view.cc rename to chrome/browser/ui/views/frame/browser_frame_view_win.cc index 2f8981f..c2c1f722 100644 --- a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc +++ b/chrome/browser/ui/views/frame/browser_frame_view_win.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/views/frame/glass_browser_frame_view.h" +#include "chrome/browser/ui/views/frame/browser_frame_view_win.h" #include <dwmapi.h> @@ -17,8 +17,8 @@ #include "chrome/browser/themes/theme_properties.h" #include "chrome/browser/ui/color/chrome_color_id.h" #include "chrome/browser/ui/view_ids.h" +#include "chrome/browser/ui/views/frame/browser_caption_button_container_win.h" #include "chrome/browser/ui/views/frame/browser_view.h" -#include "chrome/browser/ui/views/frame/glass_browser_caption_button_container.h" #include "chrome/browser/ui/views/frame/tab_strip_region_view.h" #include "chrome/browser/ui/views/frame/webui_tab_strip_container_view.h" #include "chrome/browser/ui/views/tabs/new_tab_button.h" @@ -48,8 +48,8 @@ #include "ui/views/win/hwnd_util.h" #include "ui/views/window/client_view.h" -HICON GlassBrowserFrameView::throbber_icons_[ - GlassBrowserFrameView::kThrobberIconCount]; +HICON BrowserFrameViewWin::throbber_icons_ + [BrowserFrameViewWin::kThrobberIconCount]; namespace { @@ -74,10 +74,10 @@ } // namespace /////////////////////////////////////////////////////////////////////////////// -// GlassBrowserFrameView, public: +// BrowserFrameViewWin, public: -GlassBrowserFrameView::GlassBrowserFrameView(BrowserFrame* frame, - BrowserView* browser_view) +BrowserFrameViewWin::BrowserFrameViewWin(BrowserFrame* frame, + BrowserView* browser_view) : BrowserNonClientFrameView(frame, browser_view) { // We initialize all fields despite some of them being unused in some modes, // since it's possible for modes to flip dynamically (e.g. if the user enables @@ -126,34 +126,35 @@ } caption_button_container_ = - AddChildView(std::make_unique<GlassBrowserCaptionButtonContainer>(this)); + AddChildView(std::make_unique<BrowserCaptionButtonContainer>(this)); } -GlassBrowserFrameView::~GlassBrowserFrameView() = default; +BrowserFrameViewWin::~BrowserFrameViewWin() = default; /////////////////////////////////////////////////////////////////////////////// -// GlassBrowserFrameView, BrowserNonClientFrameView implementation: +// BrowserFrameViewWin, BrowserNonClientFrameView implementation: -bool GlassBrowserFrameView::CaptionButtonsOnLeadingEdge() const { +bool BrowserFrameViewWin::CaptionButtonsOnLeadingEdge() const { // Because we don't set WS_EX_LAYOUTRTL (which would conflict with Chrome's // own RTL layout logic), Windows always draws the caption buttons on the // right, even when we want to be RTL. See crbug.com/560619. return !ShouldCustomDrawSystemTitlebar() && base::i18n::IsRTL(); } -gfx::Rect GlassBrowserFrameView::GetBoundsForTabStripRegion( +gfx::Rect BrowserFrameViewWin::GetBoundsForTabStripRegion( const gfx::Size& tabstrip_minimum_size) const { const int x = CaptionButtonsOnLeadingEdge() ? (width() - frame()->GetMinimizeButtonOffset()) : 0; int end_x = width(); - if (!CaptionButtonsOnLeadingEdge()) + if (!CaptionButtonsOnLeadingEdge()) { end_x = std::min(MinimizeButtonX(), end_x); + } return gfx::Rect(x, TopAreaHeight(false), std::max(0, end_x - x), tabstrip_minimum_size.height()); } -gfx::Rect GlassBrowserFrameView::GetBoundsForWebAppFrameToolbar( +gfx::Rect BrowserFrameViewWin::GetBoundsForWebAppFrameToolbar( const gfx::Size& toolbar_preferred_size) const { int x = display::win::ScreenWin::GetSystemMetricsInDIP(SM_CXSIZEFRAME); if (IsMaximized()) { @@ -167,7 +168,7 @@ caption_button_container_->size().height()); } -void GlassBrowserFrameView::LayoutWebAppWindowTitle( +void BrowserFrameViewWin::LayoutWebAppWindowTitle( const gfx::Rect& available_space, views::Label& window_title_label) const { gfx::Rect bounds = available_space; @@ -184,17 +185,18 @@ window_title_label.SetBoundsRect(bounds); } -int GlassBrowserFrameView::GetTopInset(bool restored) const { - if (browser_view()->GetTabStripVisible() || IsWebUITabStrip()) +int BrowserFrameViewWin::GetTopInset(bool restored) const { + if (browser_view()->GetTabStripVisible() || IsWebUITabStrip()) { return TopAreaHeight(restored); + } return ShouldCustomDrawSystemTitlebar() ? TitlebarHeight(restored) : 0; } -int GlassBrowserFrameView::GetThemeBackgroundXInset() const { +int BrowserFrameViewWin::GetThemeBackgroundXInset() const { return 0; } -bool GlassBrowserFrameView::HasVisibleBackgroundTabShapes( +bool BrowserFrameViewWin::HasVisibleBackgroundTabShapes( BrowserFrameActiveState active_state) const { DCHECK(GetWidget()); @@ -204,20 +206,21 @@ // colors). // TODO(pkasting): https://crbug.com/831769 Change the architecture of the // high contrast support to respect system colors, then remove this. - if (GetNativeTheme()->UserHasContrastPreference()) + if (GetNativeTheme()->UserHasContrastPreference()) { return true; + } return BrowserNonClientFrameView::HasVisibleBackgroundTabShapes(active_state); } -SkColor GlassBrowserFrameView::GetCaptionColor( +SkColor BrowserFrameViewWin::GetCaptionColor( BrowserFrameActiveState active_state) const { return GetColorProvider()->GetColor(ShouldPaintAsActive(active_state) ? kColorCaptionForegroundActive : kColorCaptionForegroundInactive); } -void GlassBrowserFrameView::UpdateThrobber(bool running) { +void BrowserFrameViewWin::UpdateThrobber(bool running) { if (ShouldShowWindowIcon(TitlebarType::kCustom)) { window_icon_->Update(); } else if (ShouldShowWindowIcon(TitlebarType::kSystem)) { @@ -233,40 +236,41 @@ } } -gfx::Size GlassBrowserFrameView::GetMinimumSize() const { +gfx::Size BrowserFrameViewWin::GetMinimumSize() const { gfx::Size min_size(browser_view()->GetMinimumSize()); min_size.Enlarge(0, GetTopInset(false)); return min_size; } -void GlassBrowserFrameView::WindowControlsOverlayEnabledChanged() { +void BrowserFrameViewWin::WindowControlsOverlayEnabledChanged() { caption_button_container_->OnWindowControlsOverlayEnabledChanged(); } -TabSearchBubbleHost* GlassBrowserFrameView::GetTabSearchBubbleHost() { +TabSearchBubbleHost* BrowserFrameViewWin::GetTabSearchBubbleHost() { return caption_button_container_->GetTabSearchBubbleHost(); } -void GlassBrowserFrameView::PaintAsActiveChanged() { +void BrowserFrameViewWin::PaintAsActiveChanged() { BrowserNonClientFrameView::PaintAsActiveChanged(); // When window controls overlay is enabled, the caption button container is // painted to a layer and is not repainted by // BrowserNonClientFrameView::PaintAsActiveChanged. Schedule a re-paint here // to update the caption button colors. - if (caption_button_container_ && caption_button_container_->layer()) + if (caption_button_container_ && caption_button_container_->layer()) { caption_button_container_->SchedulePaint(); + } } /////////////////////////////////////////////////////////////////////////////// -// GlassBrowserFrameView, views::NonClientFrameView implementation: +// BrowserFrameViewWin, views::NonClientFrameView implementation: -gfx::Rect GlassBrowserFrameView::GetBoundsForClientView() const { +gfx::Rect BrowserFrameViewWin::GetBoundsForClientView() const { return client_view_bounds_; } -gfx::Rect GlassBrowserFrameView::GetWindowBoundsForClientBounds( +gfx::Rect BrowserFrameViewWin::GetWindowBoundsForClientBounds( const gfx::Rect& client_bounds) const { HWND hwnd = views::HWNDForWidget(frame()); if (!browser_view()->GetTabStripVisible() && hwnd) { @@ -286,20 +290,23 @@ client_bounds.width(), client_bounds.height() + top_inset); } -int GlassBrowserFrameView::NonClientHitTest(const gfx::Point& point) { +int BrowserFrameViewWin::NonClientHitTest(const gfx::Point& point) { int super_component = BrowserNonClientFrameView::NonClientHitTest(point); - if (super_component != HTNOWHERE) + if (super_component != HTNOWHERE) { return super_component; + } // For app windows and popups without a custom titlebar we haven't customized // the frame at all so Windows can figure it out. - if (!ShouldCustomDrawSystemTitlebar() && !browser_view()->GetIsNormalType()) + if (!ShouldCustomDrawSystemTitlebar() && !browser_view()->GetIsNormalType()) { return HTNOWHERE; + } // If the point isn't within our bounds, then it's in the native portion of // the frame so again Windows can figure it out. - if (!bounds().Contains(point)) + if (!bounds().Contains(point)) { return HTNOWHERE; + } int frame_component = frame()->client_view()->NonClientHitTest(point); @@ -310,12 +317,14 @@ 0, display::win::ScreenWin::GetSystemMetricsInDIP(SM_CYSIZEFRAME), display::win::ScreenWin::GetSystemMetricsInDIP(SM_CXSMICON), display::win::ScreenWin::GetSystemMetricsInDIP(SM_CYSMICON)); - if (sys_menu_region.Contains(point)) + if (sys_menu_region.Contains(point)) { return HTSYSMENU; + } } - if (frame_component != HTNOWHERE) + if (frame_component != HTNOWHERE) { return frame_component; + } // Then see if the point is within any of the window controls. if (caption_button_container_) { @@ -324,8 +333,9 @@ if (caption_button_container_->HitTestPoint(local_point)) { const int hit_test_result = caption_button_container_->NonClientHitTest(local_point); - if (hit_test_result != HTNOWHERE) + if (hit_test_result != HTNOWHERE) { return hit_test_result; + } } } @@ -377,75 +387,81 @@ return (window_component == HTNOWHERE) ? HTCAPTION : window_component; } -void GlassBrowserFrameView::UpdateWindowIcon() { - if (window_icon_ && window_icon_->GetVisible()) +void BrowserFrameViewWin::UpdateWindowIcon() { + if (window_icon_ && window_icon_->GetVisible()) { window_icon_->SchedulePaint(); + } } -void GlassBrowserFrameView::UpdateWindowTitle() { +void BrowserFrameViewWin::UpdateWindowTitle() { LayoutTitleBar(); - if (window_title_ && window_title_->GetVisible()) + if (window_title_ && window_title_->GetVisible()) { window_title_->SchedulePaint(); + } } -void GlassBrowserFrameView::ResetWindowControls() { +void BrowserFrameViewWin::ResetWindowControls() { BrowserNonClientFrameView::ResetWindowControls(); - if (caption_button_container_) + if (caption_button_container_) { caption_button_container_->ResetWindowControls(); + } } -bool GlassBrowserFrameView::ShouldTabIconViewAnimate() const { - if (!ShouldShowWindowIcon(TitlebarType::kCustom)) +bool BrowserFrameViewWin::ShouldTabIconViewAnimate() const { + if (!ShouldShowWindowIcon(TitlebarType::kCustom)) { return false; + } content::WebContents* current_tab = browser_view()->GetActiveWebContents(); return current_tab && current_tab->IsLoading(); } -ui::ImageModel GlassBrowserFrameView::GetFaviconForTabIconView() { +ui::ImageModel BrowserFrameViewWin::GetFaviconForTabIconView() { DCHECK(ShouldShowWindowIcon(TitlebarType::kCustom)); return frame()->widget_delegate()->GetWindowIcon(); } -bool GlassBrowserFrameView::IsMaximized() const { +bool BrowserFrameViewWin::IsMaximized() const { return frame()->IsMaximized(); } -bool GlassBrowserFrameView::IsWebUITabStrip() const { +bool BrowserFrameViewWin::IsWebUITabStrip() const { return WebUITabStripContainerView::UseTouchableTabStrip( browser_view()->browser()); } /////////////////////////////////////////////////////////////////////////////// -// GlassBrowserFrameView, views::View overrides: +// BrowserFrameViewWin, views::View overrides: -void GlassBrowserFrameView::OnPaint(gfx::Canvas* canvas) { - TRACE_EVENT0("views.frame", "GlassBrowserFrameView::OnPaint"); - if (ShouldCustomDrawSystemTitlebar()) +void BrowserFrameViewWin::OnPaint(gfx::Canvas* canvas) { + TRACE_EVENT0("views.frame", "BrowserFrameViewWin::OnPaint"); + if (ShouldCustomDrawSystemTitlebar()) { PaintTitlebar(canvas); + } } -void GlassBrowserFrameView::Layout() { - TRACE_EVENT0("views.frame", "GlassBrowserFrameView::Layout"); +void BrowserFrameViewWin::Layout() { + TRACE_EVENT0("views.frame", "BrowserFrameViewWin::Layout"); LayoutCaptionButtons(); - if (browser_view()->IsWindowControlsOverlayEnabled()) + if (browser_view()->IsWindowControlsOverlayEnabled()) { LayoutWindowControlsOverlay(); - else + } else { LayoutTitleBar(); + } LayoutClientView(); BrowserNonClientFrameView::Layout(); } /////////////////////////////////////////////////////////////////////////////// -// GlassBrowserFrameView, private: +// BrowserFrameViewWin, private: -int GlassBrowserFrameView::FrameBorderThickness() const { +int BrowserFrameViewWin::FrameBorderThickness() const { return (IsMaximized() || frame()->IsFullscreen()) ? 0 : display::win::ScreenWin::GetSystemMetricsInDIP(SM_CXSIZEFRAME); } -int GlassBrowserFrameView::FrameTopBorderThickness(bool restored) const { +int BrowserFrameViewWin::FrameTopBorderThickness(bool restored) const { const bool is_fullscreen = (frame()->IsFullscreen() || IsMaximized()) && !restored; if (!is_fullscreen) { @@ -454,8 +470,9 @@ // extends beyond the screen edges. In that case, we must return the default // value. constexpr int kTopResizeFrameArea = 5; - if (browser_view()->GetTabStripVisible()) + if (browser_view()->GetTabStripVisible()) { return kTopResizeFrameArea; + } // There is no top border in tablet mode when the window is "restored" // because it is still tiled into either the left or right pane of the @@ -463,8 +480,9 @@ // rendering bug in Windows may still cause the very top of the window to be // cut off intermittently, but that's an OS issue that affects all // applications, not specifically Chrome. - if (IsWebUITabStrip()) + if (IsWebUITabStrip()) { return 0; + } } // Mouse and touch locations are floored but GetSystemMetricsInDIP is rounded, @@ -475,7 +493,7 @@ display::win::ScreenWin::GetScaleFactorForHWND(HWNDForView(this))); } -int GlassBrowserFrameView::FrameTopBorderThicknessPx(bool restored) const { +int BrowserFrameViewWin::FrameTopBorderThicknessPx(bool restored) const { // Distinct from FrameBorderThickness() because we can't inset the top // border, otherwise Windows will give us a standard titlebar. // For maximized windows this is not true, and the top border must be @@ -484,8 +502,9 @@ const bool needs_no_border = (ShouldCustomDrawSystemTitlebar() && frame()->IsMaximized()) || frame()->IsFullscreen(); - if (needs_no_border && !restored) + if (needs_no_border && !restored) { return 0; + } // Note that this method assumes an equal resize handle thickness on all // sides of the window. @@ -494,9 +513,10 @@ MonitorFromWindow(HWNDForView(this), MONITOR_DEFAULTTONEAREST)); } -int GlassBrowserFrameView::TopAreaHeight(bool restored) const { - if (frame()->IsFullscreen() && !restored) +int BrowserFrameViewWin::TopAreaHeight(bool restored) const { + if (frame()->IsFullscreen() && !restored) { return 0; + } const bool maximized = IsMaximized() && !restored; int top = FrameTopBorderThickness(restored); @@ -511,8 +531,9 @@ // In maximized mode, we do not add any additional thickness to the grab // handle above the tabs; just return the frame thickness. - if (maximized) + if (maximized) { return top; + } // Besides the frame border, there's empty space atop the window in restored // mode, to use to drag the window around. @@ -525,7 +546,7 @@ return top + thickness; } -int GlassBrowserFrameView::TitlebarMaximizedVisualHeight() const { +int BrowserFrameViewWin::TitlebarMaximizedVisualHeight() const { int maximized_height = display::win::ScreenWin::GetSystemMetricsInDIP(SM_CYCAPTION); // Adding 2 dip of vertical padding puts at least 1 dip of space on the top @@ -547,9 +568,10 @@ return maximized_height; } -int GlassBrowserFrameView::TitlebarHeight(bool restored) const { - if (frame()->IsFullscreen() && !restored) +int BrowserFrameViewWin::TitlebarHeight(bool restored) const { + if (frame()->IsFullscreen() && !restored) { return 0; + } // The titlebar's actual height is the same in restored and maximized, but // some of it is above the screen in maximized mode. See the comment in @@ -560,17 +582,18 @@ FrameTopBorderThickness(false); } -int GlassBrowserFrameView::WindowTopY() const { +int BrowserFrameViewWin::WindowTopY() const { // The window top is SM_CYSIZEFRAME pixels when maximized (see the comment in // FrameTopBorderThickness()) and floor(system dsf) pixels when restored. // Unfortunately we can't represent either of those at hidpi without using // non-integral dips, so we return the closest reasonable values instead. - if (IsMaximized()) + if (IsMaximized()) { return FrameTopBorderThickness(false); + } return IsWebUITabStrip() ? FrameTopBorderThickness(true) : 1; } -int GlassBrowserFrameView::MinimizeButtonX() const { +int BrowserFrameViewWin::MinimizeButtonX() const { // When CaptionButtonsOnLeadingEdge() is true call // frame()->GetMinimizeButtonOffset() directly, because minimize_button_->x() // will give the wrong edge of the button. @@ -584,32 +607,38 @@ : frame()->GetMinimizeButtonOffset(); } -bool GlassBrowserFrameView::ShouldShowWindowIcon(TitlebarType type) const { - if (type == TitlebarType::kCustom && !ShouldCustomDrawSystemTitlebar()) +bool BrowserFrameViewWin::ShouldShowWindowIcon(TitlebarType type) const { + if (type == TitlebarType::kCustom && !ShouldCustomDrawSystemTitlebar()) { return false; - if (type == TitlebarType::kSystem && ShouldCustomDrawSystemTitlebar()) + } + if (type == TitlebarType::kSystem && ShouldCustomDrawSystemTitlebar()) { return false; - if (frame()->IsFullscreen() || browser_view()->GetIsWebAppType()) + } + if (frame()->IsFullscreen() || browser_view()->GetIsWebAppType()) { return false; + } return browser_view()->ShouldShowWindowIcon(); } -bool GlassBrowserFrameView::ShouldShowWindowTitle(TitlebarType type) const { - if (type == TitlebarType::kCustom && !ShouldCustomDrawSystemTitlebar()) +bool BrowserFrameViewWin::ShouldShowWindowTitle(TitlebarType type) const { + if (type == TitlebarType::kCustom && !ShouldCustomDrawSystemTitlebar()) { return false; - if (type == TitlebarType::kSystem && ShouldCustomDrawSystemTitlebar()) + } + if (type == TitlebarType::kSystem && ShouldCustomDrawSystemTitlebar()) { return false; - if (frame()->IsFullscreen()) + } + if (frame()->IsFullscreen()) { return false; + } return browser_view()->ShouldShowWindowTitle(); } -SkColor GlassBrowserFrameView::GetTitlebarColor() const { +SkColor BrowserFrameViewWin::GetTitlebarColor() const { return GetFrameColor(BrowserFrameActiveState::kUseCurrent); } -void GlassBrowserFrameView::PaintTitlebar(gfx::Canvas* canvas) const { - TRACE_EVENT0("views.frame", "GlassBrowserFrameView::PaintTitlebar"); +void BrowserFrameViewWin::PaintTitlebar(gfx::Canvas* canvas) const { + TRACE_EVENT0("views.frame", "BrowserFrameViewWin::PaintTitlebar"); // This is the pixel-accurate version of WindowTopY(). Scaling the DIP values // here compounds precision error, which exposes unpainted client area. When @@ -681,14 +710,16 @@ } } -void GlassBrowserFrameView::LayoutTitleBar() { - TRACE_EVENT0("views.frame", "GlassBrowserFrameView::LayoutTitleBar"); +void BrowserFrameViewWin::LayoutTitleBar() { + TRACE_EVENT0("views.frame", "BrowserFrameViewWin::LayoutTitleBar"); const bool show_icon = ShouldShowWindowIcon(TitlebarType::kCustom); const bool show_title = ShouldShowWindowTitle(TitlebarType::kCustom); - if (window_icon_) + if (window_icon_) { window_icon_->SetVisible(show_icon); - if (window_title_) + } + if (window_title_) { window_title_->SetVisible(show_title); + } if (!show_icon && !show_title && (!web_app_frame_toolbar() || frame()->IsFullscreen())) { // TODO(crbug.com/1132767): The "frame()->IsFullscreen()" term is required @@ -707,8 +738,9 @@ const int window_top = IsMaximized() ? WindowTopY() : 0; int next_leading_x = display::win::ScreenWin::GetSystemMetricsInDIP(SM_CXSIZEFRAME); - if (IsMaximized()) + if (IsMaximized()) { next_leading_x += kMaximizedLeftMargin; + } int next_trailing_x = MinimizeButtonX(); const int y = window_top + (titlebar_visual_height - icon_size) / 2; @@ -743,10 +775,11 @@ } } -void GlassBrowserFrameView::LayoutCaptionButtons() { - TRACE_EVENT0("views.frame", "GlassBrowserFrameView::LayoutCaptionButtons"); - if (!caption_button_container_) +void BrowserFrameViewWin::LayoutCaptionButtons() { + TRACE_EVENT0("views.frame", "BrowserFrameViewWin::LayoutCaptionButtons"); + if (!caption_button_container_) { return; + } // Non-custom system titlebar already contains caption buttons. if (!ShouldCustomDrawSystemTitlebar()) { @@ -778,7 +811,7 @@ height); } -void GlassBrowserFrameView::LayoutWindowControlsOverlay() { +void BrowserFrameViewWin::LayoutWindowControlsOverlay() { if (!web_app_frame_toolbar()) { return; } @@ -801,7 +834,7 @@ } } -void GlassBrowserFrameView::LayoutClientView() { +void BrowserFrameViewWin::LayoutClientView() { client_view_bounds_ = GetLocalBounds(); int top_inset = GetTopInset(false); if (browser_view()->IsWindowControlsOverlayEnabled()) { @@ -815,7 +848,7 @@ client_view_bounds_.Inset(gfx::Insets::TLBR(top_inset, 0, 0, 0)); } -void GlassBrowserFrameView::StartThrobber() { +void BrowserFrameViewWin::StartThrobber() { DCHECK(ShouldShowWindowIcon(TitlebarType::kSystem)); if (!throbber_running_) { throbber_running_ = true; @@ -827,7 +860,7 @@ } } -void GlassBrowserFrameView::StopThrobber() { +void BrowserFrameViewWin::StopThrobber() { DCHECK(ShouldShowWindowIcon(TitlebarType::kSystem)); if (throbber_running_) { throbber_running_ = false; @@ -878,7 +911,7 @@ } } -void GlassBrowserFrameView::DisplayNextThrobberFrame() { +void BrowserFrameViewWin::DisplayNextThrobberFrame() { throbber_frame_ = (throbber_frame_ + 1) % kThrobberIconCount; SendMessage(views::HWNDForWidget(frame()), WM_SETICON, static_cast<WPARAM>(ICON_SMALL), @@ -886,7 +919,7 @@ } // static -void GlassBrowserFrameView::InitThrobberIcons() { +void BrowserFrameViewWin::InitThrobberIcons() { static bool initialized = false; if (!initialized) { for (int i = 0; i < kThrobberIconCount; ++i) { @@ -898,5 +931,5 @@ } } -BEGIN_METADATA(GlassBrowserFrameView, BrowserNonClientFrameView) +BEGIN_METADATA(BrowserFrameViewWin, BrowserNonClientFrameView) END_METADATA
diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view.h b/chrome/browser/ui/views/frame/browser_frame_view_win.h similarity index 87% rename from chrome/browser/ui/views/frame/glass_browser_frame_view.h rename to chrome/browser/ui/views/frame/browser_frame_view_win.h index c092b31..204e8d4 100644 --- a/chrome/browser/ui/views/frame/glass_browser_frame_view.h +++ b/chrome/browser/ui/views/frame/browser_frame_view_win.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_VIEWS_FRAME_GLASS_BROWSER_FRAME_VIEW_H_ -#define CHROME_BROWSER_UI_VIEWS_FRAME_GLASS_BROWSER_FRAME_VIEW_H_ +#ifndef CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_FRAME_VIEW_WIN_H_ +#define CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_FRAME_VIEW_WIN_H_ #include "base/memory/raw_ptr.h" #include "base/win/scoped_gdi_object.h" @@ -16,18 +16,18 @@ class BrowserView; class TabSearchBubbleHost; -class GlassBrowserCaptionButtonContainer; +class BrowserCaptionButtonContainer; -class GlassBrowserFrameView : public BrowserNonClientFrameView, - public TabIconViewModel { +class BrowserFrameViewWin : public BrowserNonClientFrameView, + public TabIconViewModel { public: - METADATA_HEADER(GlassBrowserFrameView); + METADATA_HEADER(BrowserFrameViewWin); // Constructs a non-client view for an BrowserFrame. - GlassBrowserFrameView(BrowserFrame* frame, BrowserView* browser_view); - GlassBrowserFrameView(const GlassBrowserFrameView&) = delete; - GlassBrowserFrameView& operator=(const GlassBrowserFrameView&) = delete; - ~GlassBrowserFrameView() override; + BrowserFrameViewWin(BrowserFrame* frame, BrowserView* browser_view); + BrowserFrameViewWin(const BrowserFrameViewWin&) = delete; + BrowserFrameViewWin& operator=(const BrowserFrameViewWin&) = delete; + ~BrowserFrameViewWin() override; // BrowserNonClientFrameView: bool CaptionButtonsOnLeadingEdge() const override; @@ -71,8 +71,8 @@ SkColor GetTitlebarColor() const; - const GlassBrowserCaptionButtonContainer* - caption_button_container_for_testing() const { + const BrowserCaptionButtonContainer* caption_button_container_for_testing() + const { return caption_button_container_; } @@ -85,7 +85,7 @@ void Layout() override; private: - friend class GlassBrowserCaptionButtonContainer; + friend class BrowserCaptionButtonContainer; // Describes the type of titlebar that a window might have; used to query // whether specific elements may be present. @@ -174,7 +174,7 @@ // The container holding the caption buttons (minimize, maximize, close, etc.) // May be null if the caption button container is destroyed before the frame // view. Always check for validity before using! - raw_ptr<GlassBrowserCaptionButtonContainer> caption_button_container_; + raw_ptr<BrowserCaptionButtonContainer> caption_button_container_; // Whether or not the window throbber is currently animating. bool throbber_running_ = false; @@ -187,4 +187,4 @@ static void InitThrobberIcons(); }; -#endif // CHROME_BROWSER_UI_VIEWS_FRAME_GLASS_BROWSER_FRAME_VIEW_H_ +#endif // CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_FRAME_VIEW_WIN_H_
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_factory_views.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_factory_views.cc index f8cc223..b65c3cc 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_factory_views.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_factory_views.cc
@@ -13,7 +13,7 @@ #include "chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view.h" #if BUILDFLAG(IS_WIN) -#include "chrome/browser/ui/views/frame/glass_browser_frame_view.h" +#include "chrome/browser/ui/views/frame/browser_frame_view_win.h" #endif #if BUILDFLAG(IS_LINUX) @@ -98,7 +98,7 @@ #if BUILDFLAG(IS_WIN) if (frame->ShouldUseNativeFrame()) - return std::make_unique<GlassBrowserFrameView>(frame, browser_view); + return std::make_unique<BrowserFrameViewWin>(frame, browser_view); #endif auto view = CreateOpaqueBrowserFrameView(frame, browser_view); view->InitViews();
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index 7f4c811..01dc9657 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -526,6 +526,36 @@ return parent()->GetAccelerator(cmd_id, accelerator); } }; + +// TabContainerOverlayView is a view that hosts the TabStripRegionView during +// immersive fullscreen. The TopContainerView usually draws the background for +// the tab strip. Since the tab strip has been reparented we need to handle +// drawing the background here. +class TabContainerOverlayView : public views::View { + public: + METADATA_HEADER(TabContainerOverlayView); + explicit TabContainerOverlayView(base::WeakPtr<BrowserView> browser_view) + : browser_view_(std::move(browser_view)) {} + ~TabContainerOverlayView() override = default; + + // views::View override + void OnPaintBackground(gfx::Canvas* canvas) override { + SkColor frame_color = browser_view_->frame()->GetFrameView()->GetFrameColor( + BrowserFrameActiveState::kUseCurrent); + canvas->DrawColor(frame_color); + + // TODO(https://crbug.com/1414521): Support extension based themes / + // backgrounds. + } + + private: + // The BrowserView this overlay is created for. WeakPtr is used since + // this view is held in a different hierarchy. + base::WeakPtr<BrowserView> browser_view_; +}; + +BEGIN_METADATA(TabContainerOverlayView, views::View) +END_METADATA #endif // BUILDFLAG(IS_MAC) } // namespace @@ -579,11 +609,18 @@ int GetTopInsetInBrowserView() const override { // BrowserView should fill the full window when window controls overlay - // is enabled. + // is enabled or when immersive fullscreen with tabs is enabled. if (browser_view_->IsWindowControlsOverlayEnabled() || browser_view_->IsBorderlessModeEnabled()) { return 0; } +#if BUILDFLAG(IS_MAC) + if (base::FeatureList::IsEnabled(features::kImmersiveFullscreenTabs) && + browser_view_->immersive_mode_controller()->IsEnabled()) { + return 0; + } +#endif + return browser_view_->frame()->GetTopInset() - browser_view_->y(); } @@ -679,6 +716,18 @@ : browser_view_->GetMirroredRect(available_titlebar_area)); } + bool ShouldLayoutTabStrip() const override { +#if BUILDFLAG(IS_MAC) + // The tab strip is hosted in a separate widget in immersive fullscreen on + // macOS. + if (base::FeatureList::IsEnabled(features::kImmersiveFullscreenTabs) && + browser_view_->immersive_mode_controller()->IsEnabled()) { + return false; + } +#endif + return true; + } + private: raw_ptr<BrowserView> browser_view_; }; @@ -3554,6 +3603,12 @@ if (base::FeatureList::IsEnabled(features::kImmersiveFullscreenTabs)) { // Create the tab overlay widget. tab_overlay_widget_ = create_overlay_widget(); + std::unique_ptr<TabContainerOverlayView> tab_overlay_view = + std::make_unique<TabContainerOverlayView>( + weak_ptr_factory_.GetWeakPtr()); + tab_overlay_view_ = tab_overlay_view.get(); + tab_overlay_widget_->GetRootView()->AddChildView( + std::move(tab_overlay_view)); // TODO(https://crbug.com/1414521): Figure out how to handle multiple view // targeters.
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h index d769d391..e24a154 100644 --- a/chrome/browser/ui/views/frame/browser_view.h +++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -199,6 +199,7 @@ #if BUILDFLAG(IS_MAC) views::Widget* overlay_widget() { return overlay_widget_.get(); } views::Widget* tab_overlay_widget() { return tab_overlay_widget_.get(); } + views::View* tab_overlay_view() { return tab_overlay_view_.get(); } // Returns if this browser view will use immersive fullscreen mode, based // on the state of the two relevant base::Features, as well as the type of @@ -1046,13 +1047,17 @@ // Used when calling CreateMacOverlayView(). This widget owns `overlay_view_`. // Its content NSView will be reparented to a NSToolbarFullScreenWindow // during fullscreen. - raw_ptr<views::Widget, DanglingUntriaged> overlay_widget_; + raw_ptr<views::Widget, DanglingUntriaged> overlay_widget_ = nullptr; // Also used when calling CreateMacOverlayView(). This widget will host the // tabstrip contents. Its content NSView will be reparented to a separate // section of the NSToolbarFullScreenWindow allowing for the tabs to live in // the Titlebar. - raw_ptr<views::Widget, DanglingUntriaged> tab_overlay_widget_; + raw_ptr<views::Widget, DanglingUntriaged> tab_overlay_widget_ = nullptr; + + // The hosting view of TabStripRegionView during immersive fullscreen. + raw_ptr<views::View, DanglingUntriaged> tab_overlay_view_ = nullptr; + #endif // The Bookmark Bar View for this window. Lazily created. May be null for
diff --git a/chrome/browser/ui/views/frame/browser_view_layout.cc b/chrome/browser/ui/views/frame/browser_view_layout.cc index c9b4becd..bb08afe 100644 --- a/chrome/browser/ui/views/frame/browser_view_layout.cc +++ b/chrome/browser/ui/views/frame/browser_view_layout.cc
@@ -384,13 +384,15 @@ vertical_layout_rect_ = browser_view->GetLocalBounds(); int top_inset = delegate_->GetTopInsetInBrowserView(); int top = LayoutTitleBarForWebApp(top_inset); - top = LayoutTabStripRegion(top); - if (delegate_->IsTabStripVisible()) { - tab_strip_->SetBackgroundOffset(tab_strip_region_view_->GetMirroredX() + - browser_view_->GetMirroredX() + - delegate_->GetThemeBackgroundXInset()); + if (delegate_->ShouldLayoutTabStrip()) { + top = LayoutTabStripRegion(top); + if (delegate_->IsTabStripVisible()) { + tab_strip_->SetBackgroundOffset(tab_strip_region_view_->GetMirroredX() + + browser_view_->GetMirroredX() + + delegate_->GetThemeBackgroundXInset()); + } + top = LayoutWebUITabStrip(top); } - top = LayoutWebUITabStrip(top); top = LayoutToolbar(top); top = LayoutBookmarkAndInfoBars(top, browser_view->y());
diff --git a/chrome/browser/ui/views/frame/browser_view_layout_delegate.h b/chrome/browser/ui/views/frame/browser_view_layout_delegate.h index f4217b2..20824d6 100644 --- a/chrome/browser/ui/views/frame/browser_view_layout_delegate.h +++ b/chrome/browser/ui/views/frame/browser_view_layout_delegate.h
@@ -46,6 +46,7 @@ virtual bool IsWindowControlsOverlayEnabled() const = 0; virtual void UpdateWindowControlsOverlay( const gfx::Rect& available_titlebar_area) const = 0; + virtual bool ShouldLayoutTabStrip() const = 0; }; #endif // CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_VIEW_LAYOUT_DELEGATE_H_
diff --git a/chrome/browser/ui/views/frame/browser_view_layout_unittest.cc b/chrome/browser/ui/views/frame/browser_view_layout_unittest.cc index a0fe278..d5c9c26 100644 --- a/chrome/browser/ui/views/frame/browser_view_layout_unittest.cc +++ b/chrome/browser/ui/views/frame/browser_view_layout_unittest.cc
@@ -106,6 +106,7 @@ void MoveWindowForFindBarIfNecessary() const override {} bool IsWindowControlsOverlayEnabled() const override { return false; } void UpdateWindowControlsOverlay(const gfx::Rect& rect) const override {} + bool ShouldLayoutTabStrip() const override { return true; } private: bool tab_strip_visible_ = true;
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_mac.mm b/chrome/browser/ui/views/frame/immersive_mode_controller_mac.mm index fc865b14..f655245 100644 --- a/chrome/browser/ui/views/frame/immersive_mode_controller_mac.mm +++ b/chrome/browser/ui/views/frame/immersive_mode_controller_mac.mm
@@ -11,19 +11,30 @@ #include "base/mac/scoped_nsobject.h" #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" +#include "chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/frame/immersive_mode_controller.h" #include "chrome/browser/ui/views/frame/tab_strip_region_view.h" #include "chrome/browser/ui/views/frame/top_container_view.h" #include "chrome/common/chrome_features.h" +#include "ui/gfx/geometry/insets.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" +#include "ui/views/border.h" #include "ui/views/cocoa/native_widget_mac_ns_window_host.h" #include "ui/views/focus/focus_manager.h" #include "ui/views/view_observer.h" #include "ui/views/widget/widget.h" namespace { + +// The width of the traffic lights. Used to layout the tab strip leaving a hole +// for the traffic lights. +// TODO(https://crbug.com/1414521): Get this dynamically. Unfortunately the +// values in BrowserNonClientFrameViewMac::GetCaptionButtonInsets don't account +// for a window with an NSToolbar. +const int kTrafficLightsWidth = 70; + class ImmersiveModeControllerMac : public ImmersiveModeController, public views::FocusChangeListener, public views::ViewObserver, @@ -286,24 +297,48 @@ // ImmersiveModeControllerMac overrides: void SetEnabled(bool enabled) override; + void OnViewBoundsChanged(views::View* observed_view) override; private: + int tab_widget_height_ = 0; }; void ImmersiveModeTabbedControllerMac::SetEnabled(bool enabled) { BrowserView* browser_view = ImmersiveModeControllerMac::browser_view(); if (enabled) { - browser_view->tab_overlay_widget()->GetRootView()->AddChildView( - browser_view->tab_strip_region_view()); + tab_widget_height_ = browser_view->tab_strip_region_view()->height(); + tab_widget_height_ += static_cast<BrowserNonClientFrameViewMac*>( + browser_view->frame()->GetFrameView()) + ->GetTopInset(false); + // Without this -1 the tabs sit 1px too high. I assume this is because in + // fullscreen there is no resize handle. + tab_widget_height_ -= 1; - // TODO(https://crbug.com/1414521): The +8 height here is just a - // placeholder. Instead we need to move the top_container background to the - // tab_overlay_widget. - gfx::Size tab_region_size = browser_view->tab_strip_region_view()->size(); - tab_region_size.set_height(tab_region_size.height() + 8); - browser_view->tab_overlay_widget()->SetSize(tab_region_size); + // TODO(https://crbug.com/1414521): The |tab_overlay_widget()| draws + // underneath the traffic lights via an NSTitlebarViewController with + // NSLayoutAttributeTrailing layout. In order to propagate all mouse and + // keyboard events from AppKit back to Views the |tab_overlay_widget()| + // needs to be placed at the same location on screen as the + // NSTitlebarViewController. 0,0 is the correct location for the input to + // line up with the view, however this causes mouse actions to not make it + // to the traffic lights. For now the |tab_overlay_widget()| has been + // ordered behind the AppKit fullscreen window which hosts the traffic + // lights. This allows for interaction with the traffic lights and tab strip + // but child widgets of |tab_overlay_widget()| appear underneath the + // toolbar. Find a solution. + browser_view->tab_overlay_widget()->SetBounds( + gfx::Rect(0, 0, browser_view->top_container()->size().width(), + tab_widget_height_)); browser_view->tab_overlay_widget()->Show(); + // Inset the start of |tab_strip_region_view()| by |kTrafficLightsWidth|. + // This will leave a hole for the traffic light to appear. + browser_view->tab_overlay_view()->AddChildView( + browser_view->tab_strip_region_view()); + gfx::Insets insets = gfx::Insets::TLBR(0, kTrafficLightsWidth, 0, 0); + browser_view->tab_strip_region_view()->SetBorder( + views::CreateEmptyBorder(insets)); + views::NativeWidgetMacNSWindowHost* tab_overlay_host = views::NativeWidgetMacNSWindowHost::GetFromNativeWindow( browser_view->tab_overlay_widget()->GetNativeWindow()); @@ -311,12 +346,25 @@ ImmersiveModeControllerMac::SetEnabled(enabled); } else { browser_view->tab_overlay_widget()->Hide(); + browser_view->tab_strip_region_view()->SetBorder(nullptr); browser_view->top_container()->AddChildViewAt( browser_view->tab_strip_region_view(), 0); ImmersiveModeControllerMac::SetEnabled(enabled); } } +void ImmersiveModeTabbedControllerMac::OnViewBoundsChanged( + views::View* observed_view) { + // Resize the width of |tab_overlay_view()| and |tab_overlay_widget()|. + BrowserView* browser_view = ImmersiveModeControllerMac::browser_view(); + gfx::Size new_size(observed_view->size().width(), tab_widget_height_); + browser_view->tab_overlay_widget()->SetSize(new_size); + browser_view->tab_overlay_view()->SetSize(new_size); + browser_view->tab_strip_region_view()->SetSize(gfx::Size( + new_size.width(), browser_view->tab_strip_region_view()->height())); + ImmersiveModeControllerMac::OnViewBoundsChanged(observed_view); +} + std::unique_ptr<ImmersiveModeController> CreateImmersiveModeControllerMac() { if (base::FeatureList::IsEnabled(features::kImmersiveFullscreenTabs)) { return std::make_unique<ImmersiveModeTabbedControllerMac>();
diff --git a/chrome/browser/ui/views/frame/windows_caption_button.cc b/chrome/browser/ui/views/frame/windows_caption_button.cc index 10b7c49..ff6450c 100644 --- a/chrome/browser/ui/views/frame/windows_caption_button.cc +++ b/chrome/browser/ui/views/frame/windows_caption_button.cc
@@ -10,8 +10,8 @@ #include "chrome/browser/themes/theme_properties.h" #include "chrome/browser/ui/color/chrome_color_id.h" #include "chrome/browser/ui/frame/window_frame_util.h" +#include "chrome/browser/ui/views/frame/browser_frame_view_win.h" #include "chrome/browser/ui/views/frame/browser_view.h" -#include "chrome/browser/ui/views/frame/glass_browser_frame_view.h" #include "chrome/grit/theme_resources.h" #include "ui/base/metadata/metadata_impl_macros.h" #include "ui/base/theme_provider.h" @@ -23,7 +23,7 @@ WindowsCaptionButton::WindowsCaptionButton( PressedCallback callback, - GlassBrowserFrameView* frame_view, + BrowserFrameViewWin* frame_view, ViewID button_type, const std::u16string& accessible_name) : views::Button(std::move(callback)),
diff --git a/chrome/browser/ui/views/frame/windows_caption_button.h b/chrome/browser/ui/views/frame/windows_caption_button.h index d025b0b1..7fb3185 100644 --- a/chrome/browser/ui/views/frame/windows_caption_button.h +++ b/chrome/browser/ui/views/frame/windows_caption_button.h
@@ -14,13 +14,13 @@ #include "ui/gfx/canvas.h" #include "ui/views/controls/button/button.h" -class GlassBrowserFrameView; +class BrowserFrameViewWin; class WindowsCaptionButton : public views::Button { public: METADATA_HEADER(WindowsCaptionButton); WindowsCaptionButton(PressedCallback callback, - GlassBrowserFrameView* frame_view, + BrowserFrameViewWin* frame_view, ViewID button_type, const std::u16string& accessible_name); WindowsCaptionButton(const WindowsCaptionButton&) = delete; @@ -52,7 +52,7 @@ // Paints the minimize/maximize/restore/close icon for the button. void PaintSymbol(gfx::Canvas* canvas); - raw_ptr<GlassBrowserFrameView> frame_view_; + raw_ptr<BrowserFrameViewWin> frame_view_; std::unique_ptr<Windows10IconPainter> icon_painter_; ViewID button_type_; };
diff --git a/chrome/browser/ui/views/frame/windows_tab_search_caption_button.cc b/chrome/browser/ui/views/frame/windows_tab_search_caption_button.cc index 6d68998..868958e 100644 --- a/chrome/browser/ui/views/frame/windows_tab_search_caption_button.cc +++ b/chrome/browser/ui/views/frame/windows_tab_search_caption_button.cc
@@ -6,8 +6,8 @@ #include "chrome/browser/ui/browser_element_identifiers.h" #include "chrome/browser/ui/color/chrome_color_id.h" +#include "chrome/browser/ui/views/frame/browser_frame_view_win.h" #include "chrome/browser/ui/views/frame/browser_view.h" -#include "chrome/browser/ui/views/frame/glass_browser_frame_view.h" #include "chrome/browser/ui/views/tab_search_bubble_host.h" #include "chrome/grit/generated_resources.h" #include "ui/base/l10n/l10n_util.h" @@ -15,7 +15,7 @@ #include "ui/views/view_class_properties.h" WindowsTabSearchCaptionButton::WindowsTabSearchCaptionButton( - GlassBrowserFrameView* frame_view, + BrowserFrameViewWin* frame_view, ViewID button_type, const std::u16string& accessible_name) : WindowsCaptionButton(views::Button::PressedCallback(),
diff --git a/chrome/browser/ui/views/frame/windows_tab_search_caption_button.h b/chrome/browser/ui/views/frame/windows_tab_search_caption_button.h index 2aa061fa..678513c8 100644 --- a/chrome/browser/ui/views/frame/windows_tab_search_caption_button.h +++ b/chrome/browser/ui/views/frame/windows_tab_search_caption_button.h
@@ -8,13 +8,13 @@ #include "chrome/browser/ui/views/frame/windows_caption_button.h" #include "ui/base/metadata/metadata_header_macros.h" -class GlassBrowserFrameView; +class BrowserFrameViewWin; class TabSearchBubbleHost; class WindowsTabSearchCaptionButton : public WindowsCaptionButton { public: METADATA_HEADER(WindowsTabSearchCaptionButton); - WindowsTabSearchCaptionButton(GlassBrowserFrameView* frame_view, + WindowsTabSearchCaptionButton(BrowserFrameViewWin* frame_view, ViewID button_type, const std::u16string& accessible_name); WindowsTabSearchCaptionButton(const WindowsTabSearchCaptionButton&) = delete;
diff --git a/chrome/browser/ui/views/location_bar/content_setting_bubble_dialog_browsertest.cc b/chrome/browser/ui/views/location_bar/content_setting_bubble_dialog_browsertest.cc index a46a0bfd..5e49c1c 100644 --- a/chrome/browser/ui/views/location_bar/content_setting_bubble_dialog_browsertest.cc +++ b/chrome/browser/ui/views/location_bar/content_setting_bubble_dialog_browsertest.cc
@@ -2,14 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/auto_reset.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/test/scoped_feature_list.h" #include "base/time/time.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/chrome_content_browser_client.h" #include "chrome/browser/content_settings/page_specific_content_settings_delegate.h" #include "chrome/browser/download/download_request_limiter.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/blocked_content/chrome_popup_navigation_delegate.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/content_settings/content_setting_image_model.h" @@ -30,6 +33,7 @@ #include "components/permissions/permission_ui_selector.h" #include "components/permissions/request_type.h" #include "components/permissions/test/mock_permission_request.h" +#include "content/public/browser/navigation_entry.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" #include "ui/events/event.h" @@ -75,13 +79,31 @@ QuietUiReason simulated_reason_for_quiet_ui_; }; +// An override that returns a fake URL for every blocked popup, so the UI +// displays consistent strings for pixel tests. +class TestPopupNavigationDelegate : public ChromePopupNavigationDelegate { + public: + using ChromePopupNavigationDelegate::ChromePopupNavigationDelegate; + + // ChromePopupNavigationDelegate: + GURL GetURL() override { return GURL("http://blocked-popup/"); } +}; + +std::unique_ptr<blocked_content::PopupNavigationDelegate> +CreateTestPopupNavigationDelegate(NavigateParams params) { + return std::make_unique<TestPopupNavigationDelegate>(std::move(params)); +} + } // namespace using ImageType = ContentSettingImageModel::ImageType; class ContentSettingBubbleDialogTest : public DialogBrowserTest { public: - ContentSettingBubbleDialogTest() { + ContentSettingBubbleDialogTest() + : resetter_(&ChromeContentBrowserClient:: + GetPopupNavigationDelegateFactoryForTesting(), + &CreateTestPopupNavigationDelegate) { scoped_feature_list_.InitWithFeatures( {features::kQuietNotificationPrompts}, {permissions::features::kPermissionQuietChip}); @@ -102,6 +124,8 @@ void ShowUi(const std::string& name) override; private: + base::AutoReset<ChromeContentBrowserClient::PopupNavigationDelegateFactory> + resetter_; base::test::ScopedFeatureList scoped_feature_list_; absl::optional<permissions::MockPermissionRequest> notification_permission_request_; @@ -157,6 +181,9 @@ blocked_content::PopupBlockerTabHelper::FromWebContents(web_contents); // popup-many-10.html should generate 10 blocked popups. EXPECT_EQ(10u, helper->GetBlockedPopupsCount()); + // Set a fake URL so the UI displays a consistent string for pixel tests. + web_contents->GetController().GetVisibleEntry()->SetVirtualURL( + GURL("http://popuptest/")); break; } case ContentSettingsType::PROTOCOL_HANDLERS:
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc index d549d83..f8e5eefc 100644 --- a/chrome/browser/ui/views/location_bar/location_bar_view.cc +++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -1098,15 +1098,6 @@ return match_selection_timestamp(); } -void LocationBarView::AcceptInput() { - AcceptInput(base::TimeTicks()); -} - -void LocationBarView::AcceptInput(base::TimeTicks match_selection_timestamp) { - omnibox_view_->model()->AcceptInput(WindowOpenDisposition::CURRENT_TAB, - match_selection_timestamp); -} - void LocationBarView::FocusSearch() { // This is called by keyboard accelerator, so it's user-initiated. omnibox_view_->SetFocus(/*is_user_initiated=*/true);
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.h b/chrome/browser/ui/views/location_bar/location_bar_view.h index f7d7965..8057f45 100644 --- a/chrome/browser/ui/views/location_bar/location_bar_view.h +++ b/chrome/browser/ui/views/location_bar/location_bar_view.h
@@ -320,8 +320,6 @@ WindowOpenDisposition GetWindowOpenDisposition() const override; ui::PageTransition GetPageTransition() const override; base::TimeTicks GetMatchSelectionTimestamp() const override; - void AcceptInput() override; - void AcceptInput(base::TimeTicks match_selection_timestamp) override; void FocusSearch() override; void UpdateContentSettingsIcons() override; void SaveStateToContents(content::WebContents* contents) override;
diff --git a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc index 0eaafaf..a60f0b6 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
@@ -416,8 +416,8 @@ void OmniboxResultView::ButtonPressed(OmniboxPopupSelection::LineState state, const ui::Event& event) { - model_->TriggerPopupSelectionAction( - OmniboxPopupSelection(model_index_, state), event.time_stamp()); + model_->OpenSelection(OmniboxPopupSelection(model_index_, state), + event.time_stamp()); } ////////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/browser/ui/views/omnibox/omnibox_row_view.cc b/chrome/browser/ui/views/omnibox/omnibox_row_view.cc index 7c05ce6..79cfdc9 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_row_view.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_row_view.cc
@@ -7,6 +7,7 @@ #include "base/functional/bind.h" #include "base/i18n/case_conversion.h" #include "base/memory/raw_ptr.h" +#include "base/time/time.h" #include "chrome/browser/ui/color/chrome_color_id.h" #include "chrome/browser/ui/layout_constants.h" #include "chrome/browser/ui/omnibox/omnibox_theme.h" @@ -129,7 +130,7 @@ return true; } void OnMouseReleased(const ui::MouseEvent& event) override { - row_view_->model_->TriggerPopupSelectionAction(GetHeaderSelection()); + row_view_->model_->OpenSelection(GetHeaderSelection(), event.time_stamp()); } void OnMouseEntered(const ui::MouseEvent& event) override { UpdateUI(); } void OnMouseExited(const ui::MouseEvent& event) override { UpdateUI(); } @@ -208,7 +209,7 @@ private: void HeaderToggleButtonPressed() { - row_view_->model_->TriggerPopupSelectionAction(GetHeaderSelection()); + row_view_->model_->OpenSelection(GetHeaderSelection(), base::TimeTicks()); // The PrefChangeRegistrar will update the actual button toggle state. }
diff --git a/chrome/browser/ui/views/omnibox/omnibox_suggestion_button_row_view.cc b/chrome/browser/ui/views/omnibox/omnibox_suggestion_button_row_view.cc index 5a8fda3..42f7e06 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_suggestion_button_row_view.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_suggestion_button_row_view.cc
@@ -352,8 +352,7 @@ } else { WindowOpenDisposition disposition = ui::DispositionFromEventFlags(event.flags()); - model_->TriggerPopupSelectionAction(selection, event.time_stamp(), - disposition); + model_->OpenSelection(selection, event.time_stamp(), disposition); } }
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc index 06b3dea..bd53c0b 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
@@ -1587,13 +1587,8 @@ } else if (shift) { disposition = WindowOpenDisposition::NEW_WINDOW; } - if (model()->PopupIsOpen() && - model()->TriggerPopupSelectionAction( - model()->GetPopupSelection(), event.time_stamp(), disposition)) { - return true; - } else { - model()->AcceptInput(disposition, event.time_stamp()); - } + model()->OpenSelection(model()->GetPopupSelection(), event.time_stamp(), + disposition); return true; } case ui::VKEY_ESCAPE: @@ -1699,10 +1694,8 @@ if (model()->PopupIsOpen()) { OmniboxPopupSelection selection = model()->GetPopupSelection(); if (selection.IsButtonFocused() && !control && !alt && !shift) { - if (model()->TriggerPopupSelectionAction(selection, - event.time_stamp())) { - return true; - } + model()->OpenSelection(selection, event.time_stamp()); + return true; } } break;
diff --git a/chrome/browser/ui/views/passwords/password_save_update_view.cc b/chrome/browser/ui/views/passwords/password_save_update_view.cc index c7e2ac4..7a7829d 100644 --- a/chrome/browser/ui/views/passwords/password_save_update_view.cc +++ b/chrome/browser/ui/views/passwords/password_save_update_view.cc
@@ -714,6 +714,9 @@ [](PasswordSaveUpdateView* view, std::unique_ptr<CloseOnDeactivatePin> pin, bool reveal) { view->password_dropdown_->RevealPasswords(reveal); + // This is necessary on Windows since the bubble isn't activated again + // after the conlusion of the auth flow. + view->GetWidget()->Activate(); // Delay the destruction of `pin` for 1 sec to make sure the bubble // remains open till the OS closes the authentication dialog and // reactivates the bubble.
diff --git a/chrome/browser/ui/views/performance_controls/high_efficiency_interactive_ui_test.cc b/chrome/browser/ui/views/performance_controls/high_efficiency_interactive_ui_test.cc index 435cf0a..fc13bf5b 100644 --- a/chrome/browser/ui/views/performance_controls/high_efficiency_interactive_ui_test.cc +++ b/chrome/browser/ui/views/performance_controls/high_efficiency_interactive_ui_test.cc
@@ -35,6 +35,7 @@ #include "components/user_education/views/help_bubble_view.h" #include "content/public/test/browser_test.h" #include "net/dns/mock_host_resolver.h" +#include "third_party/blink/public/common/switches.h" #include "ui/base/interaction/element_identifier.h" #include "ui/base/interaction/element_tracker.h" #include "ui/base/text/bytes_formatting.h" @@ -152,6 +153,13 @@ HighEfficiencyDiscardPolicyInteractiveTest() = default; ~HighEfficiencyDiscardPolicyInteractiveTest() override = default; + void SetUpCommandLine(base::CommandLine* command_line) override { + HighEfficiencyInteractiveTest::SetUpCommandLine(command_line); + // Some builders are flaky due to slower loading interacting with + // deferred commits. + command_line->AppendSwitch(blink::switches::kAllowPreCommitInput); + } + auto PressKeyboard() { return Do(base::BindLambdaForTesting([=]() { ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), ui::VKEY_A, false, @@ -220,9 +228,8 @@ // Check that a form in the background but was interacted by the user // won't be discarded -// TODO(crbug.com/1415833): Re-enable this test IN_PROC_BROWSER_TEST_F(HighEfficiencyDiscardPolicyInteractiveTest, - DISABLED_TabWithFormNotDiscarded) { + TabWithFormNotDiscarded) { DEFINE_LOCAL_CUSTOM_ELEMENT_EVENT_TYPE(kInputIsFocused); DEFINE_LOCAL_CUSTOM_ELEMENT_EVENT_TYPE(kInputValueIsUpated); const DeepQuery input_text_box = {"#value"}; @@ -241,11 +248,6 @@ input_value_updated.test_function = "(el) => { return el.value === 'a'; }"; RunTestSequence( - SetOnIncompatibleAction(OnIncompatibleAction::kSkipTest, - "Some Linux window managers do not allow " - "programmatically raising/activating windows. " - "This skips the rest of the test."), - ActivateSurface(kBrowserViewElementId), FlushEvents(), InstrumentTab(kFirstTabContents, 0), NavigateWebContents(kFirstTabContents, GetURL("/form_search.html")), @@ -254,7 +256,7 @@ // Wait until the input text box is focused and simulate typing a letter ExecuteJsAt(kFirstTabContents, input_text_box, - "(el) => { el.select(); }"), + "(el) => { el.focus(); el.select(); }"), WaitForStateChange(kFirstTabContents, std::move(input_is_focused)), PressKeyboard(), WaitForStateChange(kFirstTabContents, std::move(input_value_updated)),
diff --git a/chrome/browser/ui/views/side_panel/read_anything/read_anything_controller.cc b/chrome/browser/ui/views/side_panel/read_anything/read_anything_controller.cc index c1f20c0..673d4f9 100644 --- a/chrome/browser/ui/views/side_panel/read_anything/read_anything_controller.cc +++ b/chrome/browser/ui/views/side_panel/read_anything/read_anything_controller.cc
@@ -6,70 +6,14 @@ #include <vector> -#include "base/containers/contains.h" -#include "base/memory/raw_ptr.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/browser_finder.h" -#include "chrome/browser/ui/tab_contents/tab_contents_iterator.h" #include "chrome/browser/ui/webui/side_panel/read_anything/read_anything_prefs.h" #include "chrome/common/accessibility/read_anything.mojom.h" #include "chrome/common/accessibility/read_anything_constants.h" -#include "content/public/browser/web_contents_observer.h" -#include "content/public/browser/web_contents_user_data.h" #include "ui/accessibility/accessibility_features.h" #include "ui/accessibility/ax_action_data.h" -class ReadAnythingWebContentsObserver - : public content::WebContentsObserver, - public content::WebContentsUserData<ReadAnythingWebContentsObserver> { - public: - ReadAnythingWebContentsObserver(const ReadAnythingWebContentsObserver&) = - delete; - ReadAnythingWebContentsObserver& operator=( - const ReadAnythingWebContentsObserver&) = delete; - ~ReadAnythingWebContentsObserver() override = default; - - // content::WebContentsObserver: - void AccessibilityEventReceived( - const content::AXEventNotificationDetails& details) override { - if (controller_) { - controller_->AccessibilityEventReceived(details); - } - } - - void WebContentsDestroyed() override { - if (controller_) { - controller_->WebContentsDestroyed(web_contents()); - } - } - - // This causes AXTreeSerializer to reset and send accessibility events of the - // AXTree when it is re-serialized. - void EnableAccessibility() { - // TODO(crbug.com/1266555): Only enable kReadAnythingAXMode. - web_contents()->EnableWebContentsOnlyAccessibilityMode(); - } - - void SetController(ReadAnythingController* controller) { - controller_ = controller; - } - - private: - friend class content::WebContentsUserData<ReadAnythingWebContentsObserver>; - - explicit ReadAnythingWebContentsObserver(content::WebContents* web_contents) - : content::WebContentsObserver(web_contents), - content::WebContentsUserData<ReadAnythingWebContentsObserver>( - *web_contents) {} - - raw_ptr<ReadAnythingController> controller_ = nullptr; - - WEB_CONTENTS_USER_DATA_KEY_DECL(); -}; - -WEB_CONTENTS_USER_DATA_KEY_IMPL(ReadAnythingWebContentsObserver); - ReadAnythingController::ReadAnythingController(ReadAnythingModel* model, Browser* browser) : model_(model), browser_(browser) { @@ -79,18 +23,12 @@ ReadAnythingController::~ReadAnythingController() { TabStripModelObserver::StopObservingAll(this); - for (auto* web_contents : AllTabContentses()) { - ReadAnythingWebContentsObserver* observer = - ReadAnythingWebContentsObserver::FromWebContents(web_contents); - if (observer) { - observer->SetController(nullptr); - } - } + Observe(nullptr); } void ReadAnythingController::Activate(bool active) { active_ = active; - NotifyActiveAXTreeIDChanged(); + OnActiveWebContentsChanged(); } /////////////////////////////////////////////////////////////////////////////// @@ -196,11 +134,12 @@ screen_ai::ScreenAIInstallState::GetInstance()); } #endif - NotifyActiveAXTreeIDChanged(); + OnActiveWebContentsChanged(); } void ReadAnythingController::OnUIDestroyed() { ui_ready_ = false; + Observe(nullptr); } void ReadAnythingController::OnLinkClicked(const ui::AXTreeID& target_tree_id, @@ -250,7 +189,7 @@ return; } if (selection.active_tab_changed()) { - NotifyActiveAXTreeIDChanged(); + OnActiveWebContentsChanged(); } } @@ -270,33 +209,48 @@ model_->AccessibilityEventReceived(details); } -void ReadAnythingController::WebContentsDestroyed( - content::WebContents* web_contents) { +void ReadAnythingController::WebContentsDestroyed() { content::RenderFrameHost* render_frame_host = - web_contents->GetPrimaryMainFrame(); + web_contents()->GetPrimaryMainFrame(); if (!render_frame_host) return; ui::AXTreeID tree_id = render_frame_host->GetAXTreeID(); model_->OnAXTreeDestroyed(tree_id); } -void ReadAnythingController::NotifyActiveAXTreeIDChanged() { +void ReadAnythingController::OnActiveWebContentsChanged() { + // TODO(crbug.com/1266555): Disable accessibility.and stop observing events + // on the now inactive tab. But make sure that we don't disable it for + // assistive technology users. Some options here are: + // 1. Cache the current AXMode of the active web contents before enabling + // accessibility, and reset the mode to that mode when the tab becomes + // inactive. + // 2. Set an AXContext on the web contents with web contents only mode + // enabled. + ui::AXTreeID tree_id = ui::AXTreeIDUnknown(); ukm::SourceId ukm_source_id = ukm::kInvalidSourceId; + content::WebContents* web_contents = nullptr; if (active_) { - content::WebContents* web_contents = - browser_->tab_strip_model()->GetActiveWebContents(); - if (!web_contents) { - return; + web_contents = browser_->tab_strip_model()->GetActiveWebContents(); + if (web_contents) { + content::RenderFrameHost* render_frame_host = + web_contents->GetPrimaryMainFrame(); + if (render_frame_host) { + tree_id = render_frame_host->GetAXTreeID(); + ukm_source_id = render_frame_host->GetPageUkmSourceId(); + } } - content::RenderFrameHost* render_frame_host = - web_contents->GetPrimaryMainFrame(); - if (!render_frame_host) { - return; - } - tree_id = render_frame_host->GetAXTreeID(); - ukm_source_id = render_frame_host->GetPageUkmSourceId(); - ObserveAccessibilityEventsOnActiveTab(); + } + + Observe(web_contents); + // Enable accessibility for the top level render frame and all descendants. + // This causes AXTreeSerializer to reset and send accessibility events of + // the AXTree when it is re-serialized. + // TODO(crbug.com/1266555): Only enable kReadAnythingAXMode while still + // causing the reset. + if (web_contents) { + web_contents->EnableWebContentsOnlyAccessibilityMode(); } model_->OnActiveAXTreeIDChanged(tree_id, ukm_source_id); } @@ -311,26 +265,3 @@ model_->ScreenAIServiceReady(); } #endif - -void ReadAnythingController::ObserveAccessibilityEventsOnActiveTab() { - content::WebContents* web_contents = - browser_->tab_strip_model()->GetActiveWebContents(); - if (!web_contents) { - return; - } - // CreateForWebContents is no-op if an observer already exists. - ReadAnythingWebContentsObserver::CreateForWebContents(web_contents); - ReadAnythingWebContentsObserver* observer = - ReadAnythingWebContentsObserver::FromWebContents(web_contents); - observer->SetController(this); - observer->EnableAccessibility(); - - // TODO(crbug.com/1266555): Disable accessibility.and stop observing events - // on the now inactive tab. But make sure that we don't disable it for - // assistive technology users. Some options here are: - // 1. Cache the current AXMode of the active web contents before enabling - // accessibility, and reset the mode to that mode when the tab becomes - // inactive. - // 2. Set an AXContext on the web contents with web contents only mode - // enabled. -}
diff --git a/chrome/browser/ui/views/side_panel/read_anything/read_anything_controller.h b/chrome/browser/ui/views/side_panel/read_anything/read_anything_controller.h index 00c2085..14b4432 100644 --- a/chrome/browser/ui/views/side_panel/read_anything/read_anything_controller.h +++ b/chrome/browser/ui/views/side_panel/read_anything/read_anything_controller.h
@@ -40,7 +40,8 @@ #if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE) public screen_ai::ScreenAIInstallState::Observer, #endif - public TabStripModelObserver { + public TabStripModelObserver, + public content::WebContentsObserver { public: ReadAnythingController(ReadAnythingModel* model, Browser* browser); ReadAnythingController(const ReadAnythingController&) = delete; @@ -52,14 +53,6 @@ void Activate(bool active); bool IsActiveForTesting() { return active_; } - // Called by ReadAnythingWebContentsObserver. Sends |details| to the WebUI. - void AccessibilityEventReceived( - const content::AXEventNotificationDetails& details); - - // Called by ReadAnythingWebContentsObserver. Notifies the WebUI that the - // AXTree for |web_contents| has been destroyed. - void WebContentsDestroyed(content::WebContents* web_contents); - private: friend class ReadAnythingControllerTest; @@ -94,17 +87,19 @@ const TabStripSelectionChange& selection) override; void OnTabStripModelDestroyed(TabStripModel* tab_strip_model) override; - // Notifies the model that the AXTreeID has changed. - void NotifyActiveAXTreeIDChanged(); + // content::WebContentsObserver: + void AccessibilityEventReceived( + const content::AXEventNotificationDetails& details) override; + void WebContentsDestroyed() override; - // Create a web contents observer for the active tab and enable web - // contents-only accessibility. This causes AXTreeSerializer to reset and send - // accessibility events of the AXTree when it is re-serialized. The WebUI - // receives these events and stores a copy of each web contents' AXTree. If - // the UI was destroyed, it stops receiving events. OnUIReady is called when - // it is re-created, indicating that it needs to restore its copy of each - // web contents' AXTree. - void ObserveAccessibilityEventsOnActiveTab(); + // When the active web contents changes (or the UI becomes active): + // 1. Begins observing the web contents of the active tab and enables web + // contents-only accessibility on that web contents. This causes + // AXTreeSerializer to reset and send accessibility events of the AXTree + // when it is re-serialized. The WebUI receives these events and stores a + // copy of the web contents' AXTree. + // 2. Notifies the model that the AXTreeID has changed. + void OnActiveWebContentsChanged(); const raw_ptr<ReadAnythingModel> model_;
diff --git a/chrome/browser/ui/web_applications/web_app_browser_controller.cc b/chrome/browser/ui/web_applications/web_app_browser_controller.cc index 46b0597..f7ef943b0 100644 --- a/chrome/browser/ui/web_applications/web_app_browser_controller.cc +++ b/chrome/browser/ui/web_applications/web_app_browser_controller.cc
@@ -267,14 +267,15 @@ } void WebAppBrowserController::OnRelationshipCheckComplete( - digital_asset_links::RelationshipCheckResult result) { + content_relationship_verification::RelationshipCheckResult result) { bool should_show_cct = false; switch (result) { - case digital_asset_links::RelationshipCheckResult::kSuccess: + case content_relationship_verification::RelationshipCheckResult::kSuccess: should_show_cct = false; break; - case digital_asset_links::RelationshipCheckResult::kFailure: - case digital_asset_links::RelationshipCheckResult::kNoConnection: + case content_relationship_verification::RelationshipCheckResult::kFailure: + case content_relationship_verification::RelationshipCheckResult:: + kNoConnection: should_show_cct = true; break; } @@ -670,9 +671,9 @@ void WebAppBrowserController::PerformDigitalAssetLinkVerification( Browser* browser) { #if BUILDFLAG(IS_CHROMEOS) - asset_link_handler_ = - std::make_unique<digital_asset_links::DigitalAssetLinksHandler>( - browser->profile()->GetURLLoaderFactory()); + asset_link_handler_ = std::make_unique< + content_relationship_verification::DigitalAssetLinksHandler>( + browser->profile()->GetURLLoaderFactory()); is_verified_ = absl::nullopt; #endif
diff --git a/chrome/browser/ui/web_applications/web_app_browser_controller.h b/chrome/browser/ui/web_applications/web_app_browser_controller.h index 09bfc87..0727bd5 100644 --- a/chrome/browser/ui/web_applications/web_app_browser_controller.h +++ b/chrome/browser/ui/web_applications/web_app_browser_controller.h
@@ -28,7 +28,7 @@ #include "ui/base/models/image_model.h" #if BUILDFLAG(IS_CHROMEOS) -#include "components/digital_asset_links/digital_asset_links_handler.h" // nogncheck +#include "components/content_relationship_verification/digital_asset_links_handler.h" // nogncheck #endif #if BUILDFLAG(IS_CHROMEOS_LACROS) @@ -44,7 +44,7 @@ } #endif // BUILDFLAG(IS_CHROMEOS_ASH) -namespace digital_asset_links { +namespace content_relationship_verification { class DigitalAssetLinksHandler; } @@ -154,7 +154,7 @@ const std::string& package_name, const std::string& fingerprint); void OnRelationshipCheckComplete( - digital_asset_links::RelationshipCheckResult result); + content_relationship_verification::RelationshipCheckResult result); #endif // BUILDFLAG(IS_CHROMEOS) #if BUILDFLAG(IS_CHROMEOS_LACROS) @@ -184,7 +184,7 @@ // Only used for web-only TWAs installed through the Play Store. absl::optional<bool> is_verified_; - std::unique_ptr<digital_asset_links::DigitalAssetLinksHandler> + std::unique_ptr<content_relationship_verification::DigitalAssetLinksHandler> asset_link_handler_; #endif // BUILDFLAG(IS_CHROMEOS)
diff --git a/chrome/browser/ui/webui/settings/ash/input_device_settings/input_device_settings_provider_unittest.cc b/chrome/browser/ui/webui/settings/ash/input_device_settings/input_device_settings_provider_unittest.cc index 71166c7..86e7a022 100644 --- a/chrome/browser/ui/webui/settings/ash/input_device_settings/input_device_settings_provider_unittest.cc +++ b/chrome/browser/ui/webui/settings/ash/input_device_settings/input_device_settings_provider_unittest.cc
@@ -70,7 +70,21 @@ override { return CloneMojomVector(pointing_sticks_); } - + const ::ash::mojom::KeyboardSettings* GetKeyboardSettings( + DeviceId id) override { + return nullptr; + } + const ::ash::mojom::TouchpadSettings* GetTouchpadSettings( + DeviceId id) override { + return nullptr; + } + const ::ash::mojom::MouseSettings* GetMouseSettings(DeviceId id) override { + return nullptr; + } + const ::ash::mojom::PointingStickSettings* GetPointingStickSettings( + DeviceId id) override { + return nullptr; + } void SetKeyboardSettings( DeviceId id, const ::ash::mojom::KeyboardSettings& settings) override {}
diff --git a/chrome/browser/ui/webui/side_panel/user_notes/user_notes.mojom b/chrome/browser/ui/webui/side_panel/user_notes/user_notes.mojom index cf7aead..68eaeb5 100644 --- a/chrome/browser/ui/webui/side_panel/user_notes/user_notes.mojom +++ b/chrome/browser/ui/webui/side_panel/user_notes/user_notes.mojom
@@ -87,6 +87,10 @@ // Called when the sort option has been updated and the profile pref should be // updated. SetSortOrder(bool sort_by_newest); + + // Return whether there are any notes in any pages. + // Used to determine if the empty state UI should be shown. + HasNotesInAnyPages() => (bool has_notes); }; // WebUI-side handler for requests from the browser.
diff --git a/chrome/browser/ui/webui/side_panel/user_notes/user_notes_page_handler.cc b/chrome/browser/ui/webui/side_panel/user_notes/user_notes_page_handler.cc index 8c28c900..f19d851f 100644 --- a/chrome/browser/ui/webui/side_panel/user_notes/user_notes_page_handler.cc +++ b/chrome/browser/ui/webui/side_panel/user_notes/user_notes_page_handler.cc
@@ -257,6 +257,22 @@ } } +void UserNotesPageHandler::HasNotesInAnyPages( + HasNotesInAnyPagesCallback callback) { + // TODO(crbug.com/1419697) Implement a more efficient API to retrieve number + // of powers for a specific type instead of using GetPowerOverviewsForType + service_->GetPowerOverviewsForType( + sync_pb::PowerBookmarkSpecifics::POWER_TYPE_NOTE, + base::BindOnce( + [](HasNotesInAnyPagesCallback callback, + std::vector<std::unique_ptr<power_bookmarks::PowerOverview>> + power_overviews) { + bool has_notes = power_overviews.size() > 0; + std::move(callback).Run(has_notes); + }, + std::move(callback))); +} + void UserNotesPageHandler::OnSortByNewestPrefChanged() { PrefService* pref_service = profile_->GetPrefs(); if (pref_service) {
diff --git a/chrome/browser/ui/webui/side_panel/user_notes/user_notes_page_handler.h b/chrome/browser/ui/webui/side_panel/user_notes/user_notes_page_handler.h index 1ab5da0..ac08090a9 100644 --- a/chrome/browser/ui/webui/side_panel/user_notes/user_notes_page_handler.h +++ b/chrome/browser/ui/webui/side_panel/user_notes/user_notes_page_handler.h
@@ -62,6 +62,7 @@ const ::GURL& url, ui::mojom::ClickModifiersPtr click_modifiers) override; void SetSortOrder(bool sort_by_newest) override; + void HasNotesInAnyPages(HasNotesInAnyPagesCallback callback) override; void OnSortByNewestPrefChanged();
diff --git a/chrome/browser/ui/webui/side_panel/user_notes/user_notes_page_handler_unittest.cc b/chrome/browser/ui/webui/side_panel/user_notes/user_notes_page_handler_unittest.cc index b06ce61f..ffb63b50 100644 --- a/chrome/browser/ui/webui/side_panel/user_notes/user_notes_page_handler_unittest.cc +++ b/chrome/browser/ui/webui/side_panel/user_notes/user_notes_page_handler_unittest.cc
@@ -227,4 +227,12 @@ ASSERT_EQ(GURL(u"https://newurl4"), handler()->GetCurrentTabUrlForTesting()); } +TEST_F(UserNotesPageHandlerTest, HasNotesOnAnyPages) { + side_panel::mojom::UserNotesPageHandlerAsyncWaiter waiter(handler()); + ASSERT_EQ(false, waiter.HasNotesInAnyPages()); + handler()->SetCurrentTabUrlForTesting(GURL(u"https://url1")); + ASSERT_TRUE(waiter.NewNoteFinished("note1")); + ASSERT_EQ(true, waiter.HasNotesInAnyPages()); +} + } // namespace
diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model.cc b/chrome/browser/webauthn/authenticator_request_dialog_model.cc index 93b7936..5884eb27 100644 --- a/chrome/browser/webauthn/authenticator_request_dialog_model.cc +++ b/chrome/browser/webauthn/authenticator_request_dialog_model.cc
@@ -650,8 +650,7 @@ const device::FidoAuthenticator& authenticator) { if (!authenticator.AuthenticatorTransport()) { #if BUILDFLAG(IS_WIN) - DCHECK_EQ(authenticator.GetType(), - device::FidoAuthenticator::Type::kWinNative); + DCHECK_EQ(authenticator.GetType(), device::AuthenticatorType::kWinNative); #endif // BUILDFLAG(IS_WIN) return; }
diff --git a/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc b/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc index c0f33857..40f3750e 100644 --- a/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc +++ b/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc
@@ -548,7 +548,7 @@ } #if BUILDFLAG(IS_WIN) - if (authenticator->GetType() == device::FidoAuthenticator::Type::kWinNative && + if (authenticator->GetType() == device::AuthenticatorType::kWinNative && static_cast<const device::WinWebAuthnApiAuthenticator*>(authenticator) ->ShowsPrivacyNotice()) { // The OS' native API includes an attestation prompt.
diff --git a/chrome/browser/win/conflicts/incompatible_applications_updater.cc b/chrome/browser/win/conflicts/incompatible_applications_updater.cc index 873b80a9..1f3e92e 100644 --- a/chrome/browser/win/conflicts/incompatible_applications_updater.cc +++ b/chrome/browser/win/conflicts/incompatible_applications_updater.cc
@@ -68,40 +68,33 @@ if (!value.is_dict()) return nullptr; - const base::Value* registry_is_hkcu_value = - value.FindKeyOfType("registry_is_hkcu", base::Value::Type::BOOLEAN); - const base::Value* registry_key_path_value = - value.FindKeyOfType("registry_key_path", base::Value::Type::STRING); - const base::Value* registry_wow64_access_value = - value.FindKeyOfType("registry_wow64_access", base::Value::Type::INTEGER); - const base::Value* allow_load_value = - value.FindKeyOfType("allow_load", base::Value::Type::BOOLEAN); - const base::Value* type_value = - value.FindKeyOfType("type", base::Value::Type::INTEGER); - const base::Value* message_url_value = - value.FindKeyOfType("message_url", base::Value::Type::STRING); + const base::Value::Dict& dict = value.GetDict(); + absl::optional<bool> registry_is_hkcu = dict.FindBool("registry_is_hkcu"); + const std::string* registry_key_path = dict.FindString("registry_key_path"); + absl::optional<int> registry_wow64_access = + dict.FindInt("registry_wow64_access"); + absl::optional<bool> allow_load = dict.FindBool("allow_load"); + absl::optional<int> type = dict.FindInt("type"); + const std::string* message_url = dict.FindString("message_url"); // All of the above are required for a valid application. - if (!registry_is_hkcu_value || !registry_key_path_value || - !registry_wow64_access_value || !allow_load_value || !type_value || - !message_url_value) { + if (!registry_is_hkcu || !registry_key_path || !registry_wow64_access || + !allow_load || !type || !message_url) { return nullptr; } InstalledApplications::ApplicationInfo application_info = { base::UTF8ToWide(name), - registry_is_hkcu_value->GetBool() ? HKEY_CURRENT_USER - : HKEY_LOCAL_MACHINE, - base::UTF8ToWide(registry_key_path_value->GetString()), - static_cast<REGSAM>(registry_wow64_access_value->GetInt())}; + *registry_is_hkcu ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, + base::UTF8ToWide(*registry_key_path), + static_cast<REGSAM>(*registry_wow64_access)}; auto blocklist_action = std::make_unique<chrome::conflicts::BlocklistAction>(); - blocklist_action->set_allow_load(allow_load_value->GetBool()); + blocklist_action->set_allow_load(*allow_load); blocklist_action->set_message_type( - static_cast<chrome::conflicts::BlocklistMessageType>( - type_value->GetInt())); - blocklist_action->set_message_url(message_url_value->GetString()); + static_cast<chrome::conflicts::BlocklistMessageType>(*type)); + blocklist_action->set_message_url(*message_url); return std::make_unique< IncompatibleApplicationsUpdater::IncompatibleApplication>(
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index fd1f0f6e..11c4b4f 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-main-1677477161-fa3e7882d465aefebf6c40416ffc5625a24594ba.profdata +chrome-linux-main-1677520762-483400653117e6cccd8f74772be757e2dc79c93a.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt index 9b0af3e..a691573c 100644 --- a/chrome/build/mac-arm.pgo.txt +++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@ -chrome-mac-arm-main-1677506397-e5ba997bd0152fa9c3a18d96e42eb7a351e61109.profdata +chrome-mac-arm-main-1677520762-d8987ca4a030e8e7e0de8f88fb0384bc32a1bfb7.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index 04aa0c5..7b2db968 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-main-1677499066-24efb56f6d80b5279656911e7050b6ea6bc97ba9.profdata +chrome-mac-main-1677520762-2d7666fce4fb5f853778434582b9d11d4d31bb2a.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index 7e34940..f1d291b 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1677499066-cacaed160a22e02d39505b344ef512a64c4aed13.profdata +chrome-win32-main-1677520818-ff46d4d8dc039ff21d56a5bbdece793055c639e4.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index 3dea86d2..1f798042 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1677499066-2cc4fc4384d64306a69d333d4d2587065c67c858.profdata +chrome-win64-main-1677520818-54a8caacd34207e830f91c8bb4f314979b3698a9.profdata
diff --git a/chrome/renderer/accessibility/read_anything_app_controller.cc b/chrome/renderer/accessibility/read_anything_app_controller.cc index f30505f..22fa430 100644 --- a/chrome/renderer/accessibility/read_anything_app_controller.cc +++ b/chrome/renderer/accessibility/read_anything_app_controller.cc
@@ -371,17 +371,18 @@ ui::AXTreeID previous_active_tree_id = model_.active_tree_id(); model_.SetActiveTreeId(tree_id); model_.SetActiveUkmSourceId(ukm_source_id); - // Unserialize all pending updates on the formerly active AXTree. + // Delete all pending updates on the formerly active AXTree. // TODO(crbug.com/1266555): If distillation is in progress, cancel the // distillation request. #if DCHECK_IS_ON() DCHECK(pending_updates_.empty() || model_.pending_updates_bundle_id() == previous_active_tree_id); #endif - UnserializeUpdates(std::move(pending_updates_), previous_active_tree_id); + pending_updates_.clear(); #if DCHECK_IS_ON() model_.SetPendingUpdatesBundleId(ui::AXTreeIDUnknown()); #endif + // When the UI first constructs, this function may be called before tree_id // has been added to trees_ in AccessibilityEventReceived. In that case, do // not distill. @@ -389,6 +390,7 @@ base::Contains(trees_, model_.active_tree_id())) { Distill(); } + OnAXTreeDestroyed(previous_active_tree_id); } void ReadAnythingAppController::OnAXTreeDestroyed(const ui::AXTreeID& tree_id) {
diff --git a/chrome/renderer/accessibility/read_anything_app_controller_browsertest.cc b/chrome/renderer/accessibility/read_anything_app_controller_browsertest.cc index 1a655626..0ba1cda4 100644 --- a/chrome/renderer/accessibility/read_anything_app_controller_browsertest.cc +++ b/chrome/renderer/accessibility/read_anything_app_controller_browsertest.cc
@@ -213,6 +213,10 @@ size_t GetNumTrees() { return controller_->trees_.size(); } + bool HasTree(ui::AXTreeID tree_id) { + return base::Contains(controller_->trees_, tree_id); + } + size_t GetNumPendingUpdates() { return controller_->pending_updates_.size(); } ui::AXTreeID tree_id_; @@ -614,15 +618,11 @@ updates.push_back(update); } // Add the three updates separately since they have different tree IDs. - for (int i = 0; i < 3; i++) { - AccessibilityEventReceived({updates[i]}); - } - - OnAXTreeDistilled({1}); - // Check that changing the active tree ID changes the active tree which is // used when using a v8 getter. for (int i = 0; i < 3; i++) { + AccessibilityEventReceived({updates[i]}); + OnAXTreeDistilled({1}); EXPECT_CALL(*distiller_, Distill).Times(1); OnActiveAXTreeIDChanged(tree_ids[i]); EXPECT_EQ("Tree " + base::NumberToString(i), GetTextContent(1)); @@ -633,6 +633,44 @@ OnActiveAXTreeIDChanged(tree_ids[2]); } +TEST_F(ReadAnythingAppControllerTest, + OnActiveAXTreeIDChanged_PreviousActiveTreeDestroyed) { + ui::AXTreeID tree_id_2 = ui::AXTreeID::CreateNewAXTreeID(); + ui::AXTreeUpdate update_2; + SetUpdateTreeID(&update_2, tree_id_2); + update_2.root_id = 1; + update_2.nodes.resize(1); + update_2.nodes[0].id = 1; + + ASSERT_EQ(1u, GetNumTrees()); + ASSERT_TRUE(HasTree(tree_id_)); + + // Add update 2. + AccessibilityEventReceived({update_2}); + ASSERT_EQ(2u, GetNumTrees()); + ASSERT_TRUE(HasTree(tree_id_)); + ASSERT_TRUE(HasTree(tree_id_2)); + OnAXTreeDistilled({1}); + EXPECT_CALL(*distiller_, Distill).Times(1); + + // Change the active tree id to the same id. Nothing happens. + OnActiveAXTreeIDChanged(tree_id_); + ASSERT_EQ(2u, GetNumTrees()); + ASSERT_TRUE(HasTree(tree_id_)); + ASSERT_TRUE(HasTree(tree_id_2)); + + // Change the active tree id to tree id 2. The previously active tree id's + // tree is deleted. + OnActiveAXTreeIDChanged(tree_id_2); + ASSERT_EQ(1u, GetNumTrees()); + ASSERT_TRUE(HasTree(tree_id_2)); + + // Change the active tree id to the same id. The previously active tree id's + // tree is deleted. + OnActiveAXTreeIDChanged(tree_id_); + ASSERT_EQ(0u, GetNumTrees()); +} + TEST_F(ReadAnythingAppControllerTest, DoesNotCrashIfActiveAXTreeIDUnknown) { EXPECT_CALL(*distiller_, Distill).Times(0); ui::AXTreeID tree_id = ui::AXTreeIDUnknown(); @@ -663,18 +701,27 @@ // Start with 1 tree (the tree created in SetUp). ASSERT_EQ(1u, GetNumTrees()); + ASSERT_TRUE(HasTree(tree_id_)); // Add the two trees. AccessibilityEventReceived({updates[0]}); ASSERT_EQ(2u, GetNumTrees()); + ASSERT_TRUE(HasTree(tree_id_)); + ASSERT_TRUE(HasTree(tree_ids[0])); AccessibilityEventReceived({updates[1]}); ASSERT_EQ(3u, GetNumTrees()); + ASSERT_TRUE(HasTree(tree_id_)); + ASSERT_TRUE(HasTree(tree_ids[0])); + ASSERT_TRUE(HasTree(tree_ids[1])); // Remove all of the trees. OnAXTreeDestroyed(tree_id_); ASSERT_EQ(2u, GetNumTrees()); + ASSERT_TRUE(HasTree(tree_ids[0])); + ASSERT_TRUE(HasTree(tree_ids[1])); OnAXTreeDestroyed(tree_ids[0]); ASSERT_EQ(1u, GetNumTrees()); + ASSERT_TRUE(HasTree(tree_ids[1])); OnAXTreeDestroyed(tree_ids[1]); ASSERT_EQ(0u, GetNumTrees()); } @@ -704,14 +751,21 @@ // Start with 1 tree (the tree created in SetUp). ASSERT_EQ(1u, GetNumTrees()); + ASSERT_TRUE(HasTree(tree_id_)); AccessibilityEventReceived({updates[0]}); ASSERT_EQ(1u, GetNumTrees()); + ASSERT_TRUE(HasTree(tree_id_)); // Add two trees. AccessibilityEventReceived({updates[1]}); ASSERT_EQ(2u, GetNumTrees()); + ASSERT_TRUE(HasTree(tree_id_)); + ASSERT_TRUE(HasTree(tree_ids[0])); AccessibilityEventReceived({updates[2]}); ASSERT_EQ(3u, GetNumTrees()); + ASSERT_TRUE(HasTree(tree_id_)); + ASSERT_TRUE(HasTree(tree_ids[0])); + ASSERT_TRUE(HasTree(tree_ids[1])); // Remove the grandparent tree (tree_ids[0]. When it is removed, its // child (tree_ids[1]) and its child's child (tree_ids[2]) are both removed. @@ -840,15 +894,11 @@ EXPECT_EQ(2u, GetNumPendingUpdates()); EXPECT_EQ("5", GetTextContent(1)); - // Switching the active AXTreeID flushes the pending updates. + // Switching the active AXTreeID deletes the pending updates. ui::AXTreeID tree_id_2 = ui::AXTreeID::CreateNewAXTreeID(); EXPECT_CALL(*distiller_, Distill).Times(0); OnActiveAXTreeIDChanged(tree_id_2); EXPECT_EQ(0u, GetNumPendingUpdates()); - - EXPECT_CALL(*distiller_, Distill).Times(1); - OnActiveAXTreeIDChanged(tree_id_); - EXPECT_EQ("567", GetTextContent(1)); } TEST_F(ReadAnythingAppControllerTest,
diff --git a/chrome/services/file_util/public/cpp/zip_file_creator_browsertest.cc b/chrome/services/file_util/public/cpp/zip_file_creator_browsertest.cc index 5343f69..3eb757bf 100644 --- a/chrome/services/file_util/public/cpp/zip_file_creator_browsertest.cc +++ b/chrome/services/file_util/public/cpp/zip_file_creator_browsertest.cc
@@ -26,11 +26,6 @@ namespace { -bool CreateFile(const base::FilePath& file, const std::string& content) { - return base::WriteFile(file, content.c_str(), content.size()) == - static_cast<int>(content.size()); -} - class ZipFileCreatorTest : public InProcessBrowserTest { protected: void SetUpOnMainThread() override { @@ -276,7 +271,7 @@ for (int i = 1; i < 90; i++) { base::FilePath file(std::to_string(i) + ".txt"); std::string content = "Hello" + std::to_string(i); - ASSERT_TRUE(CreateFile(root_dir.Append(file), content)); + ASSERT_TRUE(base::WriteFile(root_dir.Append(file), content)); file_tree_content[file] = content; } for (int i = 1; i <= 10; i++) { @@ -287,7 +282,7 @@ base::FilePath file = dir.Append(std::to_string(j) + ".txt"); std::string content = "Hello" + std::to_string(i) + "/" + std::to_string(j); - ASSERT_TRUE(CreateFile(root_dir.Append(file), content)); + ASSERT_TRUE(base::WriteFile(root_dir.Append(file), content)); file_tree_content[file] = content; } }
diff --git a/chrome/services/media_gallery_util/media_parser_android_unittest.cc b/chrome/services/media_gallery_util/media_parser_android_unittest.cc index a50d4537..eb75231 100644 --- a/chrome/services/media_gallery_util/media_parser_android_unittest.cc +++ b/chrome/services/media_gallery_util/media_parser_android_unittest.cc
@@ -179,7 +179,7 @@ // Test to verify frame extraction will fail on invalid video file. TEST_F(MediaParserAndroidTest, VideoFrameExtractionInvalidFile) { base::FilePath dummy_file = temp_dir().AppendASCII("test.txt"); - EXPECT_GT(base::WriteFile(dummy_file, "123", sizeof("123")), 0); + EXPECT_TRUE(base::WriteFile(dummy_file, "123")); EXPECT_FALSE(ExtractFrame(dummy_file, "video/webm")); }
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 80b00069..603d7dbd 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -3553,7 +3553,9 @@ "../browser/ui/views/web_apps/web_app_uninstall_dialog_browsertest.cc", ] if (is_win) { - sources += [ "../browser/ui/views/frame/glass_browser_frame_view_browsertest_win.cc" ] + sources += [ + "../browser/ui/views/frame/browser_frame_view_browsertest_win.cc", + ] } if (is_mac) { sources += [ @@ -4025,6 +4027,7 @@ "../browser/ash/policy/reporting/metrics_reporting/network/network_events_observer_browsertest.cc", "../browser/ash/policy/reporting/metrics_reporting/network/network_info_sampler_browsertest.cc", "../browser/ash/policy/reporting/metrics_reporting/usb/usb_events_browsertest.cc", + "../browser/ash/policy/reporting/os_updates/os_updates_reporter_browsertest.cc", "../browser/ash/policy/reporting/user_added_removed/user_added_removed_reporter_browsertest.cc", "../browser/ash/policy/status_collector/child_status_collector_browsertest.cc", "../browser/ash/policy/status_collector/device_status_collector_browsertest.cc", @@ -4843,6 +4846,7 @@ "../browser/lacros/field_trial_service_lacros_browsertest.cc", "../browser/lacros/file_manager_lacros_browsertest.cc", "../browser/lacros/idle_service_lacros_browsertest.cc", + "../browser/lacros/multitask_menu_nudge_delegate_lacros_browsertest.cc", "../browser/sync/test/lacros/sync_apps_toggle_sharing_lacros_browsertest.cc", "../browser/sync/test/lacros/sync_custom_passphrase_sharing_lacros_browsertest.cc", "../browser/upgrade_detector/get_installed_version_lacros_browsertest.cc", @@ -7497,6 +7501,7 @@ "../browser/ui/ash/desks/chrome_desks_templates_delegate_unittest.cc", "../browser/ui/ash/device_scheduled_reboot/reboot_notification_controller_unittest.cc", "../browser/ui/ash/device_scheduled_reboot/scheduled_reboot_dialog_unittest.cc", + "../browser/ui/ash/glanceables/glanceables_keyed_service_factory_unittest.cc", "../browser/ui/ash/global_media_controls/media_notification_provider_impl_unittest.cc", "../browser/ui/ash/holding_space/holding_space_keyed_service_unittest.cc", "../browser/ui/ash/ime_controller_client_impl_unittest.cc",
diff --git a/chrome/test/base/devtools_listener.cc b/chrome/test/base/devtools_listener.cc index aeea968..37f788a 100644 --- a/chrome/test/base/devtools_listener.cc +++ b/chrome/test/base/devtools_listener.cc
@@ -177,7 +177,7 @@ result->Set("result", std::move(entries)); CHECK(base::JSONWriter::Write(*result, &coverage)); - base::WriteFile(path, coverage.data(), coverage.size()); + base::WriteFile(path, coverage); script_coverage_.clear(); script_hash_map_.clear(); @@ -268,7 +268,7 @@ store.AppendASCII("scripts").AppendASCII(hash.append(".js.json")); CHECK(base::JSONWriter::Write(*params, &text)); if (!base::PathExists(path)) // script de-duplication - base::WriteFile(path, text.data(), text.size()); + base::WriteFile(path, text); value_.clear(); } }
diff --git a/chrome/test/base/test_browser_window.h b/chrome/test/base/test_browser_window.h index 2870b502..32b7bf4 100644 --- a/chrome/test/base/test_browser_window.h +++ b/chrome/test/base/test_browser_window.h
@@ -289,8 +289,6 @@ WindowOpenDisposition GetWindowOpenDisposition() const override; ui::PageTransition GetPageTransition() const override; base::TimeTicks GetMatchSelectionTimestamp() const override; - void AcceptInput() override {} - void AcceptInput(base::TimeTicks match_selection_timestamp) override {} void FocusLocation(bool select_all) override {} void FocusSearch() override {} void UpdateContentSettingsIcons() override {}
diff --git a/chrome/test/base/ui_test_utils.cc b/chrome/test/base/ui_test_utils.cc index c5343ed4..f4d21430 100644 --- a/chrome/test/base/ui_test_utils.cc +++ b/chrome/test/base/ui_test_utils.cc
@@ -456,11 +456,10 @@ void SendToOmniboxAndSubmit(Browser* browser, const std::string& input, base::TimeTicks match_selection_timestamp) { - LocationBar* location_bar = browser->window()->GetLocationBar(); - OmniboxView* omnibox = location_bar->GetOmniboxView(); + OmniboxView* omnibox = browser->window()->GetLocationBar()->GetOmniboxView(); omnibox->model()->OnSetFocus(/*control_down=*/false); omnibox->SetUserText(base::ASCIIToUTF16(input)); - location_bar->AcceptInput(match_selection_timestamp); + omnibox->model()->OpenSelection(match_selection_timestamp); WaitForAutocompleteDone(browser); }
diff --git a/chrome/test/chromedriver/chrome_launcher.cc b/chrome/test/chromedriver/chrome_launcher.cc index 44e8d5f..5a57d8b 100644 --- a/chrome/test/chromedriver/chrome_launcher.cc +++ b/chrome/test/chromedriver/chrome_launcher.cc
@@ -939,8 +939,7 @@ if (!temp_crx_dir.CreateUniqueTempDir()) return Status(kUnknownError, "cannot create temp dir"); base::FilePath extension_crx = temp_crx_dir.GetPath().AppendASCII("temp.crx"); - int size = static_cast<int>(decoded_extension.length()); - if (base::WriteFile(extension_crx, decoded_extension.c_str(), size) != size) { + if (!base::WriteFile(extension_crx, decoded_extension)) { return Status(kUnknownError, "cannot write file"); } @@ -1025,9 +1024,7 @@ } else { manifest->Set("key", public_key_base64); base::JSONWriter::Write(*manifest, &manifest_data); - if (base::WriteFile( - manifest_path, manifest_data.c_str(), manifest_data.size()) != - static_cast<int>(manifest_data.size())) { + if (!base::WriteFile(manifest_path, manifest_data)) { return Status(kUnknownError, "cannot add 'key' to manifest"); } } @@ -1107,8 +1104,7 @@ base::JSONWriter::Write(*prefs, &prefs_str); VLOG(0) << "Populating " << path.BaseName().value() << " file: " << PrettyPrintValue(base::Value(prefs->Clone())); - if (static_cast<int>(prefs_str.length()) != base::WriteFile( - path, prefs_str.c_str(), prefs_str.length())) { + if (!base::WriteFile(path, prefs_str)) { return Status(kUnknownError, "failed to write prefs file"); } return Status(kOk); @@ -1155,8 +1151,7 @@ // Write empty "First Run" file, otherwise Chrome will wipe the default // profile that was written. - if (base::WriteFile( - user_data_dir.Append(chrome::kFirstRunSentinel), "", 0) != 0) { + if (!base::WriteFile(user_data_dir.Append(chrome::kFirstRunSentinel), "")) { return Status(kUnknownError, "failed to write first run file"); } return Status(kOk);
diff --git a/chrome/test/chromedriver/chrome_launcher_unittest.cc b/chrome/test/chromedriver/chrome_launcher_unittest.cc index db86710e..49bfcdd 100644 --- a/chrome/test/chromedriver/chrome_launcher_unittest.cc +++ b/chrome/test/chromedriver/chrome_launcher_unittest.cc
@@ -225,7 +225,7 @@ char data[] = "12345\nblahblah"; base::FilePath temp_file = temp_dir.GetPath().Append(FILE_PATH_LITERAL("DevToolsActivePort")); - ASSERT_TRUE(base::WriteFile(temp_file, data, strlen(data))); + ASSERT_TRUE(base::WriteFile(temp_file, data)); int port; ASSERT_TRUE( internal::ParseDevToolsActivePortFile(temp_dir.GetPath(), &port).IsOk()); @@ -238,7 +238,7 @@ char data[] = "12345"; base::FilePath temp_file = temp_dir.GetPath().Append(FILE_PATH_LITERAL("DevToolsActivePort")); - ASSERT_TRUE(base::WriteFile(temp_file, data, strlen(data))); + ASSERT_TRUE(base::WriteFile(temp_file, data)); int port = 1111; ASSERT_FALSE( internal::ParseDevToolsActivePortFile(temp_dir.GetPath(), &port).IsOk()); @@ -251,7 +251,7 @@ char data[] = "12345asdf\nblahblah"; base::FilePath temp_file = temp_dir.GetPath().Append(FILE_PATH_LITERAL("DevToolsActivePort")); - ASSERT_TRUE(base::WriteFile(temp_file, data, strlen(data))); + ASSERT_TRUE(base::WriteFile(temp_file, data)); int port; ASSERT_FALSE( internal::ParseDevToolsActivePortFile(temp_dir.GetPath(), &port).IsOk()); @@ -274,7 +274,7 @@ base::FilePath temp_file = temp_dir.GetPath().Append(FILE_PATH_LITERAL("DevToolsActivePort")); char data[] = "12345asdf\nblahblah"; - base::WriteFile(temp_file, data, strlen(data)); + base::WriteFile(temp_file, data); ASSERT_TRUE( internal::RemoveOldDevToolsActivePortFile(temp_dir.GetPath()).IsOk()); ASSERT_FALSE(base::PathExists(temp_file));
diff --git a/chrome/test/chromedriver/util.cc b/chrome/test/chromedriver/util.cc index 08ec8233..84638c2 100644 --- a/chrome/test/chromedriver/util.cc +++ b/chrome/test/chromedriver/util.cc
@@ -104,9 +104,9 @@ return Status(kUnknownError, "unable to create temp dir"); base::FilePath archive = dir.GetPath().AppendASCII("temp.zip"); - int length = bytes.length(); - if (base::WriteFile(archive, bytes.c_str(), length) != length) + if (!base::WriteFile(archive, bytes)) { return Status(kUnknownError, "could not write file to temp dir"); + } if (!zip::Unzip(archive, unzip_dir)) return Status(kUnknownError, "could not unzip archive");
diff --git a/chrome/test/data/popup_blocker/popup-many-10.html b/chrome/test/data/popup_blocker/popup-many-10.html index c93d380..6efb0d2 100644 --- a/chrome/test/data/popup_blocker/popup-many-10.html +++ b/chrome/test/data/popup_blocker/popup-many-10.html
@@ -3,8 +3,8 @@ <title>Popup created using window.open</title> <script> function popup(name) { - window.open("popup-success" + name + ".html", - name, "menubar=1, resizable=1, width=350, height=250"); + window.open("popup-success.html", name, + "menubar=1, resizable=1, width=350, height=250"); } function test() {
diff --git a/chrome/test/data/webui/new_tab_page/modules/history_clusters/module_test.ts b/chrome/test/data/webui/new_tab_page/modules/history_clusters/module_test.ts index 265905fc..4bb12376 100644 --- a/chrome/test/data/webui/new_tab_page/modules/history_clusters/module_test.ts +++ b/chrome/test/data/webui/new_tab_page/modules/history_clusters/module_test.ts
@@ -4,9 +4,9 @@ import 'chrome://webui-test/mojo_webui_test_support.js'; -import {Cluster, RawVisitData, URLVisit} from 'chrome://new-tab-page/history_cluster_types.mojom-webui.js'; +import {Cluster, RawVisitData} from 'chrome://new-tab-page/history_cluster_types.mojom-webui.js'; import {PageHandlerRemote} from 'chrome://new-tab-page/history_clusters.mojom-webui.js'; -import {historyClustersDescriptor, HistoryClustersModuleElement, HistoryClustersProxyImpl} from 'chrome://new-tab-page/lazy_load.js'; +import {HistoryClusterLayoutType, historyClustersDescriptor, HistoryClustersModuleElement, HistoryClustersProxyImpl} from 'chrome://new-tab-page/lazy_load.js'; import {$$} from 'chrome://new-tab-page/new_tab_page.js'; import {assertEquals, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js'; @@ -25,32 +25,18 @@ new HistoryClustersProxyImpl(mock))); }); - function createSampleCluster(overrides?: Partial<Cluster>): Cluster { + function createSampleCluster( + numVisits: number = 1, numImageVisits: number = 0, + overrides?: Partial<Cluster>): Cluster { const rawVisitData: RawVisitData = { url: {url: ''}, visitTime: {internalValue: BigInt(0)}, }; - const urlVisit1: URLVisit = { - visitId: BigInt(1), - normalizedUrl: {url: 'https://www.google.com'}, - urlForDisplay: 'https://www.google.com', - pageTitle: 'Test Title', - titleMatchPositions: [], - urlForDisplayMatchPositions: [], - duplicates: [], - relativeDate: '', - annotations: [], - debugInfo: {}, - rawVisitData: rawVisitData, - imageUrl: undefined, - isKnownToSync: false, - }; - const cluster: Cluster = Object.assign( { id: BigInt(111), - visits: [urlVisit1], + visits: [], label: undefined, labelMatchPositions: [], relatedSearches: [], @@ -60,6 +46,26 @@ }, overrides); + for (let i = 0; i < numVisits; i++) { + cluster.visits.push({ + visitId: BigInt(i), + normalizedUrl: {url: `https://www.google.com/${i}`}, + urlForDisplay: `www.google.com/${i}`, + pageTitle: `Test Title ${i}`, + titleMatchPositions: [], + urlForDisplayMatchPositions: [], + duplicates: [], + relativeDate: '', + annotations: [], + debugInfo: {}, + rawVisitData: rawVisitData, + imageUrl: i >= numImageVisits ? undefined : { + url: `https://image.com/${i}`, + }, + isKnownToSync: false, + }); + } + return cluster; } @@ -76,10 +82,10 @@ assertEquals(null, moduleElement); }); - test('Module created when history cluster data available', async () => { + test('No module created when data does not match layouts', async () => { // Arrange. handler.setResultFor( - 'getCluster', Promise.resolve({cluster: createSampleCluster()})); + 'getCluster', Promise.resolve({cluster: createSampleCluster(2, 0)})); // Act. const moduleElement = await historyClustersDescriptor.initialize(0) as @@ -87,12 +93,72 @@ // Assert. await handler.whenCalled('getCluster'); - assertTrue(!!moduleElement); + assertEquals(null, moduleElement); + }); + + test('Layout 1 is used', async () => { + // Arrange. + // 3 total visits (2 + SRP) with 2 being image visits. + handler.setResultFor( + 'getCluster', Promise.resolve({cluster: createSampleCluster(3, 2)})); + + // Act. + const moduleElement = await historyClustersDescriptor.initialize(0) as + HistoryClustersModuleElement; + document.body.append(moduleElement); + await waitAfterNextRender(moduleElement); + + // Assert. + const layoutElements = + moduleElement.shadowRoot!.querySelectorAll('.layout'); + assertEquals(HistoryClusterLayoutType.LAYOUT_1, moduleElement.layoutType); + assertEquals(layoutElements.length, 1); + assertEquals(layoutElements[0]!.id, 'layout1'); + }); + + test('Layout 2 is used', async () => { + // Arrange. + // 4 total visits (3 + SRP) with 1 being an image visit. + handler.setResultFor( + 'getCluster', Promise.resolve({cluster: createSampleCluster(4, 1)})); + + // Act. + const moduleElement = await historyClustersDescriptor.initialize(0) as + HistoryClustersModuleElement; + document.body.append(moduleElement); + await waitAfterNextRender(moduleElement); + + // Assert. + const layoutElements = + moduleElement.shadowRoot!.querySelectorAll('.layout'); + assertEquals(HistoryClusterLayoutType.LAYOUT_2, moduleElement.layoutType); + assertEquals(layoutElements.length, 1); + assertEquals(layoutElements[0]!.id, 'layout2'); + }); + + test('Layout 3 is used', async () => { + // Arrange. + // 5 total visits (4 + SRP) with 2 being image visits. + handler.setResultFor( + 'getCluster', Promise.resolve({cluster: createSampleCluster(5, 2)})); + + // Act. + const moduleElement = await historyClustersDescriptor.initialize(0) as + HistoryClustersModuleElement; + document.body.append(moduleElement); + await waitAfterNextRender(moduleElement); + + // Assert. + const layoutElements = + moduleElement.shadowRoot!.querySelectorAll('.layout'); + assertEquals(HistoryClusterLayoutType.LAYOUT_3, moduleElement.layoutType); + assertEquals(layoutElements.length, 1); + assertEquals(layoutElements[0]!.id, 'layout3'); }); test('Tile element populated with correct data', async () => { handler.setResultFor( - 'getCluster', Promise.resolve({cluster: createSampleCluster()})); + 'getCluster', Promise.resolve({cluster: createSampleCluster(3, 2)})); const moduleElement = await historyClustersDescriptor.initialize(0) as HistoryClustersModuleElement; @@ -105,6 +171,6 @@ const tileElement = $$(moduleElement, 'ntp-history-clusters-tile'); assertTrue(!!tileElement); - assertEquals($$(tileElement, '#title')!.innerHTML, 'Test Title'); + assertEquals($$(tileElement, '#title')!.innerHTML, 'Test Title 0'); }); });
diff --git a/chrome/test/data/webui/tab_strip/tab_list_test.ts b/chrome/test/data/webui/tab_strip/tab_list_test.ts index fa79c61..02c44fb5 100644 --- a/chrome/test/data/webui/tab_strip/tab_list_test.ts +++ b/chrome/test/data/webui/tab_strip/tab_list_test.ts
@@ -306,6 +306,7 @@ test('PlacePinnedTabElementAnimatesTabsWithinSameColumn', async () => { tabs.forEach(pinTabAt); + await flushTasks(); await tabList.animationPromises; // Test moving a tab within the same column. If a tab is moved from index 0
diff --git a/chrome/test/data/webui/tab_strip/tab_test.ts b/chrome/test/data/webui/tab_strip/tab_test.ts index ec7f471..cd0b90b5 100644 --- a/chrome/test/data/webui/tab_strip/tab_test.ts +++ b/chrome/test/data/webui/tab_strip/tab_test.ts
@@ -59,65 +59,6 @@ document.body.appendChild(tabElement); }); - test('slideIn animates scale for the last tab', async () => { - document.documentElement.dir = 'ltr'; - tabElement.style.paddingRight = '100px'; - const tabElementStyle = window.getComputedStyle(tabElement); - - const animationPromise = tabElement.slideIn(); - // Before animation completes. - assertEquals('20px', tabElementStyle.paddingRight); - assertEquals('280px', tabElementStyle.maxWidth); - assertEquals('matrix(0, 0, 0, 0, 0, 0)', tabElementStyle.transform); - await animationPromise; - // After animation completes. - assertEquals('100px', tabElementStyle.paddingRight); - assertEquals('none', tabElementStyle.maxWidth); - assertEquals('none', tabElementStyle.transform); - }); - - test('slideIn animations for not the last tab', async () => { - // Add another element to make sure the element being tested is not the - // last. - document.body.appendChild(document.createElement('div')); - - document.documentElement.dir = 'ltr'; - tabElement.style.paddingRight = '100px'; - const tabElementStyle = window.getComputedStyle(tabElement); - - const animationPromise = tabElement.slideIn(); - // Before animation completes. - assertEquals('0px', tabElementStyle.paddingRight); - assertEquals('0px', tabElementStyle.maxWidth); - assertEquals('matrix(0, 0, 0, 0, 0, 0)', tabElementStyle.transform); - await animationPromise; - // After animation completes. - assertEquals('100px', tabElementStyle.paddingRight); - assertEquals('none', tabElementStyle.maxWidth); - assertEquals('none', tabElementStyle.transform); - }); - - test('slideIn animations right to left for RTL languages', async () => { - // Add another element to make sure the element being tested is not the - // last. - document.body.appendChild(document.createElement('div')); - - document.documentElement.dir = 'rtl'; - tabElement.style.paddingLeft = '100px'; - const tabElementStyle = window.getComputedStyle(tabElement); - - const animationPromise = tabElement.slideIn(); - // Before animation completes. - assertEquals('0px', tabElementStyle.paddingLeft); - assertEquals('0px', tabElementStyle.maxWidth); - assertEquals('matrix(0, 0, 0, 0, 0, 0)', tabElementStyle.transform); - await animationPromise; - // After animation completes. - assertEquals('100px', tabElementStyle.paddingLeft); - assertEquals('none', tabElementStyle.maxWidth); - assertEquals('none', tabElementStyle.transform); - }); - test('slideOut animates out the element', async () => { testTabsApiProxy.setVisible(true); const tabElementStyle = window.getComputedStyle(tabElement);
diff --git a/chrome/test/ppapi/ppapi_browsertest.cc b/chrome/test/ppapi/ppapi_browsertest.cc index fb52f2f2..aea70a3 100644 --- a/chrome/test/ppapi/ppapi_browsertest.cc +++ b/chrome/test/ppapi/ppapi_browsertest.cc
@@ -1585,20 +1585,18 @@ RUN_FILEIO_PRIVATE_SUBTESTS; } -#define SETUP_FOR_FILEREF_TESTS \ - const char kContents[] = "Hello from browser"; \ - base::ScopedAllowBlockingForTesting allow_blocking; \ - base::ScopedTempDir temp_dir; \ - ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); \ - base::FilePath existing_filename = temp_dir.GetPath().AppendASCII("foo"); \ - ASSERT_EQ( \ - static_cast<int>(sizeof(kContents) - 1), \ - base::WriteFile(existing_filename, kContents, sizeof(kContents) - 1)); \ - PPAPITestSelectFileDialogFactory::SelectedFileInfoList file_info_list; \ - file_info_list.push_back( \ - ui::SelectedFileInfo(existing_filename, existing_filename)); \ - PPAPITestSelectFileDialogFactory test_dialog_factory( \ - PPAPITestSelectFileDialogFactory::RESPOND_WITH_FILE_LIST, \ +#define SETUP_FOR_FILEREF_TESTS \ + const char kContents[] = "Hello from browser"; \ + base::ScopedAllowBlockingForTesting allow_blocking; \ + base::ScopedTempDir temp_dir; \ + ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); \ + base::FilePath existing_filename = temp_dir.GetPath().AppendASCII("foo"); \ + ASSERT_TRUE(base::WriteFile(existing_filename, kContents)); \ + PPAPITestSelectFileDialogFactory::SelectedFileInfoList file_info_list; \ + file_info_list.emplace_back( \ + ui::SelectedFileInfo(existing_filename, existing_filename)); \ + PPAPITestSelectFileDialogFactory test_dialog_factory( \ + PPAPITestSelectFileDialogFactory::RESPOND_WITH_FILE_LIST, \ file_info_list); // FileRef tests.
diff --git a/chrome/test/ppapi/ppapi_filechooser_browsertest.cc b/chrome/test/ppapi/ppapi_filechooser_browsertest.cc index 30e9e0e1..f141cfd 100644 --- a/chrome/test/ppapi/ppapi_filechooser_browsertest.cc +++ b/chrome/test/ppapi/ppapi_filechooser_browsertest.cc
@@ -149,9 +149,7 @@ ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); base::FilePath existing_filename = temp_dir.GetPath().AppendASCII("foo"); - ASSERT_EQ( - static_cast<int>(sizeof(kContents) - 1), - base::WriteFile(existing_filename, kContents, sizeof(kContents) - 1)); + ASSERT_TRUE(base::WriteFile(existing_filename, kContents)); PPAPITestSelectFileDialogFactory::SelectedFileInfoList file_info_list; file_info_list.push_back( @@ -334,9 +332,7 @@ ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); base::FilePath existing_filename = temp_dir.GetPath().AppendASCII("foo"); - ASSERT_EQ( - static_cast<int>(sizeof(kContents) - 1), - base::WriteFile(existing_filename, kContents, sizeof(kContents) - 1)); + ASSERT_TRUE(base::WriteFile(existing_filename, kContents)); safe_browsing_test_configuration_.default_result = safe_browsing::DownloadCheckResult::DANGEROUS;
diff --git a/chromecast/base/cast_sys_info_dummy.cc b/chromecast/base/cast_sys_info_dummy.cc index 1b9f917..feee2d31 100644 --- a/chromecast/base/cast_sys_info_dummy.cc +++ b/chromecast/base/cast_sys_info_dummy.cc
@@ -27,13 +27,12 @@ const std::string& default_val) { DCHECK(sys_info_file.is_dict()); - const base::Value* val = - sys_info_file.FindKeyOfType(key, base::Value::Type::STRING); + const std::string* val = sys_info_file.GetDict().FindString(key); if (!val) { LOG(WARNING) << "Json key not found: " << key; return default_val; } - return val->GetString(); + return *val; } } // namespace
diff --git a/chromecast/media/cma/backend/mixer/post_processing_pipeline_parser.cc b/chromecast/media/cma/backend/mixer/post_processing_pipeline_parser.cc index 44d1feb..bf81f6e 100644 --- a/chromecast/media/cma/backend/mixer/post_processing_pipeline_parser.cc +++ b/chromecast/media/cma/backend/mixer/post_processing_pipeline_parser.cc
@@ -33,12 +33,11 @@ base::Value::List& prerender_pipeline, base::Value::List& postrender_pipeline) { bool has_render = false; - for (const base::Value& processor_description_dict : processors_list) { - DCHECK(processor_description_dict.is_dict()); - std::string processor_name; - const base::Value* name_val = processor_description_dict.FindKeyOfType( - kNameKey, base::Value::Type::STRING); - if (name_val && name_val->GetString() == kRenderNameTag) { + for (const base::Value& processor_description_value : processors_list) { + DCHECK(processor_description_value.is_dict()); + const std::string* name = + processor_description_value.GetDict().FindString(kNameKey); + if (name && *name == kRenderNameTag) { has_render = true; break; } @@ -47,9 +46,9 @@ bool is_prerender = has_render; for (const base::Value& processor_description_dict : processors_list) { - const base::Value* name_val = processor_description_dict.FindKeyOfType( - kNameKey, base::Value::Type::STRING); - if (name_val && name_val->GetString() == kRenderNameTag) { + const std::string* name = + processor_description_dict.GetDict().FindString(kNameKey); + if (name && *name == kRenderNameTag) { is_prerender = false; continue; } @@ -172,9 +171,9 @@ StreamPipelineDescriptor PostProcessingPipelineParser::GetPipelineByKey( const std::string& key) { - const base::Value* stream_dict = + const base::Value* stream_value = postprocessor_config_ ? postprocessor_config_->FindPath(key) : nullptr; - if (!postprocessor_config_ || !stream_dict) { + if (!postprocessor_config_ || !stream_value) { LOG(WARNING) << "No post-processor description found for \"" << key << "\" in " << file_path_ << ". Using passthrough."; return StreamPipelineDescriptor(base::Value(base::Value::Type::LIST), @@ -182,24 +181,29 @@ nullptr, absl::nullopt, nullptr); } + const base::Value::Dict& stream_dict = stream_value->GetDict(); const base::Value::List* processors_list = - stream_dict->GetDict().FindList(kProcessorsKey); + stream_dict.FindList(kProcessorsKey); CHECK(processors_list); base::Value::List prerender_pipeline; base::Value::List postrender_pipeline; SplitPipeline(*processors_list, prerender_pipeline, postrender_pipeline); - const base::Value* streams_list = - stream_dict->FindKeyOfType(kStreamsKey, base::Value::Type::LIST); + const base::Value* streams_list = stream_dict.Find(kStreamsKey); + if (streams_list && !streams_list->is_list()) { + streams_list = nullptr; + } - const base::Value* volume_limits = - stream_dict->FindKeyOfType(kVolumeLimitsKey, base::Value::Type::DICT); + const base::Value* volume_limits = stream_dict.Find(kVolumeLimitsKey); + if (volume_limits && !volume_limits->is_dict()) { + volume_limits = nullptr; + } return StreamPipelineDescriptor( base::Value(std::move(prerender_pipeline)), base::Value(std::move(postrender_pipeline)), streams_list, - stream_dict->FindIntKey(kNumInputChannelsKey), volume_limits); + stream_dict.FindInt(kNumInputChannelsKey), volume_limits); } base::FilePath PostProcessingPipelineParser::GetFilePath() const {
diff --git a/chromeos/ash/components/audio/cros_audio_config_impl.cc b/chromeos/ash/components/audio/cros_audio_config_impl.cc index 942edf6..4d03184 100644 --- a/chromeos/ash/components/audio/cros_audio_config_impl.cc +++ b/chromeos/ash/components/audio/cros_audio_config_impl.cc
@@ -18,9 +18,9 @@ // Histogram names. constexpr char kOutputMuteChangeHistogramName[] = - "ChromeOS.Settings.Device.Audio.OutputMuteStateChange"; + "ChromeOS.CrosAudioConfig.OutputMuteStateChange"; constexpr char kInputMuteChangeHistogramName[] = - "ChromeOS.Settings.Device.Audio.InputMuteStateChange"; + "ChromeOS.CrosAudioConfig.InputMuteStateChange"; // Creates an inactive input device with default property configuration. AudioDevice CreateStubInternalMic() {
diff --git a/chromeos/ash/components/audio/cros_audio_config_impl_unittest.cc b/chromeos/ash/components/audio/cros_audio_config_impl_unittest.cc index 5ec24e88..662f6c40 100644 --- a/chromeos/ash/components/audio/cros_audio_config_impl_unittest.cc +++ b/chromeos/ash/components/audio/cros_audio_config_impl_unittest.cc
@@ -43,9 +43,9 @@ // Histogram names. constexpr char kOutputMuteChangeHistogramName[] = - "ChromeOS.Settings.Device.Audio.OutputMuteStateChange"; + "ChromeOS.CrosAudioConfig.OutputMuteStateChange"; constexpr char kInputMuteChangeHistogramName[] = - "ChromeOS.Settings.Device.Audio.InputMuteStateChange"; + "ChromeOS.CrosAudioConfig.InputMuteStateChange"; struct AudioNodeInfo { bool is_input;
diff --git a/chromeos/ash/services/recording/BUILD.gn b/chromeos/ash/services/recording/BUILD.gn index 13a6edda..1fda135 100644 --- a/chromeos/ash/services/recording/BUILD.gn +++ b/chromeos/ash/services/recording/BUILD.gn
@@ -8,8 +8,11 @@ source_set("recording") { sources = [ + "color_quantization.cc", + "color_quantization.h", "gif_encoder.cc", "gif_encoder.h", + "gif_encoding_types.h", "gif_file_writer.cc", "gif_file_writer.h", "lzw_pixel_color_indices_writer.cc",
diff --git a/chromeos/ash/services/recording/DEPS b/chromeos/ash/services/recording/DEPS index 375f8a1a..30aec87 100644 --- a/chromeos/ash/services/recording/DEPS +++ b/chromeos/ash/services/recording/DEPS
@@ -12,6 +12,8 @@ "+services/viz/privileged/mojom/compositing", "+testing/gmock/include/gmock/gmock.h", "+testing/gtest/include/gtest/gtest.h", + "+third_party/skia/include/core/SkBitmap.h", + "+third_party/skia/include/core/SkColor.h", "+ui/gfx", # Abseil is allowed by default, but some features are banned. See
diff --git a/chromeos/ash/services/recording/color_quantization.cc b/chromeos/ash/services/recording/color_quantization.cc new file mode 100644 index 0000000..26475ed --- /dev/null +++ b/chromeos/ash/services/recording/color_quantization.cc
@@ -0,0 +1,103 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromeos/ash/services/recording/color_quantization.h" + +#include <cstdint> + +#include "base/check_op.h" +#include "chromeos/ash/services/recording/gif_encoding_types.h" + +namespace recording { + +namespace { + +// If no color exists in the color table whose squared distance to the current +// color being added is smaller than this value, the new color will be added to +// the table. +constexpr uint32_t kMinSquaredDistanceToAddColor = 75; + +// Calculates and returns the squared value of the Euclidean distance between +// the two given colors. +uint32_t CalculateColorDistanceSquared(const SkColor& color_a, + const SkColor& color_b) { + const uint32_t diff_r = SkColorGetR(color_a) - SkColorGetR(color_b); + const uint32_t diff_g = SkColorGetG(color_a) - SkColorGetG(color_b); + const uint32_t diff_b = SkColorGetB(color_a) - SkColorGetB(color_b); + return diff_r * diff_r + diff_g * diff_g + diff_b * diff_b; +} + +// If `new_color` already exists in `out_palette`, it returns its index +// immediately. Otherwise, it tries to add it to the palette if possible (i.e. +// if there's still room in the palette and there's no other color that is +// considered close enough), and returns the index. If addition is not possible, +// it returns the index of the closest color in the palette. +ColorIndex MaybeAddColorToPalette(const SkColor& new_color, + ColorTable& out_palette) { + int index_of_closest = -1; + uint32_t min_squared_distance = std::numeric_limits<uint32_t>::max(); + const size_t current_size = out_palette.size(); + for (size_t i = 0; i < current_size; ++i) { + const auto& current_color = out_palette[i]; + if (current_color == new_color) { + return i; + } + + const uint32_t squared_distance = + CalculateColorDistanceSquared(new_color, current_color); + if (squared_distance < min_squared_distance) { + min_squared_distance = squared_distance; + index_of_closest = i; + } + } + + if (current_size < kMaxNumberOfColorsInPalette && + min_squared_distance >= kMinSquaredDistanceToAddColor) { + out_palette.push_back(new_color); + return current_size; + } + + DCHECK_NE(index_of_closest, -1); + return index_of_closest; +} + +} // namespace + +// TODO(b/270604745): Implement a better color quantization algorithm. +void BuildColorPaletteAndPixelIndices(const SkBitmap& bitmap, + ColorTable& out_color_palette, + ColorIndices& out_pixel_color_indices) { + out_color_palette.clear(); + out_pixel_color_indices.clear(); + + for (int row = 0; row < bitmap.height(); ++row) { + for (int col = 0; col < bitmap.width(); ++col) { + // We do not care about the alpha values, since our palette contains only + // RGB colors, therefore we make the color as fully opaque before calling + // `MaybeAddColorToPalette()` to make color comparison with the `==` + // operator possible. + const auto color = SkColorSetA(bitmap.getColor(col, row), 0xFF); + const ColorIndex index = MaybeAddColorToPalette(color, out_color_palette); + DCHECK_GE(index, 0); + DCHECK_LT(index, out_color_palette.size()); + out_pixel_color_indices.push_back(index); + } + } + + DCHECK_LE(out_color_palette.size(), kMaxNumberOfColorsInPalette); +} + +uint8_t CalculateColorBitDepth(const ColorTable& color_palette) { + DCHECK_LE(color_palette.size(), kMaxNumberOfColorsInPalette); + + uint8_t bit_depth = 1; + while ((1u << bit_depth) < color_palette.size()) { + ++bit_depth; + } + + DCHECK_LE(bit_depth, kMaxColorBitDepth); + return bit_depth; +} + +} // namespace recording
diff --git a/chromeos/ash/services/recording/color_quantization.h b/chromeos/ash/services/recording/color_quantization.h new file mode 100644 index 0000000..9529e9f4 --- /dev/null +++ b/chromeos/ash/services/recording/color_quantization.h
@@ -0,0 +1,34 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMEOS_ASH_SERVICES_RECORDING_COLOR_QUANTIZATION_H_ +#define CHROMEOS_ASH_SERVICES_RECORDING_COLOR_QUANTIZATION_H_ + +#include "chromeos/ash/services/recording/gif_encoding_types.h" +#include "third_party/skia/include/core/SkBitmap.h" + +namespace recording { + +// GIF images can have a maximum number of 256 colors in their color tables. +// This means that the minimum number of bits needed to represent this count is +// 8, which is the max bit depth value. +constexpr size_t kMaxNumberOfColorsInPalette = 256; +constexpr uint8_t kMaxColorBitDepth = 8; + +// Performs color quantization on the given `bitmap` and fills +// `out_color_palette` with the most important 256 colors in the image, and also +// fills `out_pixel_color_indices` with the indices of the chosen colors from +// `out_color_palette` for all the pixels in `bitmap`. +void BuildColorPaletteAndPixelIndices(const SkBitmap& bitmap, + ColorTable& out_color_palette, + ColorIndices& out_pixel_color_indices); + +// Calculates and returns the color bit depth based on the size of the given +// `color_palette`. The color bit depth is the least number of bits needed to be +// able to represent the size of the palette as a binary number. +uint8_t CalculateColorBitDepth(const ColorTable& color_palette); + +} // namespace recording + +#endif // CHROMEOS_ASH_SERVICES_RECORDING_COLOR_QUANTIZATION_H_
diff --git a/chromeos/ash/services/recording/gif_encoder.cc b/chromeos/ash/services/recording/gif_encoder.cc index d67de4bd..72a4286 100644 --- a/chromeos/ash/services/recording/gif_encoder.cc +++ b/chromeos/ash/services/recording/gif_encoder.cc
@@ -4,14 +4,187 @@ #include "chromeos/ash/services/recording/gif_encoder.h" +#include <cmath> + #include "base/notreached.h" +#include "base/time/time.h" +#include "chromeos/ash/services/recording/color_quantization.h" #include "chromeos/ash/services/recording/lzw_pixel_color_indices_writer.h" #include "chromeos/ash/services/recording/recording_encoder.h" #include "media/base/audio_bus.h" #include "media/base/video_frame.h" +#include "third_party/skia/include/core/SkColor.h" namespace recording { +namespace { + +// The value of the first byte of any extension block, such as the Netscape +// Extension, and the Graphic Control Extension. +constexpr uint8_t kExtensionIntroducer = 0x21; + +// ----------------------------------------------------------------------------- +// GlobalColorTableFields: + +// The bit fields packed in a single byte, which define the configuration of +// the Global Color Table as part of the Logical Screen Descriptor block of the +// GIF file. +union GlobalColorTableFields { + struct { + // The least significant 3 bits, which define the number of colors in the + // table (2 ^ (global_color_table_size + 1) colors). The value + // `global_color_table_size + 1` is known as the bit depth. For example, if + // `global_color_table_size` is 7 (i.e. 0b111), this means there are 2 ^ 8 + // colors in the table, where 8 is the color bit depth. + // This value is meaningful only if `global_color_table_flag` is set to 1. + uint8_t global_color_table_size : 3; + + // This bit indicates whether the global color table is sorted (0b1) or not + // (0b0). + // This value is meaningful only if `global_color_table_flag` is set to 1. + uint8_t sort_flag : 1; + + // For our purposes, this value is always set to 7 (0b111). Its explanation + // is copied as is from the GIF specs below: + // "Number of bits per primary color available to the original image, minus + // 1. This value represents the size of the entire palette from which the + // colors in the graphic were selected, not the number of colors actually + // used in the graphic. It indicates the richness of the original palette". + uint8_t color_resolution : 3; + + // This is the most significant bit, and it indicates whether a global color + // table will immediately follow the Logical Screen Descriptor block (0b1) + // or not (0b0). + uint8_t global_color_table_flag : 1; + }; + + // The packed value of the above bit fields as an 8-bit byte. + uint8_t value; +}; + +static_assert(sizeof(GlobalColorTableFields) == 1, + "Unexpected size of GlobalColorTableFields"); + +// ----------------------------------------------------------------------------- +// GraphicControlExtensionFields: + +// The bit fields packed in a single byte, which define some settings that the +// decoder can use while decoding and rendering the GIF file. +union GraphicControlExtensionFields { + struct { + // Indicates whether a transparency color index is given as part of the + // Graphic Control Extension block. + uint8_t transparent_color_flag : 1; + + // Indicates whether or not user input is expected before continuing. If the + // flag is set, processing will continue when user input is entered. + uint8_t user_input_flag : 1; + + // Indicates the way in which the decoded image frame is to be treated after + // being displayed. + // 0b000: No disposal specified. The decoder is not required to take any + // action. + // 0b001: Do not dispose. The image is to be left in place. + // 0b010: The area used by the image must be restored to the background + // color. + // 0b011: Restore to previous. The decoder is required to restore the area + // overwritten by the image with what was there prior to rendering + // it. + // 0b100 - 0b111: Not defined. + uint8_t disposal_method : 3; + + // Reserved for future use. + uint8_t reserved : 3; + }; + + // The packed value of the above bit fields as an 8-bit byte. + uint8_t value; +}; + +static_assert(sizeof(GraphicControlExtensionFields) == 1, + "Unexpected size of GraphicControlExtensionFields"); + +// ----------------------------------------------------------------------------- +// ImageDescriptorFields: + +// The bit fields packed in a single byte, which define the configuration of +// the Local Color Table as part of the Image Descriptor block of the GIF file. +union ImageDescriptorFields { + struct { + // Similar to `GlobalColorTableFields::global_color_table_size`. + uint8_t local_color_table_size : 3; + + // Reserved for future use. + uint8_t reserved : 2; + + // Similar to `GlobalColorTableFields::sort_flag`. + uint8_t sort_flag : 1; + + // This bit is always set to 0 for our purposes. + uint8_t interlace_flag : 1; + + // Indicates whether or not a Local Color Table will immediately follow the + // Image Descriptor block in the GIF file. + uint8_t local_color_table_flag : 1; + }; + + // The packed value of the above bit fields as an 8-bit byte. + uint8_t value; +}; + +static_assert(sizeof(ImageDescriptorFields) == 1, + "Unexpected size of ImageDescriptorFields"); + +// ----------------------------------------------------------------------------- +// GifEncoderCapabilities: + +// Implements the capabilities for GIF encoding. +class GifEncoderCapabilities : public RecordingEncoder::Capabilities { + public: + GifEncoderCapabilities() = default; + GifEncoderCapabilities(const GifEncoderCapabilities&) = delete; + GifEncoderCapabilities& operator=(const GifEncoderCapabilities&) = delete; + ~GifEncoderCapabilities() override = default; + + // RecordingEncoder::Capabilities: + media::VideoPixelFormat GetSupportedPixelFormat() const override { + return media::PIXEL_FORMAT_ARGB; + } + + bool SupportsVideoFrameSizeChanges() const override { + // The GIF file specifies the dimensions of the canvas only once in + // `InitializeVideoEncoder()` when the Logical Screen Descriptor is written. + // As a result, we cannot change the dimensions of the image after the fact + // in the middle of recording. + // TODO(afakhry): Figure out if we can allow this if the dimensions change + // to something smaller than the initial size. + return false; + } +}; + +// ----------------------------------------------------------------------------- + +// Wraps the given `video_frame` pixels in a bitmap and returns it. Note that +// this does not copy the pixels bytes from `video_frame` to the returned +// bitmap, and hence the bitmap is safe to access as long as the `video_frame` +// is alive. +SkBitmap WrapVideoFrameInBitmap(const media::VideoFrame& video_frame) { + const gfx::Size visible_size = video_frame.visible_rect().size(); + const SkImageInfo image_info = SkImageInfo::MakeN32( + visible_size.width(), visible_size.height(), kPremul_SkAlphaType, + video_frame.ColorSpace().ToSkColorSpace()); + + SkBitmap bitmap; + const uint8_t* pixels = + video_frame.visible_data(media::VideoFrame::kARGBPlane); + bitmap.installPixels( + SkPixmap(image_info, pixels, + video_frame.row_bytes(media::VideoFrame::kARGBPlane))); + return bitmap; +} + +} // namespace + // static base::SequenceBound<GifEncoder> GifEncoder::Create( scoped_refptr<base::SequencedTaskRunner> blocking_task_runner, @@ -25,6 +198,12 @@ std::move(on_failure_callback)); } +// static +std::unique_ptr<RecordingEncoder::Capabilities> +GifEncoder::CreateCapabilities() { + return std::make_unique<GifEncoderCapabilities>(); +} + GifEncoder::GifEncoder( PassKey, const media::VideoEncoder::Options& video_encoder_options, @@ -42,9 +221,47 @@ GifEncoder::~GifEncoder() = default; void GifEncoder::InitializeVideoEncoder( - const media::VideoEncoder::Options& video_encoder_options) {} + const media::VideoEncoder::Options& video_encoder_options) { + // There can be a maximum of 256 colors in our color palette, and + // `width * height` pixels. + color_palette_.reserve(kMaxNumberOfColorsInPalette); + pixel_color_indices_.reserve(video_encoder_options.frame_size.GetArea()); -void GifEncoder::EncodeVideo(scoped_refptr<media::VideoFrame> frame) {} + gif_file_writer_.WriteString("GIF89a"); // The GIF header. + WriteLogicalScreenDescriptor(video_encoder_options.frame_size); + WriteNetscapeExtension(); +} + +void GifEncoder::EncodeVideo(scoped_refptr<media::VideoFrame> frame) { + // This bitmap is backed up by the same memory containing the bytes of the + // frame. `SkBitmap` makes it more convenient to extract the colors from the + // video frame. Once we extract the color palette and pixel color indices from + // the `bitmap`, we no longer need it, nor need the video `frame`. + const SkBitmap bitmap = WrapVideoFrameInBitmap(*frame); + BuildColorPaletteAndPixelIndices(bitmap, color_palette_, + pixel_color_indices_); + + const gfx::Size visible_size = frame->visible_rect().size(); + DCHECK_EQ(pixel_color_indices_.size(), + static_cast<size_t>(visible_size.GetArea())); + const auto frame_time = + frame->metadata().reference_time.value_or(base::TimeTicks::Now()); + + // We're done with the frame, release it immediately before we spend cycles + // doing the encoding and writing to the file. This returns it back to the + // video frame buffer pool in Viz, which has a maximum number of in-flight + // frames. Releasing the frame as soon as we're done with it helps to avoid + // reaching that limit often. + frame.reset(); + + WriteGraphicControlExtension(frame_time); + const auto color_bit_depth = CalculateColorBitDepth(color_palette_); + WriteImageDescriptor(visible_size, color_bit_depth); + WriteColorPalette(color_bit_depth); + lzw_encoder_.EncodeAndWrite(pixel_color_indices_, color_bit_depth); + + last_frame_time_ = frame_time; +} void GifEncoder::EncodeAudio(std::unique_ptr<media::AudioBus> audio_bus, base::TimeTicks capture_time) { @@ -52,7 +269,150 @@ } void GifEncoder::FlushAndFinalize(base::OnceClosure on_done) { + // Write the character ';' (or `0x3B` in hex), which is the GIF trailer byte, + // and flush the contents of the file. + gif_file_writer_.WriteByte(0x3B); + gif_file_writer_.FlushFile(); + std::move(on_done).Run(); } +void GifEncoder::WriteLogicalScreenDescriptor(const gfx::Size& frame_size) { + gif_file_writer_.WriteShort(frame_size.width()); + gif_file_writer_.WriteShort(frame_size.height()); + + // We will not use a global color table, so we will set its flag to 0. The + // palette will be written once for every frame in the local color table after + // the image descriptor. + gif_file_writer_.WriteByte(GlobalColorTableFields{ + .global_color_table_size = 0b000, + .sort_flag = 0b0, + .color_resolution = 0b111, + .global_color_table_flag = 0b0, + } + .value); + + gif_file_writer_.WriteByte(0x00); // Background color index. + gif_file_writer_.WriteByte(0x00); // Pixel aspect ratio. +} + +void GifEncoder::WriteNetscapeExtension() { + gif_file_writer_.WriteByte(kExtensionIntroducer); + // Extension Label. Always set to 0xFF for application extensions, which the + // Netscape extension is an example of. + gif_file_writer_.WriteByte(0xFF); + // The size of the following block that contains the application identifier, + // and the authentication code ("NETSCAPE2.0" in our case; i.e. 11 bytes). + gif_file_writer_.WriteByte(11); + gif_file_writer_.WriteString("NETSCAPE2.0"); + + // Next are the application data sub-blocks. Each sub-block begins with a byte + // that indicates its size, followed by a byte for its ID, followed by the + // payload of the sub-block itself, and finally a block terminator byte which + // is always `0x00`. + // For the Netscape extension, we have only 1 sub-block that defines the + // config for the looping of the animated GIF image. + // The sub-block is 3 bytes (excluding the block terminator). + gif_file_writer_.WriteByte(3); + // The sub block ID is 1. + gif_file_writer_.WriteByte(1); + // GIF animation loop config as a 16-bit unsigned integer. The value `0` means + // keep looping forever. + gif_file_writer_.WriteShort(0); + // The block terminator. + gif_file_writer_.WriteByte(0); +} + +void GifEncoder::WriteGraphicControlExtension( + base::TimeTicks current_frame_time) { + gif_file_writer_.WriteByte(kExtensionIntroducer); + // The Extension Label. Always set to 0xF9 for Graphic Control Extension. + gif_file_writer_.WriteByte(0xF9); + // The number of bytes that follow (excluding the block terminator). + gif_file_writer_.WriteByte(4); + + // Write the packed fields, such that we specify that we won't provide a + // transparent color index, and user input is not expected to proceed to the + // next frame. + gif_file_writer_.WriteByte(GraphicControlExtensionFields{ + .transparent_color_flag = 0b0, + .user_input_flag = 0b0, + .disposal_method = 0b000, + .reserved = 0b000, + } + .value); + + // Write the delay after which this frame that is being encoded should be + // rendered. The delay is specified in units of 1/100 (hundredth) of a second. + if (last_frame_time_.is_null()) { + // If this is the first ever frame, then there should be no delay. + gif_file_writer_.WriteShort(0); + } else { + const uint16_t delay = std::floor( + (current_frame_time - last_frame_time_).InSecondsF() * 100.f); + gif_file_writer_.WriteShort(delay); + } + + // We're not using a transparent color (see above), so the value we write here + // doesn't matter and will be ignored. + gif_file_writer_.WriteByte(0); + + // The block terminator. + gif_file_writer_.WriteByte(0); +} + +void GifEncoder::WriteImageDescriptor(const gfx::Size& frame_size, + uint8_t color_bit_depth) { + DCHECK_LE(color_bit_depth, kMaxColorBitDepth); + + // The Image Separator byte. Always 0x2C. + gif_file_writer_.WriteByte(0x2C); + // The "left" (or X coordinate) of the frame within the canvas bounds (which + // was defined earlier in the Logical Screen Descriptor when the encoder was + // initialized). + gif_file_writer_.WriteShort(0); + // The "top" (or Y coordinate) of the frame. + gif_file_writer_.WriteShort(0); + // The frame size. + gif_file_writer_.WriteShort(frame_size.width()); + gif_file_writer_.WriteShort(frame_size.height()); + + // Write the Image Descriptor bitfields such that we specify that we're using + // a non-sorted, non-interlaced local color table of size 2 ^ color_bit_depth + // colors. + gif_file_writer_.WriteByte(ImageDescriptorFields{ + .local_color_table_size = static_cast<uint8_t>((color_bit_depth - 1)), + .reserved = 0b00, + .sort_flag = 0b0, + .interlace_flag = 0b0, + .local_color_table_flag = 0b1, + } + .value); +} + +void GifEncoder::WriteColorPalette(uint8_t color_bit_depth) { + DCHECK_LE(color_bit_depth, kMaxColorBitDepth); + + const size_t table_size = 1u << color_bit_depth; + const size_t end = std::min(table_size, color_palette_.size()); + for (size_t i = 0; i < end; ++i) { + const auto& color = color_palette_[i]; + gif_file_writer_.WriteByte(SkColorGetR(color)); + gif_file_writer_.WriteByte(SkColorGetG(color)); + gif_file_writer_.WriteByte(SkColorGetB(color)); + } + + // The color table size that we write to the GIF file has to be a multiple of + // 2 (2 ^ color_bit_depth). See + // `ImageDescriptorFields::local_color_table_size`. + // However, we may have less colors in our palette that we extracted from the + // current video frame than a value that is a multiple of 2. We fill the + // remaining colors in the table as zeros. + for (size_t i = end; i < table_size; ++i) { + gif_file_writer_.WriteByte(0); + gif_file_writer_.WriteByte(0); + gif_file_writer_.WriteByte(0); + } +} + } // namespace recording
diff --git a/chromeos/ash/services/recording/gif_encoder.h b/chromeos/ash/services/recording/gif_encoder.h index 01412c7..690b551 100644 --- a/chromeos/ash/services/recording/gif_encoder.h +++ b/chromeos/ash/services/recording/gif_encoder.h
@@ -5,8 +5,12 @@ #ifndef CHROMEOS_ASH_SERVICES_RECORDING_GIF_ENCODER_H_ #define CHROMEOS_ASH_SERVICES_RECORDING_GIF_ENCODER_H_ +#include <vector> + #include "base/threading/sequence_bound.h" +#include "base/time/time.h" #include "base/types/pass_key.h" +#include "chromeos/ash/services/recording/gif_encoding_types.h" #include "chromeos/ash/services/recording/gif_file_writer.h" #include "chromeos/ash/services/recording/lzw_pixel_color_indices_writer.h" #include "chromeos/ash/services/recording/recording_encoder.h" @@ -48,6 +52,10 @@ const base::FilePath& gif_file_path, OnFailureCallback on_failure_callback); + // Creates and returns an object that specifies the capabilities of this + // encoder. + static std::unique_ptr<Capabilities> CreateCapabilities(); + GifEncoder( PassKey, const media::VideoEncoder::Options& video_encoder_options, @@ -67,6 +75,54 @@ void FlushAndFinalize(base::OnceClosure on_done) override; private: + // Writes the Logical Screen Descriptor block to the GIF file. This block + // contains info about the dimensions of the canvas within which the images of + // the frames will be rendered. It also contains the configuration of the + // Global Color Table. + // This block is written only once in the entire GIF file. + void WriteLogicalScreenDescriptor(const gfx::Size& frame_size); + + // Writes the Netscape Application Extension block to the GIF file. This block + // allows us to embed information about looping of the frames in the output + // animated GIF. + // This block is written only once in the entire GIF file. + void WriteNetscapeExtension(); + + // Writes the Graphic Control Extension block to the GIF file. This block + // contains information about the delay after which the video frame should be + // rendered. Hence, it uses the given `current_frame_time` to calculate this + // delay. + // This block repeats once per every received video frame. + void WriteGraphicControlExtension(base::TimeTicks current_frame_time); + + // Writes the Image Descriptor block to the GIF file. It describes the bounds + // of the frame within the total bounds of the canvas (which was defined + // earlier in the Logical Screen Descriptor block). It also specifies whether + // the frame has its own Local Color Table. + // This block repeats once per every received video frame. + void WriteImageDescriptor(const gfx::Size& frame_size, + uint8_t color_bit_depth); + + // Writes the `color_palette_` which has the given `color_bit_depth` to the + // GIF file. This function can be uses to write both the Global and Local + // color tables. However, we only write Local Color Tables in this + // implementation. + void WriteColorPalette(uint8_t color_bit_depth); + + // The presentation time of the most recent video frame prior to the one being + // encoded at the moment. + base::TimeTicks last_frame_time_; + + // The list of colors (up to 256 colors) that will be written to the GIF file + // as the color table. These colors are extracted from each received frame + // using some color quantization algorithm of choice, which tries to pick the + // most important colors that represent the contents of the video frame. + ColorTable color_palette_; + + // The color of each pixel in the received video frame is represented as an + // index into `color_palette_` after color quantization is complete. + ColorIndices pixel_color_indices_; + // Abstracts writing bytes to the GIF file, and takes care of handling IO // errors and remaining disk space / DriveFS quota issues. GifFileWriter gif_file_writer_;
diff --git a/chromeos/ash/services/recording/gif_encoding_types.h b/chromeos/ash/services/recording/gif_encoding_types.h new file mode 100644 index 0000000..86a6d60 --- /dev/null +++ b/chromeos/ash/services/recording/gif_encoding_types.h
@@ -0,0 +1,30 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMEOS_ASH_SERVICES_RECORDING_GIF_ENCODING_TYPES_H_ +#define CHROMEOS_ASH_SERVICES_RECORDING_GIF_ENCODING_TYPES_H_ + +#include <cstdint> +#include <vector> + +#include "third_party/skia/include/core/SkColor.h" + +namespace recording { + +// The GIF specs specify a maximum of 12 bits per LZW compression code, so a +// 16-bit unsigned integer is perfect for this type. +using LzwCode = uint16_t; + +// We have a maximum of 256 colors in our color palette, so an 8-bit unsigned +// integer is enough to represent indices to these colors. +using ColorIndex = uint8_t; +using ColorIndices = std::vector<ColorIndex>; + +// Defines a type for a color palette table which will eventually be written to +// the GIF file. +using ColorTable = std::vector<SkColor>; + +} // namespace recording + +#endif // CHROMEOS_ASH_SERVICES_RECORDING_GIF_ENCODING_TYPES_H_
diff --git a/chromeos/ash/services/recording/gif_file_writer.cc b/chromeos/ash/services/recording/gif_file_writer.cc index d28ba48..7d92a1a 100644 --- a/chromeos/ash/services/recording/gif_file_writer.cc +++ b/chromeos/ash/services/recording/gif_file_writer.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "chromeos/ash/services/recording/gif_file_writer.h" + #include "base/containers/span.h" namespace recording { @@ -28,6 +29,20 @@ WriteBytesAndCheck(base::make_span(buffer, buffer_size)); } +void GifFileWriter::WriteString(base::StringPiece string) { + WriteBytesAndCheck(base::make_span( + reinterpret_cast<const uint8_t*>(string.data()), string.size())); +} + +void GifFileWriter::WriteShort(uint16_t value) { + WriteByte(value & 0xFF); + WriteByte(((value >> 8) & 0xFF)); +} + +void GifFileWriter::FlushFile() { + gif_file_.Flush(); +} + void GifFileWriter::WriteBytesAndCheck(base::span<const uint8_t> data) { if (!gif_file_.WriteAtCurrentPosAndCheck(data)) { file_io_helper_.delegate()->NotifyFailure(mojom::RecordingStatus::kIoError);
diff --git a/chromeos/ash/services/recording/gif_file_writer.h b/chromeos/ash/services/recording/gif_file_writer.h index 6345c9a..6d0fb06 100644 --- a/chromeos/ash/services/recording/gif_file_writer.h +++ b/chromeos/ash/services/recording/gif_file_writer.h
@@ -8,6 +8,7 @@ #include <cstdint> #include "base/files/file.h" +#include "base/strings/string_piece_forward.h" #include "chromeos/ash/services/recording/recording_file_io_helper.h" namespace recording { @@ -33,6 +34,16 @@ // the `gif_file_`. void WriteBuffer(const uint8_t* const buffer, size_t buffer_size); + // Writes the given `string` to the `gif_file_`. + void WriteString(base::StringPiece string); + + // Writes the given 16-bit `value` to the `gif_file_` in little endian format + // such that the least significant bit gets written first. + void WriteShort(uint16_t value); + + // Flushes the contents of the file to the underlying storage. + void FlushFile(); + private: // Writes the given `data` to the `gif_file_` and check for IO errors or disk // space / DriveFS quota issues.
diff --git a/chromeos/ash/services/recording/lzw_pixel_color_indices_writer.h b/chromeos/ash/services/recording/lzw_pixel_color_indices_writer.h index b7094712..addfe192 100644 --- a/chromeos/ash/services/recording/lzw_pixel_color_indices_writer.h +++ b/chromeos/ash/services/recording/lzw_pixel_color_indices_writer.h
@@ -9,20 +9,12 @@ #include <vector> #include "base/containers/flat_map.h" +#include "chromeos/ash/services/recording/gif_encoding_types.h" namespace recording { class GifFileWriter; -// The specs specify a maximum of 12 bits per LZW compression code, so a 16-bit -// unsigned integer is perfect for this type. -using LzwCode = uint16_t; - -// We have a maximum of 256 colors in our color palette, so an 8-bit unsigned -// integer is enough to represent indices to these colors. -using ColorIndex = uint8_t; -using ColorIndices = std::vector<ColorIndex>; - // Background: After color quantization is performed on the video frame, we end // up with: // 1- A color table (or a color palette) that contains a list of colors (up to
diff --git a/chromeos/ash/services/recording/public/mojom/recording_service.mojom b/chromeos/ash/services/recording/public/mojom/recording_service.mojom index e0b02a4..603573e 100644 --- a/chromeos/ash/services/recording/public/mojom/recording_service.mojom +++ b/chromeos/ash/services/recording/public/mojom/recording_service.mojom
@@ -39,6 +39,9 @@ kLowDiskSpace, // Ended due to reaching a critically low DriveFS quota. kLowDriveFsQuota, + // Ended due to the video encoder not supporting mid-recording + // re-configuation. + kVideoEncoderReconfigurationFailure, }; // Defines the interface for retrieving the remaining amount of DriveFS free
diff --git a/chromeos/ash/services/recording/recording_encoder.h b/chromeos/ash/services/recording/recording_encoder.h index f311459..700742f5 100644 --- a/chromeos/ash/services/recording/recording_encoder.h +++ b/chromeos/ash/services/recording/recording_encoder.h
@@ -13,6 +13,7 @@ #include "chromeos/ash/services/recording/recording_file_io_helper.h" #include "media/base/encoder_status.h" #include "media/base/video_encoder.h" +#include "media/base/video_types.h" namespace media { class AudioBus; @@ -35,6 +36,27 @@ // underlying actual encoders. class RecordingEncoder : public RecordingFileIoHelper::Delegate { public: + // Defines an interface for the actual encoders types to provide the + // capabilities that they support. + class Capabilities { + public: + Capabilities() = default; + Capabilities(const Capabilities&) = delete; + Capabilities& operator=(const Capabilities&) = delete; + virtual ~Capabilities() = default; + + // Returns the pixel format that the encoder supports, which should be used + // to initialize the frame sink video capturer in the GPU. Video frames + // received from the capturer should be in this pixel format. + virtual media::VideoPixelFormat GetSupportedPixelFormat() const = 0; + + // Returns whether the encoder supports size changes of the video frames + // during recording (e.g. due to screen rotation, DSF changes, ... etc.). + // Size changes during recording require a reconfiguration of the video + // encoder. + virtual bool SupportsVideoFrameSizeChanges() const = 0; + }; + explicit RecordingEncoder(OnFailureCallback on_failure_callback); RecordingEncoder(const RecordingEncoder&) = delete; RecordingEncoder& operator=(const RecordingEncoder&) = delete;
diff --git a/chromeos/ash/services/recording/recording_service.cc b/chromeos/ash/services/recording/recording_service.cc index 1cb73ef2..5b9f358 100644 --- a/chromeos/ash/services/recording/recording_service.cc +++ b/chromeos/ash/services/recording/recording_service.cc
@@ -9,12 +9,14 @@ #include <cstdlib> #include "base/check.h" +#include "base/files/file_path.h" #include "base/location.h" #include "base/task/single_thread_task_runner.h" #include "base/task/task_traits.h" #include "base/task/thread_pool.h" #include "base/time/time.h" #include "chromeos/ash/services/recording/gif_encoder.h" +#include "chromeos/ash/services/recording/recording_encoder.h" #include "chromeos/ash/services/recording/recording_service_constants.h" #include "chromeos/ash/services/recording/video_capture_params.h" #include "chromeos/ash/services/recording/webm_encoder_muxer.h" @@ -128,6 +130,15 @@ std::exit(EXIT_FAILURE); } +// Creates the appropriate encoder capabilities based to the type of the given +// `output_file_path`. +std::unique_ptr<RecordingEncoder::Capabilities> CreateEncoderCapabilities( + const base::FilePath& output_file_path) { + return output_file_path.MatchesExtension(".gif") + ? GifEncoder::CreateCapabilities() + : WebmEncoderMuxer::CreateCapabilities(); +} + // Creates and returns the appropriate encoder based on the type of the given // `output_file_path`. base::SequenceBound<RecordingEncoder> CreateEncoder( @@ -475,6 +486,7 @@ current_video_capture_params_ = std::move(capture_params); const bool should_record_audio = audio_stream_factory.is_valid(); + encoder_capabilities_ = CreateEncoderCapabilities(output_file_path); encoder_muxer_ = CreateEncoder( encoding_task_runner_, CreateVideoEncoderOptions(current_video_capture_params_->GetVideoSize()), @@ -499,6 +511,13 @@ void RecordingService::ReconfigureVideoEncoder() { DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_); DCHECK(current_video_capture_params_); + DCHECK(encoder_capabilities_); + + if (!encoder_capabilities_->SupportsVideoFrameSizeChanges()) { + OnEncodingFailure( + mojom::RecordingStatus::kVideoEncoderReconfigurationFailure); + return; + } ++number_of_video_encoder_reconfigures_; encoder_muxer_.AsyncCall(&RecordingEncoder::InitializeVideoEncoder) @@ -512,6 +531,7 @@ refresh_timer_.Stop(); current_video_capture_params_.reset(); + encoder_capabilities_.reset(); video_capturer_remote_.reset(); consumer_receiver_.reset(); @@ -524,6 +544,7 @@ mojo::PendingRemote<viz::mojom::FrameSinkVideoCapturer> video_capturer) { DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_); DCHECK(current_video_capture_params_); + DCHECK(encoder_capabilities_); video_capturer_remote_.reset(); video_capturer_remote_.Bind(std::move(video_capturer)); @@ -532,7 +553,7 @@ video_capturer_remote_.set_disconnect_handler(base::BindOnce( &RecordingService::OnVideoCapturerDisconnected, base::Unretained(this))); current_video_capture_params_->InitializeVideoCapturer( - video_capturer_remote_); + video_capturer_remote_, encoder_capabilities_->GetSupportedPixelFormat()); video_capturer_remote_->Start(consumer_receiver_.BindNewPipeAndPassRemote(), viz::mojom::BufferFormatPreference::kDefault);
diff --git a/chromeos/ash/services/recording/recording_service.h b/chromeos/ash/services/recording/recording_service.h index 258b179a..b645371 100644 --- a/chromeos/ash/services/recording/recording_service.h +++ b/chromeos/ash/services/recording/recording_service.h
@@ -259,6 +259,11 @@ scoped_refptr<media::AudioCapturerSource> audio_capturer_ GUARDED_BY_CONTEXT(main_thread_checker_); + // Abstracts querying the supported capabilities of the currently used encoder + // type. + std::unique_ptr<RecordingEncoder::Capabilities> encoder_capabilities_ + GUARDED_BY_CONTEXT(main_thread_checker_); + // Performs all encoding and muxing operations asynchronously on the // |encoding_task_runner_|. However, the |encoder_muxer_| object itself is // constructed, used, and destroyed on the main thread sequence.
diff --git a/chromeos/ash/services/recording/video_capture_params.cc b/chromeos/ash/services/recording/video_capture_params.cc index 3eeb0e05..da0b5841 100644 --- a/chromeos/ash/services/recording/video_capture_params.cc +++ b/chromeos/ash/services/recording/video_capture_params.cc
@@ -281,7 +281,8 @@ } void VideoCaptureParams::InitializeVideoCapturer( - mojo::Remote<viz::mojom::FrameSinkVideoCapturer>& capturer) const { + mojo::Remote<viz::mojom::FrameSinkVideoCapturer>& capturer, + media::VideoPixelFormat supported_pixel_format) const { DCHECK(capturer); capturer->SetMinCapturePeriod(kMinCapturePeriod); @@ -290,7 +291,7 @@ capturer->SetAutoThrottlingEnabled(false); // TODO(afakhry): Discuss with //media/ team the implications of color space // conversions. - capturer->SetFormat(media::PIXEL_FORMAT_I420); + capturer->SetFormat(supported_pixel_format); capturer->ChangeTarget( viz::VideoCaptureTarget(frame_sink_id_, subtree_capture_id_), /*crop_version=*/0);
diff --git a/chromeos/ash/services/recording/video_capture_params.h b/chromeos/ash/services/recording/video_capture_params.h index 50c421c..29e139c 100644 --- a/chromeos/ash/services/recording/video_capture_params.h +++ b/chromeos/ash/services/recording/video_capture_params.h
@@ -9,8 +9,8 @@ #include "components/viz/common/surfaces/frame_sink_id.h" #include "components/viz/common/surfaces/subtree_capture_id.h" +#include "media/base/video_types.h" #include "mojo/public/cpp/bindings/remote.h" -#include "mojo/public/cpp/bindings/struct_forward.h" #include "services/viz/privileged/mojom/compositing/frame_sink_video_capture.mojom-forward.h" #include "ui/gfx/geometry/size.h" @@ -78,10 +78,12 @@ return current_frame_sink_size_pixels_; } - // Initializes the given |capturer| (passed by ref) according to the capture - // parameters. The given |capturer| must be bound before calling this. + // Initializes the given `capturer` (passed by ref) according to the capture + // parameters. The given `capturer` must be bound before calling this. + // The given `supported_pixel_format` will be used to initialize `capturer`. void InitializeVideoCapturer( - mojo::Remote<viz::mojom::FrameSinkVideoCapturer>& capturer) const; + mojo::Remote<viz::mojom::FrameSinkVideoCapturer>& capturer, + media::VideoPixelFormat supported_pixel_format) const; // Returns the bounds to which a video frame, whose // |original_frame_visible_rect_pixels| is given, should be cropped. If no
diff --git a/chromeos/ash/services/recording/webm_encoder_muxer.cc b/chromeos/ash/services/recording/webm_encoder_muxer.cc index eecf72b..06c504b 100644 --- a/chromeos/ash/services/recording/webm_encoder_muxer.cc +++ b/chromeos/ash/services/recording/webm_encoder_muxer.cc
@@ -16,6 +16,7 @@ #include "media/base/audio_codecs.h" #include "media/base/video_codecs.h" #include "media/base/video_frame.h" +#include "media/base/video_types.h" #include "media/muxers/file_webm_muxer_delegate.h" #include "media/muxers/muxer.h" @@ -40,6 +41,25 @@ constexpr size_t kMaxDroppedFrames = 4 * kMaxFrameRate; // ----------------------------------------------------------------------------- +// WebmEncoderCapabilities: + +// Implements the capabilities for WebM encoding. +class WebmEncoderCapabilities : public RecordingEncoder::Capabilities { + public: + WebmEncoderCapabilities() = default; + WebmEncoderCapabilities(const WebmEncoderCapabilities&) = delete; + WebmEncoderCapabilities& operator=(const WebmEncoderCapabilities&) = delete; + ~WebmEncoderCapabilities() override = default; + + // RecordingEncoder::Capabilities: + media::VideoPixelFormat GetSupportedPixelFormat() const override { + return media::PIXEL_FORMAT_I420; + } + + bool SupportsVideoFrameSizeChanges() const override { return true; } +}; + +// ----------------------------------------------------------------------------- // RecordingMuxerDelegate: // Defines a delegate for the WebmMuxer which extends the capability of @@ -114,6 +134,12 @@ std::move(on_failure_callback)); } +// static +std::unique_ptr<RecordingEncoder::Capabilities> +WebmEncoderMuxer::CreateCapabilities() { + return std::make_unique<WebmEncoderCapabilities>(); +} + WebmEncoderMuxer::WebmEncoderMuxer( PassKey, const media::VideoEncoder::Options& video_encoder_options,
diff --git a/chromeos/ash/services/recording/webm_encoder_muxer.h b/chromeos/ash/services/recording/webm_encoder_muxer.h index e999855..26b048d 100644 --- a/chromeos/ash/services/recording/webm_encoder_muxer.h +++ b/chromeos/ash/services/recording/webm_encoder_muxer.h
@@ -75,6 +75,10 @@ const base::FilePath& webm_file_path, OnFailureCallback on_failure_callback); + // Creates and returns an object that specifies the capabilities of this + // encoder. + static std::unique_ptr<Capabilities> CreateCapabilities(); + WebmEncoderMuxer( PassKey, const media::VideoEncoder::Options& video_encoder_options,
diff --git a/chromeos/components/quick_answers/result_loader.cc b/chromeos/components/quick_answers/result_loader.cc index 95f9c3b..1168fa0e 100644 --- a/chromeos/components/quick_answers/result_loader.cc +++ b/chromeos/components/quick_answers/result_loader.cc
@@ -19,7 +19,6 @@ using network::ResourceRequest; using network::SharedURLLoaderFactory; -// TODO(llin): Update the policy detail after finalizing on the consent check. constexpr net::NetworkTrafficAnnotationTag kNetworkTrafficAnnotationTag = net::DefineNetworkTrafficAnnotation("quick_answers_loader", R"( semantics: { @@ -30,9 +29,11 @@ "or unit conversion." trigger: "Right click to trigger context menu." - data: "Currently selected text, device language and " - "source language of the selected text " - "is sent to Google API only for translation." + data: "Currently selected text is sent to Google API for " + "generating answers. Source language of the selected text " + "is sent to Google API only for translation and dictionary " + "definition. Device language is sent to Google API " + "only for translation." destination: GOOGLE_OWNED_SERVICE } policy: { @@ -47,7 +48,13 @@ QuickAnswersEnabled: false } QuickAnswersTranslationEnabled { - QuickAnswersTranslationEnabled: true + QuickAnswersTranslationEnabled: false + } + QuickAnswersDefinitionEnabled { + QuickAnswersDefinitionEnabled: false + } + QuickAnswersUnitConversionEnabled { + QuickAnswersUnitConversionEnabled: false } } })");
diff --git a/chromeos/crosapi/mojom/prefs.mojom b/chromeos/crosapi/mojom/prefs.mojom index 28f7025..e3b5fd5 100644 --- a/chromeos/crosapi/mojom/prefs.mojom +++ b/chromeos/crosapi/mojom/prefs.mojom
@@ -95,6 +95,10 @@ [MinVersion=7] kDnsOverHttpsSalt = 33, // M110: ash::prefs::kUserGeolocationAllowed [MinVersion=8] kGeolocationAllowed = 34, + // M112: prefs::kMultitaskMenuNudgeClamshellShownCount + [MinVersion=9] kMultitaskMenuNudgeClamshellShownCount = 35, + // M112: prefs::kMultitaskMenuNudgeClamshellLastShown + [MinVersion=9] kMultitaskMenuNudgeClamshellLastShown = 36, }; // Information about who or what is controlling a particular pref. This is used
diff --git a/chromeos/ui/frame/BUILD.gn b/chromeos/ui/frame/BUILD.gn index 1cead62..77c567e 100644 --- a/chromeos/ui/frame/BUILD.gn +++ b/chromeos/ui/frame/BUILD.gn
@@ -85,6 +85,10 @@ "//ui/views/window/vector_icons", "//ui/wm/public", ] + + if (is_chromeos_ash) { + deps += [ "//ash/constants" ] + } } source_set("test_support") {
diff --git a/chromeos/ui/frame/multitask_menu/multitask_menu_nudge_controller.cc b/chromeos/ui/frame/multitask_menu/multitask_menu_nudge_controller.cc index aba6911..373104f46 100644 --- a/chromeos/ui/frame/multitask_menu/multitask_menu_nudge_controller.cc +++ b/chromeos/ui/frame/multitask_menu/multitask_menu_nudge_controller.cc
@@ -21,6 +21,10 @@ #include "ui/views/layout/box_layout_view.h" #include "ui/views/widget/widget.h" +#if BUILDFLAG(IS_CHROMEOS_ASH) +#include "ash/constants/ash_pref_names.h" +#endif + namespace chromeos { namespace { @@ -119,14 +123,20 @@ display::Screen::GetScreen()->RemoveObserver(this); } +#if BUILDFLAG(IS_CHROMEOS_ASH) // static void MultitaskMenuNudgeController::RegisterProfilePrefs( PrefRegistrySimple* registry) { - registry->RegisterIntegerPref(kClamshellShownCountPrefName, 0); - registry->RegisterIntegerPref(kTabletShownCountPrefName, 0); - registry->RegisterTimePref(kClamshellLastShownPrefName, base::Time()); - registry->RegisterTimePref(kTabletLastShownPrefName, base::Time()); + registry->RegisterIntegerPref( + ash::prefs::kMultitaskMenuNudgeClamshellShownCount, 0); + registry->RegisterIntegerPref(ash::prefs::kMultitaskMenuNudgeTabletShownCount, + 0); + registry->RegisterTimePref(ash::prefs::kMultitaskMenuNudgeClamshellLastShown, + base::Time()); + registry->RegisterTimePref(ash::prefs::kMultitaskMenuNudgeTabletLastShown, + base::Time()); } +#endif void MultitaskMenuNudgeController::MaybeShowNudge(aura::Window* window) { MaybeShowNudge(window, /*anchor_view=*/nullptr); @@ -139,10 +149,7 @@ return; } - // TODO(sammiequon): Delegate is not available for lacros yet. - if (!g_delegate_instance) { - return; - } + DCHECK(g_delegate_instance); // If the window is not visible, do not show the nudge. if (!window->IsVisible()) {
diff --git a/chromeos/ui/frame/multitask_menu/multitask_menu_nudge_controller.h b/chromeos/ui/frame/multitask_menu/multitask_menu_nudge_controller.h index 9c4128af..ea054acb 100644 --- a/chromeos/ui/frame/multitask_menu/multitask_menu_nudge_controller.h +++ b/chromeos/ui/frame/multitask_menu/multitask_menu_nudge_controller.h
@@ -56,27 +56,15 @@ Delegate(); }; - // The name of an integer pref that counts the number of times we have shown - // the multitask menu education nudge. - static constexpr char kClamshellShownCountPrefName[] = - "ash.wm_nudge.multitask_menu_nudge_count"; - static constexpr char kTabletShownCountPrefName[] = - "cros.wm_nudge.tablet_multitask_nudge_count"; - - // The name of a time pref that stores the time we last showed the multitask - // menu education nudge. - static constexpr char kClamshellLastShownPrefName[] = - "ash.wm_nudge.multitask_menu_nudge_last_shown"; - static constexpr char kTabletLastShownPrefName[] = - "cros.wm_nudge.tablet_multitask_nudge_last_shown"; - MultitaskMenuNudgeController(); MultitaskMenuNudgeController(const MultitaskMenuNudgeController&) = delete; MultitaskMenuNudgeController& operator=(const MultitaskMenuNudgeController&) = delete; ~MultitaskMenuNudgeController() override; +#if BUILDFLAG(IS_CHROMEOS_ASH) static void RegisterProfilePrefs(PrefRegistrySimple* registry); +#endif // Attempts to show the nudge. Reads preferences and then calls // `OnGetPreferences()`.
diff --git a/components/BUILD.gn b/components/BUILD.gn index dee253d4..7816b4b 100644 --- a/components/BUILD.gn +++ b/components/BUILD.gn
@@ -339,13 +339,13 @@ "//components/cast_streaming:unit_tests", "//components/certificate_transparency:unit_tests", "//components/content_capture/browser:unit_tests", + "//components/content_relationship_verification:unit_tests", "//components/content_settings/browser:unit_tests", "//components/contextual_search/core/browser:unit_tests", "//components/continuous_search/browser:unit_tests", "//components/continuous_search/common:unit_tests", "//components/custom_handlers:unit_tests", "//components/devtools/simple_devtools_protocol_client:unit_tests", - "//components/digital_asset_links:unit_tests", "//components/discardable_memory/client:unit_tests", "//components/discardable_memory/common:unit_tests", "//components/discardable_memory/service:unit_tests",
diff --git a/components/autofill/content/browser/content_autofill_driver_factory.cc b/components/autofill/content/browser/content_autofill_driver_factory.cc index a789015f..ec6448c 100644 --- a/components/autofill/content/browser/content_autofill_driver_factory.cc +++ b/components/autofill/content/browser/content_autofill_driver_factory.cc
@@ -90,7 +90,11 @@ client_(client), driver_init_hook_(std::move(driver_init_hook)) {} -ContentAutofillDriverFactory::~ContentAutofillDriverFactory() = default; +ContentAutofillDriverFactory::~ContentAutofillDriverFactory() { + for (Observer& observer : observers_) { + observer.OnContentAutofillDriverFactoryDestroyed(*this); + } +} std::unique_ptr<ContentAutofillDriver> ContentAutofillDriverFactory::CreateDriver(content::RenderFrameHost* rfh) { @@ -129,6 +133,9 @@ // 5. `render_frame_host->~RenderFrameHostImpl()` finishes. if (render_frame_host->IsRenderFrameLive()) { driver = CreateDriver(render_frame_host); + for (Observer& observer : observers_) { + observer.OnContentAutofillDriverCreated(*this, *driver); + } DCHECK_EQ(driver_map_.find(render_frame_host)->second.get(), driver.get()); } else { @@ -169,6 +176,9 @@ driver->renderer_events().HidePopup(); } + for (Observer& observer : observers_) { + observer.OnContentAutofillDriverWillBeDeleted(*this, *driver); + } driver_map_.erase(it); }
diff --git a/components/autofill/content/browser/content_autofill_driver_factory.h b/components/autofill/content/browser/content_autofill_driver_factory.h index 0c480edf..a1e80d2 100644 --- a/components/autofill/content/browser/content_autofill_driver_factory.h +++ b/components/autofill/content/browser/content_autofill_driver_factory.h
@@ -44,6 +44,33 @@ using DriverInitCallback = base::RepeatingCallback<void(ContentAutofillDriver*)>; + // Observer of ContentAutofillDriverFactory events. + // + // Using this observer is preferable over registering a WebContentsObserver + // and calling ContentAutofillDriverFactory::DriverForFrame() in the + // WebContentsObserver events. + class Observer : public base::CheckedObserver { + public: + // Called during destruction of the ContentAutofillDriverFactory. No + // members of `factory` should be accessed in this event handler. + virtual void OnContentAutofillDriverFactoryDestroyed( + ContentAutofillDriverFactory& factory) {} + + // Called right after the driver has been created. + // At the time of this event, the `driver` object is already fully alive and + // `factory.DriverForFrame(driver.render_frame_host()) == &driver` holds. + virtual void OnContentAutofillDriverCreated( + ContentAutofillDriverFactory& factory, + ContentAutofillDriver& driver) {} + + // Called right before the driver's RenderFrameHost is deleted. + // At the time of this event, the `driver` object is still fully alive and + // `factory.DriverForFrame(driver.render_frame_host()) == &driver` holds. + virtual void OnContentAutofillDriverWillBeDeleted( + ContentAutofillDriverFactory& factory, + ContentAutofillDriver& driver) {} + }; + static ContentAutofillDriverFactory* FromWebContents( content::WebContents* contents); @@ -75,6 +102,12 @@ AutofillClient* client() { return client_; } + void AddObserver(Observer* observer) { observers_.AddObserver(observer); } + + void RemoveObserver(Observer* observer) { + observers_.RemoveObserver(observer); + } + private: friend class ContentAutofillDriverFactoryTestApi; @@ -88,13 +121,15 @@ // Must be destroyed after |driver_map_|'s elements. ContentAutofillRouter router_; - // The list of drivers, one for each frame in the WebContents. + // Owns the drivers, one for each frame in the WebContents. // Should be empty at destruction time because its elements are erased in // RenderFrameDeleted(). In case it is not empty, is must be destroyed before // |router_| because ~ContentAutofillDriver() may access |router_|. std::unordered_map<content::RenderFrameHost*, std::unique_ptr<ContentAutofillDriver>> driver_map_; + + base::ObserverList<Observer> observers_; }; } // namespace autofill
diff --git a/components/autofill/content/browser/content_autofill_driver_factory_unittest.cc b/components/autofill/content/browser/content_autofill_driver_factory_unittest.cc index 6bd709e..a94dba1 100644 --- a/components/autofill/content/browser/content_autofill_driver_factory_unittest.cc +++ b/components/autofill/content/browser/content_autofill_driver_factory_unittest.cc
@@ -30,6 +30,7 @@ using testing::_; using testing::AtLeast; using testing::Between; +using testing::Ref; namespace autofill { @@ -40,6 +41,25 @@ MOCK_METHOD(void, HideAutofillPopup, (PopupHidingReason), (override)); }; +class MockContentAutofillDriverFactoryObserver + : public ContentAutofillDriverFactory::Observer { + public: + MOCK_METHOD(void, + OnContentAutofillDriverFactoryDestroyed, + (ContentAutofillDriverFactory & factory), + (override)); + MOCK_METHOD(void, + OnContentAutofillDriverCreated, + (ContentAutofillDriverFactory & factory, + ContentAutofillDriver& driver), + (override)); + MOCK_METHOD(void, + OnContentAutofillDriverWillBeDeleted, + (ContentAutofillDriverFactory & factory, + ContentAutofillDriver& driver), + (override)); +}; + class MockAutofillAgent : public mojom::AutofillAgent { public: void BindPendingReceiver(mojo::ScopedInterfaceEndpointHandle handle) { @@ -434,4 +454,49 @@ testing::Mock::VerifyAndClearExpectations(agent_.get()); } +// Tests the notifications of ContentAutofillDriverFactory::Observer. +class ContentAutofillDriverFactoryTest_Observer + : public ContentAutofillDriverFactoryTest { + public: + void SetUp() override { + ContentAutofillDriverFactoryTest::SetUp(); + factory_->AddObserver(&observer_); + } + + void TearDown() override { + if (factory_) { + factory_->RemoveObserver(&observer_); + } + ContentAutofillDriverFactoryTest::TearDown(); + } + + MockContentAutofillDriverFactoryObserver observer_; +}; + +auto IsKnownDriver(ContentAutofillDriverFactory* factory) { + return testing::Truly([factory](ContentAutofillDriver& driver) { + return factory->DriverForFrame(driver.render_frame_host()) == &driver; + }); +} + +TEST_F(ContentAutofillDriverFactoryTest_Observer, FactoryDestroyed) { + EXPECT_CALL(observer_, + OnContentAutofillDriverFactoryDestroyed(Ref(*factory_))); + factory_.reset(); +} + +TEST_F(ContentAutofillDriverFactoryTest_Observer, DriverCreated) { + EXPECT_CALL(observer_, OnContentAutofillDriverCreated( + Ref(*factory_), IsKnownDriver(factory_.get()))); + NavigateMainFrame("https://a.com/"); +} + +TEST_F(ContentAutofillDriverFactoryTest_Observer, DriverDeleted) { + EXPECT_CALL(observer_, OnContentAutofillDriverCreated); + EXPECT_CALL(observer_, OnContentAutofillDriverWillBeDeleted( + Ref(*factory_), IsKnownDriver(factory_.get()))); + NavigateMainFrame("https://a.com/"); + factory_->RenderFrameDeleted(main_rfh()); +} + } // namespace autofill
diff --git a/components/autofill/core/browser/autofill_manager.h b/components/autofill/core/browser/autofill_manager.h index 8a0b69b3..e44db96e 100644 --- a/components/autofill/core/browser/autofill_manager.h +++ b/components/autofill/core/browser/autofill_manager.h
@@ -70,8 +70,7 @@ // - if the request in AutofillDownloadManager was not successful (i.e. no 2XX // response code or a null response body). // - // The main purpose are unit tests. New pairs of events may be added as - // needed. + // New pairs of events may be added as needed. class Observer : public base::CheckedObserver { public: virtual void OnAutofillManagerDestroyed(AutofillManager& manager) {}
diff --git a/components/autofill/core/browser/form_data_importer.cc b/components/autofill/core/browser/form_data_importer.cc index 82b000f..92d2fd8 100644 --- a/components/autofill/core/browser/form_data_importer.cc +++ b/components/autofill/core/browser/form_data_importer.cc
@@ -586,13 +586,9 @@ // country or the app locale. For the `variation_country_code` to take // precedence over the app locale, country code complemention needs to happen // before `SetPhoneNumber()`. - bool complement_country_early = - base::FeatureList::IsEnabled(features::kAutofillComplementCountryEarly); - if (complement_country_early) { - import_metadata.did_complement_country = - should_complement_country && - ComplementCountry(candidate_profile, predicted_country_code); - } + import_metadata.did_complement_country = + should_complement_country && + ComplementCountry(candidate_profile, predicted_country_code); if (!SetPhoneNumber(candidate_profile, combined_phone)) { candidate_profile.ClearFields({PHONE_HOME_WHOLE_NUMBER}); @@ -629,12 +625,6 @@ app_locale_, /*import_log_buffer=*/nullptr); } - if (!complement_country_early) { - import_metadata.did_complement_country = - should_complement_country && - ComplementCountry(candidate_profile, predicted_country_code); - } - // This relies on the profile's country code and must be done strictly after // `ComplementCountry()`. RemoveInaccessibleProfileValues(candidate_profile);
diff --git a/components/autofill/core/browser/form_data_importer_unittest.cc b/components/autofill/core/browser/form_data_importer_unittest.cc index 967ce37..b920212 100644 --- a/components/autofill/core/browser/form_data_importer_unittest.cc +++ b/components/autofill/core/browser/form_data_importer_unittest.cc
@@ -840,10 +840,10 @@ ImportWithCountry("", {kDefaultGermanProfile}); } -// Tests that by complementing the country before setting the phone number, -// the variation country code is preferred over the app locale while parsing -// nationally formatted phone numbers. -TEST_P(FormDataImporterTest, ComplementCountryEarly) { +// Tests that the country is complemented before parsing the phone number. This +// is important, since the phone number validation relies on the profile's +// country for nationally formatted numbers. +TEST_P(FormDataImporterTest, ComplementCountry_PhoneNumberParsing) { // This is a nationally formatted German phone number, which libphonenumber // doesn't parse under the "US" region. const char* kNationalNumber = "01578 7912345"; @@ -865,38 +865,16 @@ // imported country will have country = "DE" assigned. autofill_client_->SetVariationConfigCountryCode("DE"); - { - base::test::ScopedFeatureList complement_country_early_feature; - complement_country_early_feature.InitAndDisableFeature( - features::kAutofillComplementCountryEarly); - - // Without the feature, the phone number parsing logic defaults to the - // "en_US" locale. Thus, parsing fails and the phone number is removed. - base::HistogramTester histogram_tester; - expected_profile.ClearFields({PHONE_HOME_WHOLE_NUMBER}); - ExtractAddressProfilesAndVerifyExpectation(*form_structure, - {expected_profile}); - EXPECT_THAT(histogram_tester.GetAllSamples(kHistogramName), - testing::UnorderedElementsAre(base::Bucket(false, 1))); - } - - { - base::test::ScopedFeatureList complement_country_early_feature; - complement_country_early_feature.InitAndEnableFeature( - features::kAutofillComplementCountryEarly); - - // With the feature enabled, the country complemention happens first. Thus, - // at the time the number is parsed, we correctly apply the German rules. - base::HistogramTester histogram_tester; - // The `expected_profile` can successfully parse the number, as the - // profile's country is "DE". - EXPECT_TRUE(expected_profile.SetInfo( - PHONE_HOME_WHOLE_NUMBER, base::UTF8ToUTF16(kNationalNumber), kLocale)); - ExtractAddressProfilesAndVerifyExpectation(*form_structure, - {expected_profile}); - EXPECT_THAT(histogram_tester.GetAllSamples(kHistogramName), - testing::UnorderedElementsAre(base::Bucket(true, 1))); - } + // Country complemention happens before parsing the phone number. Thus, at the + // time the number is parsed, we correctly apply the German rules. + base::HistogramTester histogram_tester; + // The `expected_profile` can successfully parse the number, as the + // profile's country is "DE". + EXPECT_TRUE(expected_profile.SetInfo( + PHONE_HOME_WHOLE_NUMBER, base::UTF8ToUTF16(kNationalNumber), kLocale)); + ExtractAddressProfilesAndVerifyExpectation(*form_structure, + {expected_profile}); + histogram_tester.ExpectUniqueSample(kHistogramName, true, 1); } // Tests how invalid countries in submitted forms are treated depending on @@ -4207,10 +4185,8 @@ // Tests that a complemented country is discarded in favour of an observed one. TEST_P(FormDataImporterTest, MultiStepImport_ComplementCountryEarly) { - base::test::ScopedFeatureList features; - features.InitWithFeatures({features::kAutofillEnableMultiStepImports, - features::kAutofillComplementCountryEarly}, - {}); + base::test::ScopedFeatureList feature; + feature.InitAndEnableFeature(features::kAutofillEnableMultiStepImports); // Import a profile fragment with country information. TypeValuePairs type_value_pairs =
diff --git a/components/autofill/core/browser/form_data_importer_utils.cc b/components/autofill/core/browser/form_data_importer_utils.cc index 2154500d..db016f3 100644 --- a/components/autofill/core/browser/form_data_importer_utils.cc +++ b/components/autofill/core/browser/form_data_importer_utils.cc
@@ -244,22 +244,14 @@ auto candidate = multistep_candidates_.begin(); AutofillProfile completed_profile = profile; ProfileImportMetadata completed_metadata = import_metadata; - // If `complement_country_early` is enabled, merging might fail due to an - // incorrectly complemented country in one of the merge candidates. - // Without the feature, the country complement logic has not happened yet. - bool complement_country_early = - base::FeatureList::IsEnabled(features::kAutofillComplementCountryEarly); - DCHECK(complement_country_early || - !completed_metadata.did_complement_country); - while (candidate != multistep_candidates_.end()) { - if (!comparator_.AreMergeable(completed_profile, candidate->profile) && - (!complement_country_early || - !MergeableByRemovingIncorrectlyComplementedCountry( - completed_profile, completed_metadata.did_complement_country, - candidate->profile, - candidate->import_metadata.did_complement_country))) { - break; - } + // Merging might fail due to an incorrectly complemented country in one of the + // merge candidates. In this case, try removing the complemented country. + while (candidate != multistep_candidates_.end() && + (comparator_.AreMergeable(completed_profile, candidate->profile) || + MergeableByRemovingIncorrectlyComplementedCountry( + completed_profile, completed_metadata.did_complement_country, + candidate->profile, + candidate->import_metadata.did_complement_country))) { completed_profile.MergeDataFrom(candidate->profile, app_locale_); MergeImportMetadata(candidate->import_metadata, completed_metadata); candidate++;
diff --git a/components/autofill/core/browser/payments/credit_card_fido_authenticator.cc b/components/autofill/core/browser/payments/credit_card_fido_authenticator.cc index 1eb16a6..e5e65011 100644 --- a/components/autofill/core/browser/payments/credit_card_fido_authenticator.cc +++ b/components/autofill/core/browser/payments/credit_card_fido_authenticator.cc
@@ -611,15 +611,15 @@ CreditCardFidoAuthenticator::ParseCredentialDescriptor( const base::Value& key_info) { std::vector<uint8_t> credential_id; - const auto* id = key_info.FindStringKey("credential_id"); + const auto* id = key_info.GetDict().FindString("credential_id"); DCHECK(id); credential_id = Base64ToBytes(*id); base::flat_set<device::FidoTransportProtocol> authenticator_transports; - const auto* transports = key_info.FindKeyOfType( - "authenticator_transport_support", base::Value::Type::LIST); - if (transports && !transports->GetList().empty()) { - for (const base::Value& transport_type : transports->GetList()) { + const auto* transports = + key_info.GetDict().FindList("authenticator_transport_support"); + if (transports && !transports->empty()) { + for (const base::Value& transport_type : *transports) { absl::optional<device::FidoTransportProtocol> protocol = device::ConvertToFidoTransportProtocol( base::ToLowerASCII(transport_type.GetString()));
diff --git a/components/autofill/core/common/autofill_features.cc b/components/autofill/core/common/autofill_features.cc index 22d9cfe3..758ac85b 100644 --- a/components/autofill/core/common/autofill_features.cc +++ b/components/autofill/core/common/autofill_features.cc
@@ -82,14 +82,6 @@ "AutofillInferCountryCallingCode", base::FEATURE_DISABLED_BY_DEFAULT); -// If enabled, complementing the country happens before setting the phone number -// on profile import. This way, the variation country code takes precedence over -// the app locale. -// TODO(crbug.com/1295721): Cleanup when launched. -BASE_FEATURE(kAutofillComplementCountryEarly, - "AutofillComplementCountryEarly", - base::FEATURE_ENABLED_BY_DEFAULT); - // If enabled, label inference considers strings entirely made up of '(', ')' // and '-' as valid labels. // TODO(crbug.com/1311937): Cleanup when launched.
diff --git a/components/autofill/core/common/autofill_features.h b/components/autofill/core/common/autofill_features.h index b969b81..22be90ff 100644 --- a/components/autofill/core/common/autofill_features.h +++ b/components/autofill/core/common/autofill_features.h
@@ -37,8 +37,6 @@ COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillInferCountryCallingCode); COMPONENT_EXPORT(AUTOFILL) -BASE_DECLARE_FEATURE(kAutofillComplementCountryEarly); -COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillConsiderPhoneNumberSeparatorsValidLabels); COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillDeferSubmissionClassificationAfterAjax);
diff --git a/components/blocked_content/popup_navigation_delegate.h b/components/blocked_content/popup_navigation_delegate.h index 55ea3357..52eb3ce 100644 --- a/components/blocked_content/popup_navigation_delegate.h +++ b/components/blocked_content/popup_navigation_delegate.h
@@ -33,7 +33,7 @@ virtual bool GetOriginalUserGesture() = 0; // Gets the URL to be loaded. - virtual const GURL& GetURL() = 0; + virtual GURL GetURL() = 0; // Performs the navigation. struct NavigateResult {
diff --git a/components/blocked_content/test/test_popup_navigation_delegate.cc b/components/blocked_content/test/test_popup_navigation_delegate.cc index 640eaba6..91cc90a9 100644 --- a/components/blocked_content/test/test_popup_navigation_delegate.cc +++ b/components/blocked_content/test/test_popup_navigation_delegate.cc
@@ -23,7 +23,7 @@ return true; } -const GURL& TestPopupNavigationDelegate::GetURL() { +GURL TestPopupNavigationDelegate::GetURL() { return url_; }
diff --git a/components/blocked_content/test/test_popup_navigation_delegate.h b/components/blocked_content/test/test_popup_navigation_delegate.h index b34858c..f147d135 100644 --- a/components/blocked_content/test/test_popup_navigation_delegate.h +++ b/components/blocked_content/test/test_popup_navigation_delegate.h
@@ -32,7 +32,7 @@ // PopupNavigationDelegate: content::RenderFrameHost* GetOpener() override; bool GetOriginalUserGesture() override; - const GURL& GetURL() override; + GURL GetURL() override; NavigateResult NavigateWithGesture( const blink::mojom::WindowFeatures& window_features, absl::optional<WindowOpenDisposition> updated_disposition) override;
diff --git a/components/bookmarks/browser/bookmark_storage_unittest.cc b/components/bookmarks/browser/bookmark_storage_unittest.cc index bd07d77..5d488d2 100644 --- a/components/bookmarks/browser/bookmark_storage_unittest.cc +++ b/components/bookmarks/browser/bookmark_storage_unittest.cc
@@ -95,7 +95,7 @@ bookmarks_file_path.ReplaceExtension(FILE_PATH_LITERAL("bak")); // Create a dummy JSON file, to verify backups are created. - ASSERT_NE(0, base::WriteFile(bookmarks_file_path, "{}", 2)); + ASSERT_TRUE(base::WriteFile(bookmarks_file_path, "{}")); base::test::TaskEnvironment task_environment{ base::test::TaskEnvironment::TimeSource::MOCK_TIME};
diff --git a/components/cast_streaming/OWNERS b/components/cast_streaming/OWNERS index 92be789a..f2aea22e 100644 --- a/components/cast_streaming/OWNERS +++ b/components/cast_streaming/OWNERS
@@ -2,3 +2,4 @@ fdegans@chromium.org rwkeane@google.com ddorwin@chromium.org +mfoltz@chromium.org
diff --git a/components/digital_asset_links/BUILD.gn b/components/content_relationship_verification/BUILD.gn similarity index 76% rename from components/digital_asset_links/BUILD.gn rename to components/content_relationship_verification/BUILD.gn index a317ea5..f681c1a 100644 --- a/components/digital_asset_links/BUILD.gn +++ b/components/content_relationship_verification/BUILD.gn
@@ -2,10 +2,10 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -source_set("digital_asset_links") { +source_set("content_relationship_verification") { sources = [ - "digital_asset_links_constants.cc", - "digital_asset_links_constants.h", + "content_relationship_verification_constants.cc", + "content_relationship_verification_constants.h", "digital_asset_links_handler.cc", "digital_asset_links_handler.h", "response_header_verifier.cc", @@ -28,7 +28,8 @@ "origin_verifier.cc", "origin_verifier.h", ] - deps += [ "//components/digital_asset_links/android:jni_headers" ] + deps += + [ "//components/content_relationship_verification/android:jni_headers" ] } } @@ -41,7 +42,7 @@ ] deps = [ - ":digital_asset_links", + ":content_relationship_verification", "//base", "//content/test:test_support", "//net", @@ -56,7 +57,8 @@ android_library("java") { deps = [ "//third_party/androidx:androidx_annotation_annotation_java" ] - srcjar_deps = [ "//components/digital_asset_links:enums_srcjar" ] + srcjar_deps = + [ "//components/content_relationship_verification:enums_srcjar" ] } java_cpp_enum("enums_srcjar") {
diff --git a/components/digital_asset_links/DEPS b/components/content_relationship_verification/DEPS similarity index 100% rename from components/digital_asset_links/DEPS rename to components/content_relationship_verification/DEPS
diff --git a/components/digital_asset_links/DIR_METADATA b/components/content_relationship_verification/DIR_METADATA similarity index 100% rename from components/digital_asset_links/DIR_METADATA rename to components/content_relationship_verification/DIR_METADATA
diff --git a/components/digital_asset_links/OWNERS b/components/content_relationship_verification/OWNERS similarity index 100% rename from components/digital_asset_links/OWNERS rename to components/content_relationship_verification/OWNERS
diff --git a/components/content_relationship_verification/README.md b/components/content_relationship_verification/README.md new file mode 100644 index 0000000..8c52735 --- /dev/null +++ b/components/content_relationship_verification/README.md
@@ -0,0 +1,21 @@ +# Content Relationship Verification + +This component contains utilities to verify relationships between Web content and the embedder. + +## Verification methods + +- Digital Asset Links + + Utilities to facilitate making requests to the DigitalAssetLinks API on the Web. + + See [documentation](https://developers.google.com/digital-asset-links/v1/getting-started). + + +- Response Header Verification + + Class that contains utilities to parse the `X-Embedder-Ancestors`- response header. + + +## Browser URL Loader Throttle + +URL loader throttle that aborts loading of http responses when no relationship between Web content and embedder was verified. \ No newline at end of file
diff --git a/components/content_relationship_verification/android/BUILD.gn b/components/content_relationship_verification/android/BUILD.gn new file mode 100644 index 0000000..f33972b --- /dev/null +++ b/components/content_relationship_verification/android/BUILD.gn
@@ -0,0 +1,39 @@ +# Copyright 2022 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/android/rules.gni") + +android_library("java") { + sources = [ + "java/src/org/chromium/components/content_relationship_verification/OriginVerificationScheduler.java", + "java/src/org/chromium/components/content_relationship_verification/OriginVerifier.java", + "java/src/org/chromium/components/content_relationship_verification/OriginVerifierHelper.java", + "java/src/org/chromium/components/content_relationship_verification/Relationship.java", + "java/src/org/chromium/components/content_relationship_verification/VerificationResultStore.java", + ] + deps = [ + "//base:base_java", + "//base:jni_java", + "//build/android:build_java", + "//components/content_relationship_verification:java", + "//components/embedder_support/android:util_java", + "//content/public/android:content_java", + "//third_party/androidx:androidx_annotation_annotation_java", + ] + annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ] +} + +robolectric_library("junit_test_support") { + sources = [ "java/src/org/chromium/components/content_relationship_verification/OriginVerifierUnitTestSupport.java" ] + deps = [ + ":java", + "//components/embedder_support/android:util_java", + "//third_party/androidx:androidx_browser_browser_java", + "//third_party/mockito:mockito_java", + ] +} + +generate_jni("jni_headers") { + sources = [ "java/src/org/chromium/components/content_relationship_verification/OriginVerifier.java" ] +}
diff --git a/components/digital_asset_links/android/java/src/org/chromium/components/digital_asset_links/OriginVerificationScheduler.java b/components/content_relationship_verification/android/java/src/org/chromium/components/content_relationship_verification/OriginVerificationScheduler.java similarity index 97% rename from components/digital_asset_links/android/java/src/org/chromium/components/digital_asset_links/OriginVerificationScheduler.java rename to components/content_relationship_verification/android/java/src/org/chromium/components/content_relationship_verification/OriginVerificationScheduler.java index 0189713fe..7bf061e 100644 --- a/components/digital_asset_links/android/java/src/org/chromium/components/digital_asset_links/OriginVerificationScheduler.java +++ b/components/content_relationship_verification/android/java/src/org/chromium/components/content_relationship_verification/OriginVerificationScheduler.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.components.digital_asset_links; +package org.chromium.components.content_relationship_verification; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting;
diff --git a/components/digital_asset_links/android/java/src/org/chromium/components/digital_asset_links/OriginVerifier.java b/components/content_relationship_verification/android/java/src/org/chromium/components/content_relationship_verification/OriginVerifier.java similarity index 98% rename from components/digital_asset_links/android/java/src/org/chromium/components/digital_asset_links/OriginVerifier.java rename to components/content_relationship_verification/android/java/src/org/chromium/components/content_relationship_verification/OriginVerifier.java index c9c0009..f8f098d 100644 --- a/components/digital_asset_links/android/java/src/org/chromium/components/digital_asset_links/OriginVerifier.java +++ b/components/content_relationship_verification/android/java/src/org/chromium/components/content_relationship_verification/OriginVerifier.java
@@ -1,8 +1,8 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. +// Copyright 2017 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.components.digital_asset_links; +package org.chromium.components.content_relationship_verification; import android.content.pm.PackageManager; import android.net.Uri;
diff --git a/components/digital_asset_links/android/java/src/org/chromium/components/digital_asset_links/OriginVerifierHelper.java b/components/content_relationship_verification/android/java/src/org/chromium/components/content_relationship_verification/OriginVerifierHelper.java similarity index 97% rename from components/digital_asset_links/android/java/src/org/chromium/components/digital_asset_links/OriginVerifierHelper.java rename to components/content_relationship_verification/android/java/src/org/chromium/components/content_relationship_verification/OriginVerifierHelper.java index 3aedf0e..8f944c1 100644 --- a/components/digital_asset_links/android/java/src/org/chromium/components/digital_asset_links/OriginVerifierHelper.java +++ b/components/content_relationship_verification/android/java/src/org/chromium/components/content_relationship_verification/OriginVerifierHelper.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.components.digital_asset_links; +package org.chromium.components.content_relationship_verification; import android.content.Context; import android.content.pm.PackageManager;
diff --git a/components/digital_asset_links/android/java/src/org/chromium/components/digital_asset_links/OriginVerifierUnitTestSupport.java b/components/content_relationship_verification/android/java/src/org/chromium/components/content_relationship_verification/OriginVerifierUnitTestSupport.java similarity index 97% rename from components/digital_asset_links/android/java/src/org/chromium/components/digital_asset_links/OriginVerifierUnitTestSupport.java rename to components/content_relationship_verification/android/java/src/org/chromium/components/content_relationship_verification/OriginVerifierUnitTestSupport.java index 31527fd..65ccd5e9 100644 --- a/components/digital_asset_links/android/java/src/org/chromium/components/digital_asset_links/OriginVerifierUnitTestSupport.java +++ b/components/content_relationship_verification/android/java/src/org/chromium/components/content_relationship_verification/OriginVerifierUnitTestSupport.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.components.digital_asset_links; +package org.chromium.components.content_relationship_verification; import android.content.pm.PackageInfo; import android.content.pm.Signature;
diff --git a/components/digital_asset_links/android/java/src/org/chromium/components/digital_asset_links/Relationship.java b/components/content_relationship_verification/android/java/src/org/chromium/components/content_relationship_verification/Relationship.java similarity index 95% rename from components/digital_asset_links/android/java/src/org/chromium/components/digital_asset_links/Relationship.java rename to components/content_relationship_verification/android/java/src/org/chromium/components/content_relationship_verification/Relationship.java index da4fcdc..bfd01cb 100644 --- a/components/digital_asset_links/android/java/src/org/chromium/components/digital_asset_links/Relationship.java +++ b/components/content_relationship_verification/android/java/src/org/chromium/components/content_relationship_verification/Relationship.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.components.digital_asset_links; +package org.chromium.components.content_relationship_verification; import org.chromium.components.embedder_support.util.Origin;
diff --git a/components/digital_asset_links/android/java/src/org/chromium/components/digital_asset_links/VerificationResultStore.java b/components/content_relationship_verification/android/java/src/org/chromium/components/content_relationship_verification/VerificationResultStore.java similarity index 97% rename from components/digital_asset_links/android/java/src/org/chromium/components/digital_asset_links/VerificationResultStore.java rename to components/content_relationship_verification/android/java/src/org/chromium/components/content_relationship_verification/VerificationResultStore.java index afe2507..2aa66b6 100644 --- a/components/digital_asset_links/android/java/src/org/chromium/components/digital_asset_links/VerificationResultStore.java +++ b/components/content_relationship_verification/android/java/src/org/chromium/components/content_relationship_verification/VerificationResultStore.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.components.digital_asset_links; +package org.chromium.components.content_relationship_verification; import androidx.annotation.VisibleForTesting;
diff --git a/components/digital_asset_links/browser_url_loader_throttle.cc b/components/content_relationship_verification/browser_url_loader_throttle.cc similarity index 87% rename from components/digital_asset_links/browser_url_loader_throttle.cc rename to components/content_relationship_verification/browser_url_loader_throttle.cc index ae2f6fa..72e9747 100644 --- a/components/digital_asset_links/browser_url_loader_throttle.cc +++ b/components/content_relationship_verification/browser_url_loader_throttle.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/digital_asset_links/browser_url_loader_throttle.h" +#include "components/content_relationship_verification/browser_url_loader_throttle.h" #include "base/android/build_info.h" #include "base/check_op.h" @@ -10,8 +10,8 @@ #include "base/memory/ptr_util.h" #include "base/metrics/histogram_functions.h" #include "base/trace_event/trace_event.h" -#include "components/digital_asset_links/digital_asset_links_constants.h" -#include "components/digital_asset_links/response_header_verifier.h" +#include "components/content_relationship_verification/content_relationship_verification_constants.h" +#include "components/content_relationship_verification/response_header_verifier.h" #include "content/public/browser/browser_task_traits.h" #include "net/log/net_log_event_type.h" #include "net/url_request/redirect_info.h" @@ -19,7 +19,7 @@ #include "services/network/public/mojom/fetch_api.mojom.h" #include "services/network/public/mojom/url_response_head.mojom.h" -namespace digital_asset_links { +namespace content_relationship_verification { BrowserURLLoaderThrottle::OriginVerificationSchedulerBridge:: OriginVerificationSchedulerBridge() = default; @@ -46,7 +46,7 @@ std::string header_value; response_head.headers->GetNormalizedHeader(kEmbedderAncestorHeader, &header_value); - return digital_asset_links::ResponseHeaderVerifier::Verify( + return content_relationship_verification::ResponseHeaderVerifier::Verify( base::android::BuildInfo::GetInstance()->host_package_name(), header_value); } @@ -105,7 +105,7 @@ delegate_->Resume(); return; } - delegate_->CancelWithError(kNetErrorCodeForDigitalAssetLinks, + delegate_->CancelWithError(kNetErrorCodeForContentRelationshipVerification, kCustomCancelReasonForURLLoader); } @@ -113,4 +113,4 @@ return "DigitalAssetLinksBrowserThrottle"; } -} // namespace digital_asset_links +} // namespace content_relationship_verification
diff --git a/components/digital_asset_links/browser_url_loader_throttle.h b/components/content_relationship_verification/browser_url_loader_throttle.h similarity index 89% rename from components/digital_asset_links/browser_url_loader_throttle.h rename to components/content_relationship_verification/browser_url_loader_throttle.h index ca6572d..b4803fb 100644 --- a/components/digital_asset_links/browser_url_loader_throttle.h +++ b/components/content_relationship_verification/browser_url_loader_throttle.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_DIGITAL_ASSET_LINKS_BROWSER_URL_LOADER_THROTTLE_H_ -#define COMPONENTS_DIGITAL_ASSET_LINKS_BROWSER_URL_LOADER_THROTTLE_H_ +#ifndef COMPONENTS_CONTENT_RELATIONSHIP_VERIFICATION_BROWSER_URL_LOADER_THROTTLE_H_ +#define COMPONENTS_CONTENT_RELATIONSHIP_VERIFICATION_BROWSER_URL_LOADER_THROTTLE_H_ #include <memory> @@ -16,7 +16,7 @@ #include "third_party/blink/public/common/loader/url_loader_throttle.h" #include "url/gurl.h" -namespace digital_asset_links { +namespace content_relationship_verification { // TODO(crbug.com/1376958): Add CSP as method to allow content access in this // throttle and then move it to components/third_party_restrictions. @@ -89,6 +89,6 @@ base::WeakPtrFactory<BrowserURLLoaderThrottle> weak_factory_{this}; }; -} // namespace digital_asset_links +} // namespace content_relationship_verification -#endif // COMPONENTS_DIGITAL_ASSET_LINKS_BROWSER_URL_LOADER_THROTTLE_H_ +#endif // COMPONENTS_CONTENT_RELATIONSHIP_VERIFICATION_BROWSER_URL_LOADER_THROTTLE_H_
diff --git a/components/content_relationship_verification/content_relationship_verification_constants.cc b/components/content_relationship_verification/content_relationship_verification_constants.cc new file mode 100644 index 0000000..88e7f51 --- /dev/null +++ b/components/content_relationship_verification/content_relationship_verification_constants.cc
@@ -0,0 +1,17 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/content_relationship_verification/content_relationship_verification_constants.h" + +#include "net/base/net_errors.h" + +namespace content_relationship_verification { + +const char kCustomCancelReasonForURLLoader[] = + "ContentRelationshipVerification"; + +const int kNetErrorCodeForContentRelationshipVerification = + net::ERR_ACCESS_DENIED; + +} // namespace content_relationship_verification
diff --git a/components/content_relationship_verification/content_relationship_verification_constants.h b/components/content_relationship_verification/content_relationship_verification_constants.h new file mode 100644 index 0000000..293471b --- /dev/null +++ b/components/content_relationship_verification/content_relationship_verification_constants.h
@@ -0,0 +1,21 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_CONTENT_RELATIONSHIP_VERIFICATION_CONTENT_RELATIONSHIP_VERIFICATION_CONSTANTS_H_ +#define COMPONENTS_CONTENT_RELATIONSHIP_VERIFICATION_CONTENT_RELATIONSHIP_VERIFICATION_CONSTANTS_H_ + +namespace content_relationship_verification { + +// When a network::mojom::URLLoader is cancelled because of content relationship +// verification, this custom cancellation reason could be used to notify the +// implementation side. Please see +// network::mojom::URLLoader::kClientDisconnectReason for more details. +extern const char kCustomCancelReasonForURLLoader[]; + +// error_code to use when content relationship verification blocks a request. +extern const int kNetErrorCodeForContentRelationshipVerification; + +} // namespace content_relationship_verification + +#endif // COMPONENTS_CONTENT_RELATIONSHIP_VERIFICATION_CONTENT_RELATIONSHIP_VERIFICATION_CONSTANTS_H_
diff --git a/components/digital_asset_links/digital_asset_links_handler.cc b/components/content_relationship_verification/digital_asset_links_handler.cc similarity index 96% rename from components/digital_asset_links/digital_asset_links_handler.cc rename to components/content_relationship_verification/digital_asset_links_handler.cc index a068326..b52de5c3 100644 --- a/components/digital_asset_links/digital_asset_links_handler.cc +++ b/components/content_relationship_verification/digital_asset_links_handler.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/digital_asset_links/digital_asset_links_handler.h" +#include "components/content_relationship_verification/digital_asset_links_handler.h" #include <vector> @@ -137,7 +137,7 @@ } // namespace -namespace digital_asset_links { +namespace content_relationship_verification { const char kDigitalAssetLinksCheckResponseKeyLinked[] = "linked"; @@ -158,8 +158,9 @@ std::map<std::string, std::set<std::string>> target_values, std::unique_ptr<std::string> response_body) { int response_code = -1; - if (url_loader_->ResponseInfo() && url_loader_->ResponseInfo()->headers) + if (url_loader_->ResponseInfo() && url_loader_->ResponseInfo()->headers) { response_code = url_loader_->ResponseInfo()->headers->response_code(); + } if (!response_body || response_code != net::HTTP_OK) { int net_error = url_loader_->NetError(); @@ -241,15 +242,17 @@ break; } } - if (failed_target_check) + if (failed_target_check) { continue; + } std::move(callback_).Run(RelationshipCheckResult::kSuccess); return; } - for (const auto& failure_reason : failures) + for (const auto& failure_reason : failures) { AddMessageToConsole(web_contents_.get(), failure_reason); + } std::move(callback_).Run(RelationshipCheckResult::kFailure); } @@ -283,8 +286,9 @@ RelationshipCheckResultCallback callback) { GURL request_url = GetUrlForAssetLinks(web_domain); - if (!request_url.is_valid()) + if (!request_url.is_valid()) { return false; + } // Resetting both the callback and SimpleURLLoader here to ensure // that any previous requests will never get a @@ -338,4 +342,4 @@ return true; } -} // namespace digital_asset_links +} // namespace content_relationship_verification
diff --git a/components/digital_asset_links/digital_asset_links_handler.h b/components/content_relationship_verification/digital_asset_links_handler.h similarity index 91% rename from components/digital_asset_links/digital_asset_links_handler.h rename to components/content_relationship_verification/digital_asset_links_handler.h index 0175ab7..d3ae4bc 100644 --- a/components/digital_asset_links/digital_asset_links_handler.h +++ b/components/content_relationship_verification/digital_asset_links_handler.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_DIGITAL_ASSET_LINKS_DIGITAL_ASSET_LINKS_HANDLER_H_ -#define COMPONENTS_DIGITAL_ASSET_LINKS_DIGITAL_ASSET_LINKS_HANDLER_H_ +#ifndef COMPONENTS_CONTENT_RELATIONSHIP_VERIFICATION_DIGITAL_ASSET_LINKS_HANDLER_H_ +#define COMPONENTS_CONTENT_RELATIONSHIP_VERIFICATION_DIGITAL_ASSET_LINKS_HANDLER_H_ #include <map> #include <set> @@ -27,11 +27,12 @@ class Origin; } // namespace url -namespace digital_asset_links { +namespace content_relationship_verification { extern const char kDigitalAssetLinksCheckResponseKeyLinked[]; -// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.components.digital_asset_links +// GENERATED_JAVA_ENUM_PACKAGE: ( +// org.chromium.components.content_relationship_verification) enum class RelationshipCheckResult { kSuccess = 0, kFailure, @@ -127,6 +128,6 @@ base::WeakPtrFactory<DigitalAssetLinksHandler> weak_ptr_factory_{this}; }; -} // namespace digital_asset_links +} // namespace content_relationship_verification -#endif // COMPONENTS_DIGITAL_ASSET_LINKS_DIGITAL_ASSET_LINKS_HANDLER_H_ +#endif // COMPONENTS_CONTENT_RELATIONSHIP_VERIFICATION_DIGITAL_ASSET_LINKS_HANDLER_H_
diff --git a/components/digital_asset_links/digital_asset_links_handler_unittest.cc b/components/content_relationship_verification/digital_asset_links_handler_unittest.cc similarity index 98% rename from components/digital_asset_links/digital_asset_links_handler_unittest.cc rename to components/content_relationship_verification/digital_asset_links_handler_unittest.cc index 32564e58..52a3181f 100644 --- a/components/digital_asset_links/digital_asset_links_handler_unittest.cc +++ b/components/content_relationship_verification/digital_asset_links_handler_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/digital_asset_links/digital_asset_links_handler.h" +#include "components/content_relationship_verification/digital_asset_links_handler.h" #include "base/command_line.h" #include "base/functional/bind.h" @@ -72,7 +72,7 @@ } // namespace -namespace digital_asset_links { +namespace content_relationship_verification { namespace { class DigitalAssetLinksHandlerTest : public ::testing::Test { @@ -369,4 +369,4 @@ EXPECT_EQ(result_, RelationshipCheckResult::kFailure); } -} // namespace digital_asset_links +} // namespace content_relationship_verification
diff --git a/components/digital_asset_links/origin_verifier.cc b/components/content_relationship_verification/origin_verifier.cc similarity index 86% rename from components/digital_asset_links/origin_verifier.cc rename to components/content_relationship_verification/origin_verifier.cc index 8927741..16fd578 100644 --- a/components/digital_asset_links/origin_verifier.cc +++ b/components/content_relationship_verification/origin_verifier.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/digital_asset_links/origin_verifier.h" +#include "components/content_relationship_verification/origin_verifier.h" #include <memory> @@ -10,8 +10,8 @@ #include "base/android/jni_array.h" #include "base/android/jni_string.h" #include "base/functional/bind.h" -#include "components/digital_asset_links/android/jni_headers/OriginVerifier_jni.h" -#include "components/digital_asset_links/digital_asset_links_handler.h" +#include "components/content_relationship_verification/android/jni_headers/OriginVerifier_jni.h" +#include "components/content_relationship_verification/digital_asset_links_handler.h" #include "content/public/browser/android/browser_context_handle.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" @@ -25,7 +25,7 @@ using base::android::ConvertJavaStringToUTF16; using base::android::JavaParamRef; using base::android::JavaRef; -using digital_asset_links::RelationshipCheckResult; +using content_relationship_verification::RelationshipCheckResult; OriginVerifier::OriginVerifier( JNIEnv* env, @@ -49,8 +49,9 @@ const JavaParamRef<jstring>& j_origin, const JavaParamRef<jstring>& j_relationship, const base::android::JavaRef<jobject>& jweb_contents) { - if (!j_package_name || !j_fingerprints || !j_origin || !j_relationship) + if (!j_package_name || !j_fingerprints || !j_origin || !j_relationship) { return false; + } raw_ptr<content::WebContents> web_contents = content::WebContents::FromJavaWebContents(jweb_contents); std::string package_name = ConvertJavaStringToUTF8(env, j_package_name); @@ -61,9 +62,9 @@ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - auto asset_link_handler = - std::make_unique<digital_asset_links::DigitalAssetLinksHandler>( - url_loader_factory_, web_contents); + auto asset_link_handler = std::make_unique< + content_relationship_verification::DigitalAssetLinksHandler>( + url_loader_factory_, web_contents); auto* asset_link_handler_ptr = asset_link_handler.get(); @@ -76,7 +77,8 @@ } void OriginVerifier::OnRelationshipCheckComplete( - std::unique_ptr<digital_asset_links::DigitalAssetLinksHandler> handler, + std::unique_ptr<content_relationship_verification::DigitalAssetLinksHandler> + handler, const std::string& origin, RelationshipCheckResult result) { JNIEnv* env = base::android::AttachCurrentThread();
diff --git a/components/digital_asset_links/origin_verifier.h b/components/content_relationship_verification/origin_verifier.h similarity index 78% rename from components/digital_asset_links/origin_verifier.h rename to components/content_relationship_verification/origin_verifier.h index b35e36e..ddfb0a9 100644 --- a/components/digital_asset_links/origin_verifier.h +++ b/components/content_relationship_verification/origin_verifier.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_DIGITAL_ASSET_LINKS_ORIGIN_VERIFIER_H_ -#define COMPONENTS_DIGITAL_ASSET_LINKS_ORIGIN_VERIFIER_H_ +#ifndef COMPONENTS_CONTENT_RELATIONSHIP_VERIFICATION_ORIGIN_VERIFIER_H_ +#define COMPONENTS_CONTENT_RELATIONSHIP_VERIFICATION_ORIGIN_VERIFIER_H_ #include <memory> @@ -13,10 +13,10 @@ #include "net/url_request/url_request_context_getter.h" #include "services/network/public/cpp/shared_url_loader_factory.h" -namespace digital_asset_links { +namespace content_relationship_verification { enum class RelationshipCheckResult; class DigitalAssetLinksHandler; -} // namespace digital_asset_links +} // namespace content_relationship_verification // JNI bridge for OriginVerifier.java class OriginVerifier { @@ -53,13 +53,14 @@ private: void OnRelationshipCheckComplete( - std::unique_ptr<digital_asset_links::DigitalAssetLinksHandler> handler, + std::unique_ptr< + content_relationship_verification::DigitalAssetLinksHandler> handler, const std::string& origin, - digital_asset_links::RelationshipCheckResult result); + content_relationship_verification::RelationshipCheckResult result); scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_; base::android::ScopedJavaGlobalRef<jobject> jobject_; }; -#endif // COMPONENTS_DIGITAL_ASSET_LINKS_ORIGIN_VERIFIER_H_ +#endif // COMPONENTS_CONTENT_RELATIONSHIP_VERIFICATION_ORIGIN_VERIFIER_H_
diff --git a/components/digital_asset_links/response_header_verifier.cc b/components/content_relationship_verification/response_header_verifier.cc similarity index 87% rename from components/digital_asset_links/response_header_verifier.cc rename to components/content_relationship_verification/response_header_verifier.cc index 3062c30..f22d6635 100644 --- a/components/digital_asset_links/response_header_verifier.cc +++ b/components/content_relationship_verification/response_header_verifier.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/digital_asset_links/response_header_verifier.h" +#include "components/content_relationship_verification/response_header_verifier.h" #include <stdio.h> @@ -13,7 +13,7 @@ const char kNormalizedHeaderDelimiter[] = ","; } // namespace -namespace digital_asset_links { +namespace content_relationship_verification { const char kEmbedderAncestorHeader[] = "X-Embedder-Ancestors"; @@ -46,4 +46,4 @@ return false; } -} // namespace digital_asset_links +} // namespace content_relationship_verification
diff --git a/components/content_relationship_verification/response_header_verifier.h b/components/content_relationship_verification/response_header_verifier.h new file mode 100644 index 0000000..b96ef34 --- /dev/null +++ b/components/content_relationship_verification/response_header_verifier.h
@@ -0,0 +1,23 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_CONTENT_RELATIONSHIP_VERIFICATION_RESPONSE_HEADER_VERIFIER_H_ +#define COMPONENTS_CONTENT_RELATIONSHIP_VERIFICATION_RESPONSE_HEADER_VERIFIER_H_ + +#include <string> + +namespace content_relationship_verification { + +class ResponseHeaderVerifier { + public: + // Verify if the provided |package_name| is verified via the embedder + // ancestor header. + static bool Verify(const std::string& package_name, + const std::string& embedder_ancestors_header_value); +}; + +extern const char kEmbedderAncestorHeader[]; +} // namespace content_relationship_verification + +#endif // COMPONENTS_CONTENT_RELATIONSHIP_VERIFICATION_RESPONSE_HEADER_VERIFIER_H_
diff --git a/components/digital_asset_links/response_header_verifier_unittest.cc b/components/content_relationship_verification/response_header_verifier_unittest.cc similarity index 88% rename from components/digital_asset_links/response_header_verifier_unittest.cc rename to components/content_relationship_verification/response_header_verifier_unittest.cc index 9f4f65e..8e62414a 100644 --- a/components/digital_asset_links/response_header_verifier_unittest.cc +++ b/components/content_relationship_verification/response_header_verifier_unittest.cc
@@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/digital_asset_links/response_header_verifier.h" +#include "components/content_relationship_verification/response_header_verifier.h" #include "testing/gtest/include/gtest/gtest.h" -namespace digital_asset_links { +namespace content_relationship_verification { TEST(ResponseHeaderVerifier, VerifyEmptyHeader) { EXPECT_TRUE(ResponseHeaderVerifier::Verify("any.package.name", "")); @@ -39,4 +39,4 @@ ResponseHeaderVerifier::Verify("another.package", "*, a.package")); } -} // namespace digital_asset_links +} // namespace content_relationship_verification
diff --git a/components/crash/content/browser/crash_handler_host_linux.cc b/components/crash/content/browser/crash_handler_host_linux.cc index 47b44f24..d1f519f 100644 --- a/components/crash/content/browser/crash_handler_host_linux.cc +++ b/components/crash/content/browser/crash_handler_host_linux.cc
@@ -444,7 +444,8 @@ // Create a temporary file holding the AddressSanitizer report. const base::FilePath log_path = base::FilePath(minidump_filename).ReplaceExtension("log"); - base::WriteFile(log_path, info->asan_report_str, info->asan_report_length); + base::WriteFile(log_path, base::StringPiece(info->asan_report_str, + info->asan_report_length)); #endif // Freed in CrashDumpTask().
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/UrlResponseInfoTest.java b/components/cronet/android/test/javatests/src/org/chromium/net/UrlResponseInfoTest.java index 905633a1..40897cd69 100644 --- a/components/cronet/android/test/javatests/src/org/chromium/net/UrlResponseInfoTest.java +++ b/components/cronet/android/test/javatests/src/org/chromium/net/UrlResponseInfoTest.java
@@ -46,6 +46,7 @@ new UrlResponseInfoImpl(urlChain, httpStatusCode, httpStatusText, allHeadersList, wasCached, negotiatedProtocol, proxyServer, receivedByteCount); Assert.assertEquals(info.getUrlChain(), urlChain); + Assert.assertEquals(info.getUrl(), urlChain.get(urlChain.size() - 1)); try { info.getUrlChain().add("example.com"); Assert.fail("getUrlChain() returned modifyable list.");
diff --git a/components/desks_storage/core/desk_template_conversion.cc b/components/desks_storage/core/desk_template_conversion.cc index 4738c86..f23c09e 100644 --- a/components/desks_storage/core/desk_template_conversion.cc +++ b/components/desks_storage/core/desk_template_conversion.cc
@@ -171,50 +171,37 @@ constexpr int kVersionNum = 1; // Conversion to desk methods. -bool GetString(const base::Value* dict, const char* key, std::string* out) { - const base::Value* value = - dict->FindKeyOfType(key, base::Value::Type::STRING); +bool GetString(const base::Value::Dict& dict, + const char* key, + std::string* out) { + const std::string* value = dict.FindString(key); if (!value) return false; - *out = value->GetString(); + *out = *value; return true; } -bool GetString(const base::Value& dict, const char* key, std::string* out) { - return GetString(&dict, key, out); -} - -bool GetInt(const base::Value* dict, const char* key, int* out) { - const base::Value* value = - dict->FindKeyOfType(key, base::Value::Type::INTEGER); +bool GetInt(const base::Value::Dict& dict, const char* key, int* out) { + absl::optional<int> value = dict.FindInt(key); if (!value) return false; - *out = value->GetInt(); + *out = *value; return true; } -bool GetInt(const base::Value& dict, const char* key, int* out) { - return GetInt(&dict, key, out); -} - -bool GetBool(const base::Value* dict, const char* key, bool* out) { - const base::Value* value = - dict->FindKeyOfType(key, base::Value::Type::BOOLEAN); +bool GetBool(const base::Value::Dict& dict, const char* key, bool* out) { + absl::optional<bool> value = dict.FindBool(key); if (!value) return false; - *out = value->GetBool(); + *out = *value; return true; } -bool GetBool(const base::Value& dict, const char* key, bool* out) { - return GetBool(&dict, key, out); -} - // Get App ID from App proto. -std::string GetJsonAppId(const base::Value& app) { +std::string GetJsonAppId(const base::Value::Dict& app) { std::string app_type; if (!GetString(app, kAppType, &app_type)) return std::string(); // App Type must be specified. @@ -247,20 +234,21 @@ return std::string(); } -// Convert a TabGroupInfo object to a base::Value dictionary. -base::Value ConvertTabGroupInfoToValue( +// Convert a TabGroupInfo object to a base::Value::Dict. +base::Value::Dict ConvertTabGroupInfoToDict( const tab_groups::TabGroupInfo& group_info) { - base::Value tab_group_dict(base::Value::Type::DICT); + base::Value::Dict tab_group_dict; - tab_group_dict.SetIntKey(kTabRangeFirstIndex, group_info.tab_range.start()); - tab_group_dict.SetIntKey(kTabRangeLastIndex, group_info.tab_range.end()); - tab_group_dict.SetStringKey( - kTabGroupTitleKey, base::UTF16ToUTF8(group_info.visual_data.title())); - tab_group_dict.SetStringKey( - kTabGroupColorKey, - tab_groups::TabGroupColorToString(group_info.visual_data.color())); - tab_group_dict.SetBoolKey(kTabGroupIsCollapsed, - group_info.visual_data.is_collapsed()); + tab_group_dict.Set(kTabRangeFirstIndex, + static_cast<int>(group_info.tab_range.start())); + tab_group_dict.Set(kTabRangeLastIndex, + static_cast<int>(group_info.tab_range.end())); + tab_group_dict.Set(kTabGroupTitleKey, + base::UTF16ToUTF8(group_info.visual_data.title())); + tab_group_dict.Set(kTabGroupColorKey, tab_groups::TabGroupColorToString( + group_info.visual_data.color())); + tab_group_dict.Set(kTabGroupIsCollapsed, + group_info.visual_data.is_collapsed()); return tab_group_dict; } @@ -301,8 +289,8 @@ // Constructs a GroupVisualData from value `group_visual_data` IFF all fields // are present and valid in the value parameter. Returns true on success, false // on failure. -bool MakeTabGroupVisualDataFromValue( - const base::Value& tab_group, +bool MakeTabGroupVisualDataFromDict( + const base::Value::Dict& tab_group, tab_groups::TabGroupVisualData* out_visual_data) { std::string tab_group_title; std::string group_color_string; @@ -323,8 +311,8 @@ // Constructs a gfx::Range from value `group_range` IFF all fields are // present and valid in the value parameter. Returns true on success, false on // failure. -bool MakeTabGroupRangeFromValue(const base::Value& tab_group, - gfx::Range* out_range) { +bool MakeTabGroupRangeFromDict(const base::Value::Dict& tab_group, + gfx::Range* out_range) { int32_t range_start; int32_t range_end; if (GetInt(tab_group, kTabRangeFirstIndex, &range_start) && @@ -339,13 +327,13 @@ // Constructs a TabGroupInfo from `tab_group` IFF all fields are present // and valid in the value parameter. Returns true on success, false on failure. absl::optional<tab_groups::TabGroupInfo> MakeTabGroupInfoFromDict( - const base::Value& tab_group) { + const base::Value::Dict& tab_group) { absl::optional<tab_groups::TabGroupInfo> tab_group_info = absl::nullopt; tab_groups::TabGroupVisualData visual_data; gfx::Range range; - if (MakeTabGroupRangeFromValue(tab_group, &range) && - MakeTabGroupVisualDataFromValue(tab_group, &visual_data)) { + if (MakeTabGroupRangeFromDict(tab_group, &range) && + MakeTabGroupVisualDataFromDict(tab_group, &visual_data)) { tab_group_info.emplace(range, visual_data); } @@ -418,7 +406,7 @@ // Convert App JSON to `app_restore::AppLaunchInfo`. std::unique_ptr<app_restore::AppLaunchInfo> ConvertJsonToAppLaunchInfo( - const base::Value& app) { + const base::Value::Dict& app) { int32_t window_id; if (!GetInt(app, kWindowId, &window_id)) return nullptr; @@ -480,11 +468,11 @@ // Fill in the URL list app_launch_info->urls.emplace(); - const base::Value* tabs = app.FindKeyOfType(kTabs, base::Value::Type::LIST); + const base::Value::List* tabs = app.FindList(kTabs); if (tabs) { - for (auto& tab : tabs->GetList()) { + for (auto& tab : *tabs) { std::string url; - if (GetString(tab, kTabUrl, &url)) { + if (GetString(tab.GetDict(), kTabUrl, &url)) { app_launch_info->urls.value().emplace_back(url); } } @@ -492,12 +480,11 @@ // Fill the tab groups app_launch_info->tab_group_infos.emplace(); - const base::Value* tab_groups = - app.FindKeyOfType(kTabGroups, base::Value::Type::LIST); + const base::Value::List* tab_groups = app.FindList(kTabGroups); if (tab_groups) { - for (auto& tab : tab_groups->GetList()) { + for (auto& tab : *tab_groups) { absl::optional<tab_groups::TabGroupInfo> tab_group = - MakeTabGroupInfoFromDict(tab); + MakeTabGroupInfoFromDict(tab.GetDict()); if (tab_group.has_value()) { app_launch_info->tab_group_infos->push_back( std::move(tab_group.value())); @@ -561,38 +548,40 @@ } void FillArcExtraWindowInfoFromJson( - const base::Value& app, + const base::Value::Dict& app, app_restore::WindowInfo::ArcExtraInfo* out_window_info) { - const base::Value* bounds_in_root = app.FindDictKey(kBoundsInRoot); + const base::Value::Dict* bounds_in_root = app.FindDict(kBoundsInRoot); int top; int left; int bounds_width; int bounds_height; - if (bounds_in_root && GetInt(bounds_in_root, kWindowBoundTop, &top) && - GetInt(bounds_in_root, kWindowBoundLeft, &left) && - GetInt(bounds_in_root, kWindowBoundWidth, &bounds_width) && - GetInt(bounds_in_root, kWindowBoundHeight, &bounds_height)) + if (bounds_in_root && GetInt(*bounds_in_root, kWindowBoundTop, &top) && + GetInt(*bounds_in_root, kWindowBoundLeft, &left) && + GetInt(*bounds_in_root, kWindowBoundWidth, &bounds_width) && + GetInt(*bounds_in_root, kWindowBoundHeight, &bounds_height)) { out_window_info->bounds_in_root.emplace(left, top, bounds_width, bounds_height); + } - const base::Value* maximum_size = app.FindDictKey(kMaximumSize); + const base::Value::Dict* maximum_size = app.FindDict(kMaximumSize); int max_width; int max_height; - if (maximum_size && GetInt(maximum_size, kSizeWidth, &max_width) && - GetInt(maximum_size, kSizeHeight, &max_height)) + if (maximum_size && GetInt(*maximum_size, kSizeWidth, &max_width) && + GetInt(*maximum_size, kSizeHeight, &max_height)) { out_window_info->maximum_size.emplace(max_width, max_height); + } - const base::Value* minimum_size = app.FindDictKey(kMinimumSize); + const base::Value::Dict* minimum_size = app.FindDict(kMinimumSize); int min_width; int min_height; - if (minimum_size && GetInt(minimum_size, kSizeWidth, &min_width) && - GetInt(minimum_size, kSizeHeight, &min_height)) { + if (minimum_size && GetInt(*minimum_size, kSizeWidth, &min_width) && + GetInt(*minimum_size, kSizeHeight, &min_height)) { out_window_info->minimum_size.emplace(min_width, min_height); } } // Fill `out_window_info` with information from JSON `app`. -void FillWindowInfoFromJson(const base::Value& app, +void FillWindowInfoFromJson(const base::Value::Dict& app, app_restore::WindowInfo* out_window_info) { std::string window_state; chromeos::WindowStateType cros_window_state = @@ -609,15 +598,15 @@ &out_window_info->arc_extra_info.emplace()); } - const base::Value* window_bound = app.FindDictKey(kWindowBound); + const base::Value::Dict* window_bound = app.FindDict(kWindowBound); int top; int left; int width; int height; - if (window_bound && GetInt(window_bound, kWindowBoundTop, &top) && - GetInt(window_bound, kWindowBoundLeft, &left) && - GetInt(window_bound, kWindowBoundWidth, &width) && - GetInt(window_bound, kWindowBoundHeight, &height)) { + if (window_bound && GetInt(*window_bound, kWindowBoundTop, &top) && + GetInt(*window_bound, kWindowBoundLeft, &left) && + GetInt(*window_bound, kWindowBoundWidth, &width) && + GetInt(*window_bound, kWindowBoundHeight, &height)) { out_window_info->current_bounds.emplace(left, top, width, height); } @@ -658,20 +647,22 @@ const base::Value* apps = desk->FindListKey(kApps); if (apps) { for (const auto& app : apps->GetList()) { + const base::Value::Dict& app_dict = app.GetDict(); std::unique_ptr<app_restore::AppLaunchInfo> app_launch_info = - ConvertJsonToAppLaunchInfo(app); + ConvertJsonToAppLaunchInfo(app_dict); if (!app_launch_info) continue; // Skip unsupported app. int window_id; - if (!GetInt(app, kWindowId, &window_id)) + if (!GetInt(app_dict, kWindowId, &window_id)) { return nullptr; + } const std::string app_id = app_launch_info->app_id; restore_data->AddAppLaunchInfo(std::move(app_launch_info)); app_restore::WindowInfo app_window_info; - FillWindowInfoFromJson(app, &app_window_info); + FillWindowInfoFromJson(app_dict, &app_window_info); restore_data->ModifyWindowInfo(app_id, window_id, app_window_info); } @@ -905,7 +896,7 @@ base::Value::List tab_groups_value; for (const auto& tab_group : app->tab_group_infos.value()) { - tab_groups_value.Append(ConvertTabGroupInfoToValue(tab_group)); + tab_groups_value.Append(ConvertTabGroupInfoToDict(tab_group)); } app_data.Set(kTabGroups, std::move(tab_groups_value)); @@ -1941,6 +1932,8 @@ if (!policy_json.is_dict()) return nullptr; + const base::Value::Dict& policy_json_dict = policy_json.GetDict(); + int version; std::string uuid_str; std::string name; @@ -1949,16 +1942,17 @@ int64_t created_time_usec; int64_t updated_time_usec; const base::Value* desk = policy_json.FindDictKey(kDesk); - if (!desk || !GetInt(policy_json, kVersion, &version) || - !GetString(policy_json, kUuid, &uuid_str) || - !GetString(policy_json, kName, &name) || - !GetString(policy_json, kCreatedTime, &created_time_usec_str) || + if (!desk || !GetInt(policy_json_dict, kVersion, &version) || + !GetString(policy_json_dict, kUuid, &uuid_str) || + !GetString(policy_json_dict, kName, &name) || + !GetString(policy_json_dict, kCreatedTime, &created_time_usec_str) || !base::StringToInt64(created_time_usec_str, &created_time_usec) || - !GetString(policy_json, kUpdatedTime, &updated_time_usec_str) || + !GetString(policy_json_dict, kUpdatedTime, &updated_time_usec_str) || !base::StringToInt64(updated_time_usec_str, &updated_time_usec) || name.empty() || created_time_usec_str.empty() || - updated_time_usec_str.empty()) + updated_time_usec_str.empty()) { return nullptr; + } base::GUID uuid = base::GUID::ParseCaseInsensitive(uuid_str); if (!uuid.is_valid()) @@ -1966,7 +1960,7 @@ // Set default value for the desk type to template. std::string desk_type_string; - if (!GetString(policy_json, kDeskType, &desk_type_string)) { + if (!GetString(policy_json_dict, kDeskType, &desk_type_string)) { desk_type_string = kDeskTypeTemplate; } else if (!IsValidDeskTemplateType(desk_type_string)) { return nullptr; @@ -1988,19 +1982,18 @@ base::Value SerializeDeskTemplateAsPolicy(const ash::DeskTemplate* desk, apps::AppRegistryCache* app_cache) { - base::Value desk_dict(base::Value::Type::DICT); - desk_dict.SetKey(kVersion, base::Value(kVersionNum)); - desk_dict.SetKey(kUuid, base::Value(desk->uuid().AsLowercaseString())); - desk_dict.SetKey(kName, base::Value(desk->template_name())); - desk_dict.SetKey(kCreatedTime, base::TimeToValue(desk->created_time())); - desk_dict.SetKey(kUpdatedTime, base::TimeToValue(desk->GetLastUpdatedTime())); - desk_dict.SetKey(kDeskType, - base::Value(SerializeDeskTypeAsString(desk->type()))); + base::Value::Dict desk_dict; + desk_dict.Set(kVersion, kVersionNum); + desk_dict.Set(kUuid, desk->uuid().AsLowercaseString()); + desk_dict.Set(kName, desk->template_name()); + desk_dict.Set(kCreatedTime, base::TimeToValue(desk->created_time())); + desk_dict.Set(kUpdatedTime, base::TimeToValue(desk->GetLastUpdatedTime())); + desk_dict.Set(kDeskType, SerializeDeskTypeAsString(desk->type())); - desk_dict.SetKey( + desk_dict.Set( kDesk, ConvertRestoreDataToValue(desk->desk_restore_data(), app_cache)); - return desk_dict; + return base::Value(std::move(desk_dict)); } std::unique_ptr<DeskTemplate> FromSyncProto(
diff --git a/components/digital_asset_links/README.md b/components/digital_asset_links/README.md deleted file mode 100644 index d619dd6..0000000 --- a/components/digital_asset_links/README.md +++ /dev/null
@@ -1,6 +0,0 @@ -# Digital asset links - -This component contains utilities to facilitate making requests of the -DigitalAssetLinks API on the web. - -See [documentation](https://developers.google.com/digital-asset-links/v1/getting-started).
diff --git a/components/digital_asset_links/android/BUILD.gn b/components/digital_asset_links/android/BUILD.gn deleted file mode 100644 index d29572a..0000000 --- a/components/digital_asset_links/android/BUILD.gn +++ /dev/null
@@ -1,41 +0,0 @@ -# Copyright 2022 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//build/config/android/rules.gni") - -android_library("java") { - sources = [ - "java/src/org/chromium/components/digital_asset_links/OriginVerificationScheduler.java", - "java/src/org/chromium/components/digital_asset_links/OriginVerifier.java", - "java/src/org/chromium/components/digital_asset_links/OriginVerifierHelper.java", - "java/src/org/chromium/components/digital_asset_links/Relationship.java", - "java/src/org/chromium/components/digital_asset_links/VerificationResultStore.java", - ] - deps = [ - "//base:base_java", - "//base:jni_java", - "//build/android:build_java", - "//components/digital_asset_links:java", - "//components/embedder_support/android:util_java", - "//content/public/android:content_java", - "//third_party/androidx:androidx_annotation_annotation_java", - ] - annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ] -} - -robolectric_library("junit_test_support") { - sources = [ "java/src/org/chromium/components/digital_asset_links/OriginVerifierUnitTestSupport.java" ] - deps = [ - ":java", - "//components/embedder_support/android:util_java", - "//third_party/androidx:androidx_browser_browser_java", - "//third_party/mockito:mockito_java", - ] -} - -generate_jni("jni_headers") { - sources = [ - "java/src/org/chromium/components/digital_asset_links/OriginVerifier.java", - ] -}
diff --git a/components/digital_asset_links/digital_asset_links_constants.cc b/components/digital_asset_links/digital_asset_links_constants.cc deleted file mode 100644 index 3ef25ab..0000000 --- a/components/digital_asset_links/digital_asset_links_constants.cc +++ /dev/null
@@ -1,15 +0,0 @@ -// Copyright 2023 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/digital_asset_links/digital_asset_links_constants.h" - -#include "net/base/net_errors.h" - -namespace digital_asset_links { - -const char kCustomCancelReasonForURLLoader[] = "DigitalAssetLinks"; - -const int kNetErrorCodeForDigitalAssetLinks = net::ERR_ACCESS_DENIED; - -} // namespace digital_asset_links
diff --git a/components/digital_asset_links/digital_asset_links_constants.h b/components/digital_asset_links/digital_asset_links_constants.h deleted file mode 100644 index 5c34f0e..0000000 --- a/components/digital_asset_links/digital_asset_links_constants.h +++ /dev/null
@@ -1,21 +0,0 @@ -// Copyright 2023 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_DIGITAL_ASSET_LINKS_DIGITAL_ASSET_LINKS_CONSTANTS_H_ -#define COMPONENTS_DIGITAL_ASSET_LINKS_DIGITAL_ASSET_LINKS_CONSTANTS_H_ - -namespace digital_asset_links { - -// When a network::mojom::URLLoader is cancelled because of digital asset link -// verification, this custom cancellation reason could be used to notify the -// implementation side. Please see -// network::mojom::URLLoader::kClientDisconnectReason for more details. -extern const char kCustomCancelReasonForURLLoader[]; - -// error_code to use when Safe Browsing blocks a request. -extern const int kNetErrorCodeForDigitalAssetLinks; - -} // namespace digital_asset_links - -#endif // COMPONENTS_SAFE_BROWSING_CORE_COMMON_SAFEBROWSING_CONSTANTS_H_
diff --git a/components/digital_asset_links/response_header_verifier.h b/components/digital_asset_links/response_header_verifier.h deleted file mode 100644 index dd1c98a..0000000 --- a/components/digital_asset_links/response_header_verifier.h +++ /dev/null
@@ -1,23 +0,0 @@ -// Copyright 2023 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_DIGITAL_ASSET_LINKS_RESPONSE_HEADER_VERIFIER_H_ -#define COMPONENTS_DIGITAL_ASSET_LINKS_RESPONSE_HEADER_VERIFIER_H_ - -#include <string> - -namespace digital_asset_links { - -class ResponseHeaderVerifier { - public: - // Verify if the provided |package_name| is verified via the embedder - // ancestor header. - static bool Verify(const std::string& package_name, - const std::string& embedder_ancestors_header_value); -}; - -extern const char kEmbedderAncestorHeader[]; -} // namespace digital_asset_links - -#endif // COMPONENTS_DIGITAL_ASSET_LINKS_RESPONSE_HEADER_VERIFIER_H_
diff --git a/components/exo/shell_surface.cc b/components/exo/shell_surface.cc index 9a36fce..95850270 100644 --- a/components/exo/shell_surface.cc +++ b/components/exo/shell_surface.cc
@@ -540,6 +540,12 @@ UpdateShadow(); } + if (root_surface() && window_state->GetStateType() != old_type && + (window_state->GetStateType() == chromeos::WindowStateType::kFullscreen || + old_type == chromeos::WindowStateType::kFullscreen)) { + root_surface()->OnFullscreenStateChanged(window_state->IsFullscreen()); + } + // Re-enable animations if they were disabled in pre state change handler. animations_disabler_.reset(); window_state_is_changing_ = false;
diff --git a/components/exo/shell_surface_base.cc b/components/exo/shell_surface_base.cc index c6dfeae..814080e 100644 --- a/components/exo/shell_surface_base.cc +++ b/components/exo/shell_surface_base.cc
@@ -1540,6 +1540,7 @@ SetPip(); root_surface()->OnDeskChanged(GetWindowDeskStateChanged(window)); + root_surface()->OnFullscreenStateChanged(widget_->IsFullscreen()); WMHelper::GetInstance()->NotifyExoWindowCreated(widget_->GetNativeWindow()); }
diff --git a/components/exo/surface.cc b/components/exo/surface.cc index 514c5b12..673fcd1 100644 --- a/components/exo/surface.cc +++ b/components/exo/surface.cc
@@ -999,7 +999,6 @@ cached_state_.buffer.reset(); } state_.rounded_corners_bounds = cached_state_.rounded_corners_bounds; - state_.overlay_priority_hint = cached_state_.overlay_priority_hint; state_.clip_rect = cached_state_.clip_rect; state_.surface_transform = cached_state_.surface_transform; state_.acquire_fence = std::move(cached_state_.acquire_fence); @@ -1008,6 +1007,12 @@ if (state_.basic_state.alpha) needs_update_resource_ = true; } + + // The overlay priority hint can get set before any buffer gets + // allocated/attached and may influence the format/modifier selection for + // these. + UpdateOverlayPriorityHint(cached_state_.overlay_priority_hint); + // Either we didn't have a pending acquire fence, or we had one along with // a new buffer, and it was already moved to state_.acquire_fence. Note that // it is a commit-time client error to commit a fence without a buffer. @@ -1343,6 +1348,17 @@ } } +void Surface::UpdateOverlayPriorityHint(OverlayPriority overlay_priority_hint) { + if (state_.overlay_priority_hint == overlay_priority_hint) { + return; + } + + state_.overlay_priority_hint = overlay_priority_hint; + for (SurfaceObserver& observer : observers_) { + observer.OnOverlayPriorityHintChanged(overlay_priority_hint); + } +} + // Try to share the |SharedQuadState| (sqs) when a single layer can be // reconstructed. This is important for performance reasons in the occlusion // code and correctness in the per edge anti-alias code. @@ -1796,4 +1812,13 @@ } } +void Surface::OnFullscreenStateChanged(bool fullscreen) { + for (SurfaceObserver& observer : observers_) { + observer.OnFullscreenStateChanged(fullscreen); + } + for (const auto& [surface, point] : sub_surfaces_) { + surface->OnFullscreenStateChanged(fullscreen); + } +} + } // namespace exo
diff --git a/components/exo/surface.h b/components/exo/surface.h index a670aa9..e77bbdf3 100644 --- a/components/exo/surface.h +++ b/components/exo/surface.h
@@ -454,6 +454,13 @@ // A negative number removes it. void SetClientAccessibilityId(int id); + // Inform observers and subsurfaces about new fullscreen state + void OnFullscreenStateChanged(bool fullscreen); + + OverlayPriority GetOverlayPriorityHint() { + return state_.overlay_priority_hint; + } + private: struct State { State(); @@ -575,6 +582,9 @@ // Updates buffer_transform_ to match the current buffer parameters. void UpdateBufferTransform(bool y_invert); + // Update state_.overlay_priority_hint and notify observers + void UpdateOverlayPriorityHint(OverlayPriority overlay_priority_hint); + // Puts the current surface into a draw quad, and appends the draw quads into // the |frame|. void AppendContentsToFrame(const gfx::PointF& origin,
diff --git a/components/exo/surface_observer.h b/components/exo/surface_observer.h index 5121d6f..e9459b3 100644 --- a/components/exo/surface_observer.h +++ b/components/exo/surface_observer.h
@@ -14,6 +14,7 @@ namespace exo { class Surface; +enum class OverlayPriority; // Observers can listen to various events on the Surfaces. class SurfaceObserver { @@ -59,6 +60,11 @@ // Called when tooltip is hidden. virtual void OnTooltipHidden(Surface* surface) {} + virtual void OnFullscreenStateChanged(bool fullscreen) {} + + virtual void OnOverlayPriorityHintChanged( + OverlayPriority overlay_priority_hint) {} + protected: virtual ~SurfaceObserver() {} };
diff --git a/components/exo/wayland/wayland_dmabuf_feedback_manager.cc b/components/exo/wayland/wayland_dmabuf_feedback_manager.cc index 9aaa8ef0..f9335fd 100644 --- a/components/exo/wayland/wayland_dmabuf_feedback_manager.cc +++ b/components/exo/wayland/wayland_dmabuf_feedback_manager.cc
@@ -14,6 +14,9 @@ #include "base/functional/bind.h" #include "components/exo/buffer.h" #include "components/exo/display.h" +#include "components/exo/shell_surface_base.h" +#include "components/exo/shell_surface_util.h" +#include "components/exo/surface.h" #include "components/exo/wayland/server_util.h" #include "components/viz/common/gpu/context_provider.h" #include "ui/aura/env.h" @@ -195,6 +198,8 @@ ~WaylandDmabufSurfaceFeedback() override; void OnSurfaceDestroying(Surface* surface) override { + feedback_manager_->RemoveSurfaceFromScanoutCandidates( + surface_, ScanoutReasonFlags::kNone); feedback_manager_->RemoveSurfaceFeedback(surface_); } @@ -204,6 +209,27 @@ feedback_manager_->MaybeResendFeedback(surface_); } + void OnFullscreenStateChanged(bool fullscreen) override { + if (fullscreen) { + feedback_manager_->AddSurfaceToScanoutCandidates( + surface_, ScanoutReasonFlags::kFullscreen); + } else { + feedback_manager_->RemoveSurfaceFromScanoutCandidates( + surface_, ScanoutReasonFlags::kFullscreen); + } + } + + void OnOverlayPriorityHintChanged( + OverlayPriority overlay_priority_hint) override { + if (overlay_priority_hint == OverlayPriority::REQUIRED) { + feedback_manager_->AddSurfaceToScanoutCandidates( + surface_, ScanoutReasonFlags::kOverlayPriorityHint); + } else { + feedback_manager_->RemoveSurfaceFromScanoutCandidates( + surface_, ScanoutReasonFlags::kOverlayPriorityHint); + } + } + void AddSurfaceFeedbackRef( WaylandDmabufSurfaceFeedbackResourceWrapper* surface_feedback_ref) { surface_feedback_refs_.insert(surface_feedback_ref); @@ -402,6 +428,20 @@ std::make_unique<WaylandDmabufFeedback>(default_feedback_); auto new_surface_feedback = std::make_unique<WaylandDmabufSurfaceFeedback>( this, surface, std::move(defaut_feedback_copy)); + + ShellSurfaceBase* shell_surface_base = nullptr; + for (auto* window = surface->window(); window && !shell_surface_base; + window = window->parent()) { + shell_surface_base = GetShellSurfaceBaseForWindow(window); + } + if (shell_surface_base) { + bool fullscreen = shell_surface_base->GetWidget()->IsFullscreen(); + new_surface_feedback->OnFullscreenStateChanged(fullscreen); + } + + new_surface_feedback->OnOverlayPriorityHintChanged( + surface->GetOverlayPriorityHint()); + it = surface_feedbacks_.emplace_hint(it, surface, std::move(new_surface_feedback)); } @@ -431,23 +471,31 @@ } void WaylandDmabufFeedbackManager::AddSurfaceToScanoutCandidates( - Surface* surface) { - if (base::Contains(scanout_candidates_, surface)) + Surface* surface, + ScanoutReasonFlags reason) { + auto search = scanout_candidates_.find(surface); + if (search != scanout_candidates_.end()) { + search->second = static_cast<ScanoutReasonFlags>( + static_cast<uint32_t>(search->second) | static_cast<uint32_t>(reason)); return; + } - scanout_candidates_.emplace(surface); + scanout_candidates_.emplace(surface, reason); - if (!base::Contains(surface_feedbacks_, surface)) + if (!base::Contains(surface_feedbacks_, surface)) { return; + } const auto& surface_feedback = surface_feedbacks_[surface]; auto* feedback = surface_feedback->GetFeedback(); - if (feedback->GetScanoutTranche()) + if (feedback->GetScanoutTranche()) { return; + } feedback->MaybeAddScanoutTranche(surface); - if (!feedback->GetScanoutTranche()) + if (!feedback->GetScanoutTranche()) { return; + } for (auto* feedback_ref : surface_feedback->GetFeedbackRefs()) { SendFeedback(feedback, feedback_ref->GetFeedbackResource()); @@ -455,19 +503,31 @@ } void WaylandDmabufFeedbackManager::RemoveSurfaceFromScanoutCandidates( - Surface* surface) { - if (!base::Contains(scanout_candidates_, surface)) + Surface* surface, + ScanoutReasonFlags reason) { + auto search = scanout_candidates_.find(surface); + if (search == scanout_candidates_.end()) { return; + } - scanout_candidates_.erase(surface); - - if (!base::Contains(surface_feedbacks_, surface)) + search->second = static_cast<ScanoutReasonFlags>( + static_cast<uint32_t>(search->second) & ~static_cast<uint32_t>(reason)); + if (search->second == ScanoutReasonFlags::kNone || + reason == ScanoutReasonFlags::kNone) { + scanout_candidates_.erase(surface); + } else { return; + } + + if (!base::Contains(surface_feedbacks_, surface)) { + return; + } const auto& surface_feedback = surface_feedbacks_[surface]; auto* feedback = surface_feedback->GetFeedback(); - if (!feedback->GetScanoutTranche()) + if (!feedback->GetScanoutTranche()) { return; + } feedback->ClearScanoutTranche(); for (auto* feedback_ref : surface_feedback->GetFeedbackRefs()) {
diff --git a/components/exo/wayland/wayland_dmabuf_feedback_manager.h b/components/exo/wayland/wayland_dmabuf_feedback_manager.h index 741ff051..26145cb9 100644 --- a/components/exo/wayland/wayland_dmabuf_feedback_manager.h +++ b/components/exo/wayland/wayland_dmabuf_feedback_manager.h
@@ -7,8 +7,8 @@ #include <stdint.h> #include <sys/types.h> +#include <map> #include <memory> -#include <set> #include "base/containers/flat_map.h" #include "base/memory/read_only_shared_memory_region.h" @@ -32,6 +32,12 @@ using IndexedDrmFormatsAndModifiers = base::flat_map<uint32_t, base::flat_map<size_t, uint64_t>>; +enum class ScanoutReasonFlags : uint32_t { + kNone = 0, + kFullscreen = 1, + kOverlayPriorityHint = 2 +}; + class WaylandDmabufFeedbackManager { public: explicit WaylandDmabufFeedbackManager(Display* display); @@ -56,8 +62,10 @@ wl_resource* surface_resource); void RemoveSurfaceFeedback(Surface* surface); - void AddSurfaceToScanoutCandidates(Surface* surface); - void RemoveSurfaceFromScanoutCandidates(Surface* surface); + void AddSurfaceToScanoutCandidates(Surface* surface, + ScanoutReasonFlags reason); + void RemoveSurfaceFromScanoutCandidates(Surface* surface, + ScanoutReasonFlags reason); void MaybeResendFeedback(Surface* surface); private: @@ -72,7 +80,7 @@ std::unique_ptr<WaylandDmabufFeedback> default_feedback_; base::flat_map<Surface*, std::unique_ptr<WaylandDmabufSurfaceFeedback>> surface_feedbacks_; - std::set<Surface*> scanout_candidates_; + std::map<Surface*, ScanoutReasonFlags> scanout_candidates_; }; } // namespace wayland
diff --git a/components/feed/core/v2/BUILD.gn b/components/feed/core/v2/BUILD.gn index b1d3fb4..8d372c1 100644 --- a/components/feed/core/v2/BUILD.gn +++ b/components/feed/core/v2/BUILD.gn
@@ -71,6 +71,7 @@ "public/public_types.cc", "public/stream_type.cc", "public/unread_content_observer.cc", + "public/web_feed_subscriptions.cc", "request_throttler.cc", "request_throttler.h", "scheduling.cc",
diff --git a/components/feed/core/v2/public/test/stub_web_feed_subscriptions.h b/components/feed/core/v2/public/test/stub_web_feed_subscriptions.h index 3b51199..e208cf9f 100644 --- a/components/feed/core/v2/public/test/stub_web_feed_subscriptions.h +++ b/components/feed/core/v2/public/test/stub_web_feed_subscriptions.h
@@ -45,6 +45,9 @@ void QueryWebFeed( const GURL& gurl, base::OnceCallback<void(QueryWebFeedResult)> callback) override {} + void QueryWebFeedId( + const std::string& web_feed_id, + base::OnceCallback<void(QueryWebFeedResult)> callback) override {} }; } // namespace feed
diff --git a/components/feed/core/v2/public/web_feed_subscriptions.cc b/components/feed/core/v2/public/web_feed_subscriptions.cc new file mode 100644 index 0000000..e625b4e --- /dev/null +++ b/components/feed/core/v2/public/web_feed_subscriptions.cc
@@ -0,0 +1,14 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/feed/core/v2/public/web_feed_subscriptions.h" + +namespace feed { + +WebFeedSubscriptions::QueryWebFeedResult::QueryWebFeedResult() = default; +WebFeedSubscriptions::QueryWebFeedResult::QueryWebFeedResult( + const QueryWebFeedResult& query_web_feed_result) = default; +WebFeedSubscriptions::QueryWebFeedResult::~QueryWebFeedResult() = default; + +} // namespace feed \ No newline at end of file
diff --git a/components/feed/core/v2/public/web_feed_subscriptions.h b/components/feed/core/v2/public/web_feed_subscriptions.h index cd6fc47f..a140869 100644 --- a/components/feed/core/v2/public/web_feed_subscriptions.h +++ b/components/feed/core/v2/public/web_feed_subscriptions.h
@@ -28,10 +28,17 @@ feedwire::webfeed::WebFeedChangeReason change_reason; }; struct QueryWebFeedResult { + QueryWebFeedResult(); + QueryWebFeedResult(const QueryWebFeedResult& query_web_feed_result); + ~QueryWebFeedResult(); WebFeedQueryRequestStatus request_status = WebFeedQueryRequestStatus::kUnknown; // The id of the queried web feed. std::string web_feed_id; + // The title of the queried web feed. + std::string title; + // The url of the queried web feed. + std::string url; }; // Follow a web feed given information about a web page. Calls `callback` when // complete. The callback parameter reports whether the url is now considered @@ -118,6 +125,11 @@ const GURL& url, base::OnceCallback<void(QueryWebFeedResult)> callback) = 0; + // return the WebFeed Id based on the id provided. + virtual void QueryWebFeedId( + const std::string& web_feed_id, + base::OnceCallback<void(QueryWebFeedResult)> callback) = 0; + // Output debugging information for snippets-internals. virtual void DumpStateForDebugging(std::ostream& ss) {} };
diff --git a/components/feed/core/v2/web_feed_subscription_coordinator.cc b/components/feed/core/v2/web_feed_subscription_coordinator.cc index 80df642c..2a31e7a 100644 --- a/components/feed/core/v2/web_feed_subscription_coordinator.cc +++ b/components/feed/core/v2/web_feed_subscription_coordinator.cc
@@ -985,11 +985,30 @@ base::Unretained(this), std::move(callback)))); } +void WebFeedSubscriptionCoordinator::QueryWebFeedId( + const std::string& id, + base::OnceCallback<void(QueryWebFeedResult)> callback) { + // TODO(crbug/1409701) Combine subscription status into result callback. This + // would require binding a start call via WithModel and updating the local + // state to match the result from the server, + QueryWebFeedTask::Request request; + request.web_feed_id = id; + + feed_stream_->GetTaskQueue().AddTask( + FROM_HERE, + std::make_unique<QueryWebFeedTask>( + feed_stream_, token_generator_.Token(), std::move(request), + base::BindOnce(&WebFeedSubscriptionCoordinator::QueryWebFeedComplete, + base::Unretained(this), std::move(callback)))); +} + void WebFeedSubscriptionCoordinator::QueryWebFeedComplete( base::OnceCallback<void(QueryWebFeedResult)> callback, QueryWebFeedResult result) { QueryWebFeedResult callback_result; callback_result.web_feed_id = result.web_feed_id; + callback_result.url = result.url; + callback_result.title = result.title; callback_result.request_status = result.request_status; feed_stream_->GetMetricsReporter().OnQueryAttempt(callback_result); std::move(callback).Run(std::move(callback_result));
diff --git a/components/feed/core/v2/web_feed_subscription_coordinator.h b/components/feed/core/v2/web_feed_subscription_coordinator.h index e1f1031..dada996d 100644 --- a/components/feed/core/v2/web_feed_subscription_coordinator.h +++ b/components/feed/core/v2/web_feed_subscription_coordinator.h
@@ -84,6 +84,9 @@ void QueryWebFeed( const GURL& url, base::OnceCallback<void(QueryWebFeedResult)> callback) override; + void QueryWebFeedId( + const std::string& web_feed_id, + base::OnceCallback<void(QueryWebFeedResult)> callback) override; // Types / functions exposed for task implementations.
diff --git a/components/feed/core/v2/web_feed_subscriptions/query_web_feed_task.cc b/components/feed/core/v2/web_feed_subscriptions/query_web_feed_task.cc index 1b82a51b..e650538 100644 --- a/components/feed/core/v2/web_feed_subscriptions/query_web_feed_task.cc +++ b/components/feed/core/v2/web_feed_subscriptions/query_web_feed_task.cc
@@ -27,6 +27,7 @@ request_(std::move(request)), callback_(std::move(callback)) { url_ = request_.web_feed_url; + web_feed_id_ = request_.web_feed_id; } QueryWebFeedTask::~QueryWebFeedTask() = default; @@ -47,8 +48,11 @@ feedwire::webfeed::QueryWebFeedRequest request; SetConsistencyToken(request, stream_->GetMetadata().consistency_token()); - request.mutable_web_feed_uris()->set_web_page_uri(url_.spec()); - + if (!web_feed_id_.empty()) { + request.set_name(web_feed_id_); + } else { + request.mutable_web_feed_uris()->set_web_page_uri(url_.spec()); + } stream_->GetNetwork().SendApiRequest<QueryWebFeedDiscoverApi>( request, stream_->GetAccountInfo(), stream_->GetSignedInRequestMetadata(), base::BindOnce(&QueryWebFeedTask::RequestComplete, @@ -76,6 +80,8 @@ WebFeedSubscriptions::QueryWebFeedResult result; result.request_status = status; result.web_feed_id = queried_web_feed_info_.web_feed_id(); + result.title = queried_web_feed_info_.title(); + result.url = queried_web_feed_info_.visit_uri(); std::move(callback_).Run(std::move(result)); TaskComplete(); }
diff --git a/components/feed/core/v2/web_feed_subscriptions/query_web_feed_task.h b/components/feed/core/v2/web_feed_subscriptions/query_web_feed_task.h index 5f484ef..fc20263 100644 --- a/components/feed/core/v2/web_feed_subscriptions/query_web_feed_task.h +++ b/components/feed/core/v2/web_feed_subscriptions/query_web_feed_task.h
@@ -25,6 +25,7 @@ public: struct Request { GURL web_feed_url; + std::string web_feed_id; }; QueryWebFeedTask( FeedStream* stream, @@ -51,6 +52,7 @@ WebFeedSubscriptions::QueryWebFeedResult result_; GURL url_; + std::string web_feed_id_; }; } // namespace feed
diff --git a/components/feedback/feedback_util.cc b/components/feedback/feedback_util.cc index 22e0d2cb..0cc7224 100644 --- a/components/feedback/feedback_util.cc +++ b/components/feedback/feedback_util.cc
@@ -35,8 +35,7 @@ // another temporary file to receive the zip file in. if (!temp_dir.CreateUniqueTempDir()) return false; - if (base::WriteFile(temp_dir.GetPath().Append(filename), data.c_str(), - data.size()) == -1) { + if (!base::WriteFile(temp_dir.GetPath().Append(filename), data)) { return false; }
diff --git a/components/installedapp/android/BUILD.gn b/components/installedapp/android/BUILD.gn index e5212eb3c..852ad7c 100644 --- a/components/installedapp/android/BUILD.gn +++ b/components/installedapp/android/BUILD.gn
@@ -8,7 +8,7 @@ sources = [ "installed_app_verifier.cc" ] deps = [ "//base", - "//components/digital_asset_links", + "//components/content_relationship_verification", "//content/public/browser", ] public_deps = [ ":jni_headers" ]
diff --git a/components/installedapp/android/DEPS b/components/installedapp/android/DEPS index 894166b..28ce449 100644 --- a/components/installedapp/android/DEPS +++ b/components/installedapp/android/DEPS
@@ -1,6 +1,6 @@ include_rules = [ "+base", - "+components/digital_asset_links", + "+components/content_relationship_verification", "+components/embedder_support/android/browser_context", "+components/embedder_support/android/java/src/org/chromium/components/embedder_support/browser_context/BrowserContextHandle.java", "+components/webapk/android/libs/client",
diff --git a/components/installedapp/android/installed_app_verifier.cc b/components/installedapp/android/installed_app_verifier.cc index e8a6789..9ab16f2 100644 --- a/components/installedapp/android/installed_app_verifier.cc +++ b/components/installedapp/android/installed_app_verifier.cc
@@ -8,7 +8,7 @@ #include "base/android/callback_android.h" #include "base/android/jni_android.h" #include "base/android/jni_string.h" -#include "components/digital_asset_links/digital_asset_links_handler.h" +#include "components/content_relationship_verification/digital_asset_links_handler.h" #include "components/installedapp/android/jni_headers/InstalledAppProviderImpl_jni.h" #include "content/public/browser/android/browser_context_handle.h" #include "content/public/browser/browser_context.h" @@ -19,11 +19,13 @@ namespace { void DidGetResult( - std::unique_ptr<digital_asset_links::DigitalAssetLinksHandler> handler, + std::unique_ptr<content_relationship_verification::DigitalAssetLinksHandler> + handler, base::OnceCallback<void(bool)> callback, - digital_asset_links::RelationshipCheckResult result) { + content_relationship_verification::RelationshipCheckResult result) { std::move(callback).Run( - result == digital_asset_links::RelationshipCheckResult::kSuccess); + result == + content_relationship_verification::RelationshipCheckResult::kSuccess); } } // namespace @@ -45,10 +47,10 @@ base::BindOnce(&base::android::RunBooleanCallbackAndroid, base::android::ScopedJavaGlobalRef<jobject>(jcallback)); - auto handler = - std::make_unique<digital_asset_links::DigitalAssetLinksHandler>( - browser_context->GetDefaultStoragePartition() - ->GetURLLoaderFactoryForBrowserProcess()); + auto handler = std::make_unique< + content_relationship_verification::DigitalAssetLinksHandler>( + browser_context->GetDefaultStoragePartition() + ->GetURLLoaderFactoryForBrowserProcess()); auto* handler_ptr = handler.get(); // |handler| is owned by the callback, so it will be valid until the execution
diff --git a/components/metrics/data_use_tracker.cc b/components/metrics/data_use_tracker.cc index 362a3d575..68f5e7e2 100644 --- a/components/metrics/data_use_tracker.cc +++ b/components/metrics/data_use_tracker.cc
@@ -123,14 +123,15 @@ const base::Time current_date = GetCurrentMeasurementDate(); const base::Time week_ago = current_date - base::Days(7); - base::Value user_pref_new_dict{base::Value::Type::DICT}; + base::Value::Dict user_pref_new_dict; for (const auto it : user_pref_dict) { base::Time key_date; if (base::Time::FromUTCString(it.first.c_str(), &key_date) && - key_date > week_ago) - user_pref_new_dict.SetPath(it.first, it.second.Clone()); + key_date > week_ago) { + user_pref_new_dict.Set(it.first, it.second.Clone()); + } } - local_state_->Set(pref_name, user_pref_new_dict); + local_state_->SetDict(pref_name, std::move(user_pref_new_dict)); } // Note: We compute total data use regardless of what is the current date. In
diff --git a/components/metrics/generate_expired_histograms_array.gni b/components/metrics/generate_expired_histograms_array.gni index d3c34904e..a7e2b36 100644 --- a/components/metrics/generate_expired_histograms_array.gni +++ b/components/metrics/generate_expired_histograms_array.gni
@@ -63,6 +63,7 @@ "//tools/metrics/histograms/metadata/cookie/histograms.xml", "//tools/metrics/histograms/metadata/cras/histograms.xml", "//tools/metrics/histograms/metadata/cros/histograms.xml", + "//tools/metrics/histograms/metadata/cros_audio/histograms.xml", "//tools/metrics/histograms/metadata/cros_ml/histograms.xml", "//tools/metrics/histograms/metadata/cross_device/histograms.xml", "//tools/metrics/histograms/metadata/crostini/histograms.xml",
diff --git a/components/omnibox/browser/BUILD.gn b/components/omnibox/browser/BUILD.gn index 4a6febc..091113eb 100644 --- a/components/omnibox/browser/BUILD.gn +++ b/components/omnibox/browser/BUILD.gn
@@ -715,6 +715,7 @@ if (build_with_tflite_lib) { sources += [ "autocomplete_scoring_model_executor_unittest.cc", + "autocomplete_scoring_model_handler_unittest.cc", "on_device_tail_model_executor_unittest.cc", ] } @@ -733,6 +734,8 @@ "//components/ntp_tiles:ntp_tiles", "//components/omnibox/common", "//components/open_from_clipboard:test_support", + "//components/optimization_guide/core:test_support", + "//components/optimization_guide/proto:optimization_guide_proto", "//components/prefs:test_support", "//components/search", "//components/search_engines",
diff --git a/components/omnibox/browser/autocomplete_scoring_model_handler.cc b/components/omnibox/browser/autocomplete_scoring_model_handler.cc index 7feb8bc..8ded5cd 100644 --- a/components/omnibox/browser/autocomplete_scoring_model_handler.cc +++ b/components/omnibox/browser/autocomplete_scoring_model_handler.cc
@@ -4,29 +4,66 @@ #include "components/omnibox/browser/autocomplete_scoring_model_handler.h" +#include <cmath> #include <memory> +#include "base/logging.h" #include "base/memory/scoped_refptr.h" #include "base/task/sequenced_task_runner.h" #include "components/omnibox/browser/autocomplete_scoring_model_executor.h" #include "components/optimization_guide/core/model_handler.h" #include "components/optimization_guide/core/optimization_guide_model_provider.h" +#include "components/optimization_guide/proto/autocomplete_scoring_model_metadata.pb.h" #include "components/optimization_guide/proto/models.pb.h" #include "third_party/abseil-cpp/absl/types/optional.h" using ModelInput = AutocompleteScoringModelExecutor::ModelInput; using ModelOutput = AutocompleteScoringModelExecutor::ModelOutput; +using ScoringSignals = ::metrics::OmniboxEventProto::Suggestion::ScoringSignals; +using ::optimization_guide::proto::AutocompleteScoringModelMetadata; using ::optimization_guide::proto::OptimizationTarget; +using ::optimization_guide::proto::ScoringSignalSpec; +using ::optimization_guide::proto::ScoringSignalTransformation; + +constexpr float kDefaultMissingValue = -1; + +namespace { + +// Checks if the signal value is valid. +bool IsValidSignal(float val, const ScoringSignalSpec& signal_spec) { + if (signal_spec.has_min_value() && val < signal_spec.min_value()) { + return false; + } + if (signal_spec.has_max_value() && val > signal_spec.max_value()) { + return false; + } + return true; +} + +// Transforms the input signals according to the configured transformation. +float TransformSignal(float val, ScoringSignalTransformation transformation) { + switch (transformation) { + case optimization_guide::proto::SCORING_SIGNAL_TRANSFORMATION_LOG_2: + return log2(val + 1); + case optimization_guide::proto::SCORING_SIGNAL_TRANSFORMATION_UNKNOWN: + default: + DVLOG(0) << "Unknown scoring signal transformation type!"; + return val; + } +} + +} // namespace AutocompleteScoringModelHandler::AutocompleteScoringModelHandler( optimization_guide::OptimizationGuideModelProvider* model_provider, scoped_refptr<base::SequencedTaskRunner> model_executor_task_runner, + std::unique_ptr<AutocompleteScoringModelExecutor> model_executor, OptimizationTarget optimization_target, const absl::optional<optimization_guide::proto::Any>& model_metadata) : optimization_guide::ModelHandler<ModelOutput, ModelInput>( model_provider, model_executor_task_runner, - std::make_unique<AutocompleteScoringModelExecutor>(), + std::move(model_executor), /*model_inference_timeout=*/absl::nullopt, optimization_target, model_metadata) { @@ -35,3 +72,201 @@ } AutocompleteScoringModelHandler::~AutocompleteScoringModelHandler() = default; + +absl::optional<std::vector<float>> +AutocompleteScoringModelHandler::GetModelInput( + const metrics::OmniboxEventProto::Suggestion::ScoringSignals& + scoring_signals) { + if (!ModelAvailable()) { + return absl::nullopt; + } + + absl::optional<AutocompleteScoringModelMetadata> model_metadata = + ParsedSupportedFeaturesForLoadedModel<AutocompleteScoringModelMetadata>(); + if (!model_metadata) { + return absl::nullopt; + } + + return ExtractInputFromScoringSignals(scoring_signals, + model_metadata.value()); +} + +std::vector<float> +AutocompleteScoringModelHandler::ExtractInputFromScoringSignals( + const ScoringSignals& scoring_signals, + const AutocompleteScoringModelMetadata& metadata) { + std::vector<float> model_input; + for (const auto& scoring_signal_spec : metadata.scoring_signal_specs()) { + absl::optional<float> val; + switch (scoring_signal_spec.type()) { + case optimization_guide::proto::SCORING_SIGNAL_TYPE_TYPED_COUNT: + if (scoring_signals.has_typed_count()) { + val = static_cast<float>(scoring_signals.typed_count()); + } + break; + case optimization_guide::proto::SCORING_SIGNAL_TYPE_VISIT_COUNT: + if (scoring_signals.has_visit_count()) { + val = static_cast<float>(scoring_signals.visit_count()); + } + break; + case optimization_guide::proto:: + SCORING_SIGNAL_TYPE_ELAPSED_TIME_LAST_VISIT_SECS: + if (scoring_signals.has_elapsed_time_last_visit_secs()) { + val = static_cast<float>( + scoring_signals.elapsed_time_last_visit_secs()); + } + break; + case optimization_guide::proto::SCORING_SIGNAL_TYPE_IS_HOST_ONLY: + if (scoring_signals.has_is_host_only()) { + val = static_cast<float>(scoring_signals.is_host_only()); + } + break; + case optimization_guide::proto::SCORING_SIGNAL_TYPE_LENGTH_OF_URL: + if (scoring_signals.has_length_of_url()) { + val = static_cast<float>(scoring_signals.length_of_url()); + } + break; + case optimization_guide::proto:: + SCORING_SIGNAL_TYPE_FIRST_URL_MATCH_POSITION: + if (scoring_signals.has_first_url_match_position()) { + val = static_cast<float>(scoring_signals.first_url_match_position()); + } + break; + case optimization_guide::proto:: + SCORING_SIGNAL_TYPE_HOST_MATCH_AT_WORD_BOUNDARY: + if (scoring_signals.has_host_match_at_word_boundary()) { + val = + static_cast<float>(scoring_signals.host_match_at_word_boundary()); + } + break; + case optimization_guide::proto:: + SCORING_SIGNAL_TYPE_TOTAL_URL_MATCH_LENGTH: + if (scoring_signals.has_total_url_match_length()) { + val = static_cast<float>(scoring_signals.total_url_match_length()); + } + break; + case optimization_guide::proto:: + SCORING_SIGNAL_TYPE_TOTAL_HOST_MATCH_LENGTH: + if (scoring_signals.has_total_host_match_length()) { + val = static_cast<float>(scoring_signals.total_host_match_length()); + } + break; + case optimization_guide::proto:: + SCORING_SIGNAL_TYPE_TOTAL_PATH_MATCH_LENGTH: + if (scoring_signals.has_total_path_match_length()) { + val = static_cast<float>(scoring_signals.total_path_match_length()); + } + break; + case optimization_guide::proto:: + SCORING_SIGNAL_TYPE_TOTAL_QUERY_OR_REF_MATCH_LENGTH: + if (scoring_signals.has_total_query_or_ref_match_length()) { + val = static_cast<float>( + scoring_signals.total_query_or_ref_match_length()); + } + break; + case optimization_guide::proto:: + SCORING_SIGNAL_TYPE_TOTAL_TITLE_MATCH_LENGTH: + if (scoring_signals.has_total_title_match_length()) { + val = static_cast<float>(scoring_signals.total_title_match_length()); + } + break; + case optimization_guide::proto:: + SCORING_SIGNAL_TYPE_NUM_INPUT_TERMS_MATCHED_BY_TITLE: + if (scoring_signals.has_num_input_terms_matched_by_title()) { + val = static_cast<float>( + scoring_signals.num_input_terms_matched_by_title()); + } + break; + case optimization_guide::proto:: + SCORING_SIGNAL_TYPE_NUM_INPUT_TERMS_MATCHED_BY_URL: + if (scoring_signals.has_num_input_terms_matched_by_url()) { + val = static_cast<float>( + scoring_signals.num_input_terms_matched_by_url()); + } + break; + case optimization_guide::proto:: + SCORING_SIGNAL_TYPE_ALLOWED_TO_BE_DEFAULT_MATCH: + if (scoring_signals.has_allowed_to_be_default_match()) { + val = + static_cast<float>(scoring_signals.allowed_to_be_default_match()); + } + break; + case optimization_guide::proto:: + SCORING_SIGNAL_TYPE_HAS_NON_SCHEME_WWW_MATCH: + if (scoring_signals.has_has_non_scheme_www_match()) { + val = static_cast<float>(scoring_signals.has_non_scheme_www_match()); + } + break; + case optimization_guide::proto:: + SCORING_SIGNAL_TYPE_TOTAL_BOOKMARK_TITLE_MATCH_LENGTH: + if (scoring_signals.has_total_bookmark_title_match_length()) { + val = static_cast<float>( + scoring_signals.total_bookmark_title_match_length()); + } + break; + case optimization_guide::proto:: + SCORING_SIGNAL_TYPE_FIRST_BOOKMARK_TITLE_MATCH_POSITION: + if (scoring_signals.has_first_bookmark_title_match_position()) { + val = static_cast<float>( + scoring_signals.first_bookmark_title_match_position()); + } + break; + case optimization_guide::proto::SCORING_SIGNAL_TYPE_NUM_BOOKMARKS_OF_URL: + if (scoring_signals.has_num_bookmarks_of_url()) { + val = static_cast<float>(scoring_signals.num_bookmarks_of_url()); + } + break; + case optimization_guide::proto::SCORING_SIGNAL_TYPE_SHORTCUT_VISIT_COUNT: + if (scoring_signals.has_shortcut_visit_count()) { + val = static_cast<float>(scoring_signals.shortcut_visit_count()); + } + break; + case optimization_guide::proto::SCORING_SIGNAL_TYPE_SHORTEST_SHORTCUT_LEN: + if (scoring_signals.has_shortest_shortcut_len()) { + val = static_cast<float>(scoring_signals.shortest_shortcut_len()); + } + break; + case optimization_guide::proto:: + SCORING_SIGNAL_TYPE_ELAPSED_TIME_LAST_SHORTCUT_VISIT_SEC: + if (scoring_signals.has_elapsed_time_last_shortcut_visit_sec()) { + val = static_cast<float>( + scoring_signals.elapsed_time_last_shortcut_visit_sec()); + } + break; + case optimization_guide::proto::SCORING_SIGNAL_TYPE_UNKNOWN: + default: + // Reached when the metadata is updated to have a new signal that + // the binary hasn't yet been updated to have; or when the binary + // has updated to remove a previous signal that the metadata hasn't + // yet been updated to remove. + DVLOG(0) << "Unknown scoring signal enum type in model metadata!"; + break; + } + + // Treat invalid signals as missing. Invalid signals may be caused by + // client errors, e.g., negative elapsed time. + if (val && !IsValidSignal(*val, scoring_signal_spec)) { + DVLOG(0) << "Invalid scoring signal value of '" + << optimization_guide::proto::ScoringSignalType_Name( + scoring_signal_spec.type()) + << "': " << *val; + val = absl::nullopt; + } + + if (val && scoring_signal_spec.has_transformation()) { + val = TransformSignal(*val, scoring_signal_spec.transformation()); + } + + // Set default value if missing. + if (!val) { + val = scoring_signal_spec.has_missing_value() + ? scoring_signal_spec.missing_value() + : kDefaultMissingValue; + } + + model_input.push_back(*val); + } + DCHECK_EQ(static_cast<size_t>(model_input.size()), + static_cast<size_t>(metadata.scoring_signal_specs().size())); + return model_input; +}
diff --git a/components/omnibox/browser/autocomplete_scoring_model_handler.h b/components/omnibox/browser/autocomplete_scoring_model_handler.h index 90b7295..220ae33 100644 --- a/components/omnibox/browser/autocomplete_scoring_model_handler.h +++ b/components/omnibox/browser/autocomplete_scoring_model_handler.h
@@ -5,12 +5,15 @@ #ifndef COMPONENTS_OMNIBOX_BROWSER_AUTOCOMPLETE_SCORING_MODEL_HANDLER_H_ #define COMPONENTS_OMNIBOX_BROWSER_AUTOCOMPLETE_SCORING_MODEL_HANDLER_H_ +#include "base/gtest_prod_util.h" #include "base/task/sequenced_task_runner.h" #include "components/omnibox/browser/autocomplete_scoring_model_executor.h" #include "components/optimization_guide/core/model_handler.h" #include "components/optimization_guide/core/optimization_guide_model_provider.h" +#include "components/optimization_guide/proto/autocomplete_scoring_model_metadata.pb.h" #include "components/optimization_guide/proto/models.pb.h" #include "third_party/abseil-cpp/absl/types/optional.h" +#include "third_party/metrics_proto/omnibox_event.pb.h" // Implements optimization_guide::ModelHandler for autocomplete scoring. // Keeps scoring model in memory. @@ -22,6 +25,7 @@ AutocompleteScoringModelHandler( optimization_guide::OptimizationGuideModelProvider* model_provider, scoped_refptr<base::SequencedTaskRunner> model_executor_task_runner, + std::unique_ptr<AutocompleteScoringModelExecutor> model_executor, optimization_guide::proto::OptimizationTarget optimization_target, const absl::optional<optimization_guide::proto::Any>& model_metadata); ~AutocompleteScoringModelHandler() override; @@ -31,6 +35,26 @@ delete; AutocompleteScoringModelHandler& operator=( const AutocompleteScoringModelHandler&) = delete; + + // Construct the model input from scoring signals. Signals are appended to the + // input vector in the same order as signal specifications in the metadata. + // Checks validness of signals and applies transformation if configured in + // metadata. Returns nullopt if the model or metadata is missing. + absl::optional<std::vector<float>> GetModelInput( + const metrics::OmniboxEventProto::Suggestion::ScoringSignals& + scoring_signals); + + private: + FRIEND_TEST_ALL_PREFIXES(AutocompleteScoringModelHandlerTest, + ExtractInputFromScoringSignalsTest); + + // Extracts the model input from scoring signals according to the model + // metadata. + std::vector<float> ExtractInputFromScoringSignals( + const metrics::OmniboxEventProto::Suggestion::ScoringSignals& + scoring_signals, + const optimization_guide::proto::AutocompleteScoringModelMetadata& + metadata); }; #endif // COMPONENTS_OMNIBOX_BROWSER_AUTOCOMPLETE_SCORING_MODEL_HANDLER_H_
diff --git a/components/omnibox/browser/autocomplete_scoring_model_handler_unittest.cc b/components/omnibox/browser/autocomplete_scoring_model_handler_unittest.cc new file mode 100644 index 0000000..c636878 --- /dev/null +++ b/components/omnibox/browser/autocomplete_scoring_model_handler_unittest.cc
@@ -0,0 +1,128 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/omnibox/browser/autocomplete_scoring_model_handler.h" + +#include "base/task/sequenced_task_runner.h" +#include "base/test/task_environment.h" +#include "components/omnibox/browser/autocomplete_scoring_model_executor.h" +#include "components/optimization_guide/core/test_optimization_guide_model_provider.h" +#include "components/optimization_guide/proto/autocomplete_scoring_model_metadata.pb.h" +#include "components/optimization_guide/proto/models.pb.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/metrics_proto/omnibox_event.pb.h" + +using ScoringSignals = ::metrics::OmniboxEventProto::Suggestion::ScoringSignals; +using ::optimization_guide::proto::AutocompleteScoringModelMetadata; +using ::optimization_guide::proto::ScoringSignalSpec; +using ::optimization_guide::proto::ScoringSignalTransformation; +using ::optimization_guide::proto::ScoringSignalType; + +namespace { + +ScoringSignalSpec CreateScoringSignalSpec( + ScoringSignalType type, + absl::optional<ScoringSignalTransformation> transformation = absl::nullopt, + absl::optional<float> min_val = absl::nullopt, + absl::optional<float> max_val = absl::nullopt, + absl::optional<float> missing_val = absl::nullopt) { + ScoringSignalSpec spec; + spec.set_type(type); + if (transformation) { + spec.set_transformation(*transformation); + } + if (min_val) { + spec.set_min_value(*min_val); + } + if (max_val) { + spec.set_max_value(*max_val); + } + if (missing_val) { + spec.set_missing_value(*missing_val); + } + return spec; +} + +} // namespace + +class TestAutocompleteScoringModelExecutor + : public AutocompleteScoringModelExecutor { + public: + TestAutocompleteScoringModelExecutor() = default; + ~TestAutocompleteScoringModelExecutor() override = default; + + void InitializeAndMoveToExecutionThread( + absl::optional<base::TimeDelta>, + optimization_guide::proto::OptimizationTarget, + scoped_refptr<base::SequencedTaskRunner>, + scoped_refptr<base::SequencedTaskRunner>) override {} + + void UpdateModelFile(const base::FilePath&) override {} + + void UnloadModel() override {} + + void SetShouldUnloadModelOnComplete(bool should_auto_unload) override {} +}; + +class AutocompleteScoringModelHandlerTest : public testing::Test { + public: + AutocompleteScoringModelHandlerTest() = default; + ~AutocompleteScoringModelHandlerTest() override = default; + + void SetUp() override { + model_provider_ = std::make_unique< + optimization_guide::TestOptimizationGuideModelProvider>(); + model_handler_ = std::make_unique<AutocompleteScoringModelHandler>( + model_provider_.get(), task_environment_.GetMainThreadTaskRunner(), + std::make_unique<TestAutocompleteScoringModelExecutor>(), + /*optimization_target=*/ + optimization_guide::proto::OPTIMIZATION_TARGET_OMNIBOX_URL_SCORING, + /*model_metadata=*/absl::nullopt); + } + + void TearDown() override { + model_handler_.reset(); + model_provider_.reset(); + RunUntilIdle(); + } + + void RunUntilIdle() { task_environment_.RunUntilIdle(); } + + protected: + base::test::TaskEnvironment task_environment_; + std::unique_ptr<optimization_guide::TestOptimizationGuideModelProvider> + model_provider_; + std::unique_ptr<AutocompleteScoringModelHandler> model_handler_; +}; + +TEST_F(AutocompleteScoringModelHandlerTest, + ExtractInputFromScoringSignalsTest) { + // Metadata with three scoring signal specifications. + AutocompleteScoringModelMetadata model_metadata; + *model_metadata.add_scoring_signal_specs() = CreateScoringSignalSpec( + optimization_guide::proto::SCORING_SIGNAL_TYPE_LENGTH_OF_URL); + // Signal with log2 transformation. + *model_metadata.add_scoring_signal_specs() = CreateScoringSignalSpec( + optimization_guide::proto:: + SCORING_SIGNAL_TYPE_ELAPSED_TIME_LAST_VISIT_SECS, + /*transformation=*/optimization_guide::proto:: + SCORING_SIGNAL_TRANSFORMATION_LOG_2); + // Invalid signal. + *model_metadata.add_scoring_signal_specs() = CreateScoringSignalSpec( + optimization_guide::proto:: + SCORING_SIGNAL_TYPE_ELAPSED_TIME_LAST_SHORTCUT_VISIT_SEC, + /*transformation=*/absl::nullopt, + /*min_val=*/0, /*max_val=*/absl::nullopt, /*missing_val=*/-2); + + // Scoring signals. + ScoringSignals scoring_signals; + scoring_signals.set_length_of_url(10); + scoring_signals.set_elapsed_time_last_visit_secs(511); + scoring_signals.set_elapsed_time_last_shortcut_visit_sec(-200); + + const auto input_signals = model_handler_->ExtractInputFromScoringSignals( + scoring_signals, model_metadata); + EXPECT_THAT(input_signals, testing::UnorderedElementsAre(10, 9, -2)); +} \ No newline at end of file
diff --git a/components/omnibox/browser/autocomplete_scoring_model_service.cc b/components/omnibox/browser/autocomplete_scoring_model_service.cc index f330350f..b88695d 100644 --- a/components/omnibox/browser/autocomplete_scoring_model_service.cc +++ b/components/omnibox/browser/autocomplete_scoring_model_service.cc
@@ -26,6 +26,7 @@ url_scoring_model_handler_ = std::make_unique<AutocompleteScoringModelHandler>( model_provider, model_executor_task_runner_.get(), + std::make_unique<AutocompleteScoringModelExecutor>(), optimization_guide::proto::OPTIMIZATION_TARGET_OMNIBOX_URL_SCORING, /*model_metadata=*/absl::nullopt); } @@ -34,12 +35,21 @@ AutocompleteScoringModelService::~AutocompleteScoringModelService() = default; void AutocompleteScoringModelService::ScoreAutocompleteUrlMatch( - AutocompleteScoringModelExecutor::ModelInput input_signals, + const metrics::OmniboxEventProto::Suggestion::ScoringSignals& + scoring_signals, base::OnceCallback<void( const absl::optional<AutocompleteScoringModelExecutor::ModelOutput>&)> scoring_callback) { - if (url_scoring_model_handler_ != nullptr) { - url_scoring_model_handler_->ExecuteModelWithInput( - std::move(scoring_callback), input_signals); + if (!url_scoring_model_handler_) { + return; } + + absl::optional<std::vector<float>> input_signals = + url_scoring_model_handler_->GetModelInput(scoring_signals); + if (!input_signals) { + return; + } + + url_scoring_model_handler_->ExecuteModelWithInput(std::move(scoring_callback), + *input_signals); }
diff --git a/components/omnibox/browser/autocomplete_scoring_model_service.h b/components/omnibox/browser/autocomplete_scoring_model_service.h index 0021b7f..10c2445 100644 --- a/components/omnibox/browser/autocomplete_scoring_model_service.h +++ b/components/omnibox/browser/autocomplete_scoring_model_service.h
@@ -15,6 +15,7 @@ #include "components/omnibox/browser/autocomplete_scoring_model_handler.h" #include "components/optimization_guide/core/optimization_guide_model_provider.h" #include "third_party/abseil-cpp/absl/types/optional.h" +#include "third_party/metrics_proto/omnibox_event.pb.h" // Autocomplete scoring service using machine learning models via // OptimizationGuide's model handler. @@ -32,7 +33,8 @@ // Scores an autocomplete URL match with scoring signals. void ScoreAutocompleteUrlMatch( - AutocompleteScoringModelExecutor::ModelInput input_signals, + const metrics::OmniboxEventProto::Suggestion::ScoringSignals& + scoring_signals, base::OnceCallback<void( const absl::optional<AutocompleteScoringModelExecutor::ModelOutput>&)> scoring_callback);
diff --git a/components/omnibox/browser/omnibox_edit_model.cc b/components/omnibox/browser/omnibox_edit_model.cc index f5acbb59c..38f1f6d 100644 --- a/components/omnibox/browser/omnibox_edit_model.cc +++ b/components/omnibox/browser/omnibox_edit_model.cc
@@ -1147,6 +1147,65 @@ client_->OnBookmarkLaunched(); } +void OmniboxEditModel::OpenSelection(OmniboxPopupSelection selection, + base::TimeTicks timestamp, + WindowOpenDisposition disposition) { + // Intentionally accept input when selection has no line. + // This will reach `OpenMatch` indirectly. + if (selection.line >= result().size()) { + AcceptInput(disposition, timestamp); + return; + } + + // Keyword mode is handled separately, and other selections should + // only be opened when there is a popup view. + DCHECK_NE(selection.state, OmniboxPopupSelection::KEYWORD_MODE); + DCHECK(popup_view_); + + const AutocompleteMatch& match = result().match_at(selection.line); + + // TODO(crbug/1408506): This is an exceptional quirk for the new + // match takeover actions mechanism, and can likely be simplified. + const OmniboxAction* action = match.GetPrimaryAction(); + if (selection.state == OmniboxPopupSelection::NORMAL && + (action == nullptr || !action->TakesOverMatch())) { + AcceptInput(disposition, timestamp); + return; + } + + if (selection.state == OmniboxPopupSelection::FOCUSED_BUTTON_HEADER) { + DCHECK(match.suggestion_group_id.has_value()); + + const bool current_visibility = result().IsSuggestionGroupHidden( + GetPrefService(), match.suggestion_group_id.value()); + result().SetSuggestionGroupHidden(GetPrefService(), + match.suggestion_group_id.value(), + !current_visibility); + } else if (selection.state == + OmniboxPopupSelection::FOCUSED_BUTTON_REMOVE_SUGGESTION) { + TryDeletingPopupLine(selection.line); + } else if (selection.state == OmniboxPopupSelection::FOCUSED_BUTTON_ACTION) { + // TODO(crbug/1408506): Either handle in OpenMatch or convert OpenMatch + // usage to OpenSelection so this can keep a consistent code + // and metrics flow. The broad goal is to eliminate one or the other, + // or at least hide one as private so call sites are all consistent. + DCHECK(timestamp != base::TimeTicks()); + ExecuteAction(selection, disposition, timestamp); + } else { + DCHECK(timestamp != base::TimeTicks()); + if (selection.state == OmniboxPopupSelection::FOCUSED_BUTTON_TAB_SWITCH) { + disposition = WindowOpenDisposition::SWITCH_TO_TAB; + } + OpenMatch(match, disposition, GURL(), std::u16string(), + GetPopupSelection().line, timestamp); + } +} + +void OmniboxEditModel::OpenSelection(base::TimeTicks timestamp, + WindowOpenDisposition disposition) { + OpenSelection(GetPopupSelection(), timestamp, disposition); +} + bool OmniboxEditModel::InExplicitExperimentalKeywordMode() { return AutocompleteProvider::InExplicitExperimentalKeywordMode(input_, keyword_); @@ -2126,56 +2185,6 @@ return selection.IsControlPresentOnMatch(result(), GetPrefService()); } -bool OmniboxEditModel::TriggerPopupSelectionAction( - OmniboxPopupSelection selection, - base::TimeTicks timestamp, - WindowOpenDisposition disposition) { - DCHECK(popup_view_); - - // Early exit for the kNoMatch case. Also exits if the calling UI passes in - // an invalid |selection|. - if (selection.line >= result().size()) - return false; - - auto& match = result().match_at(selection.line); - switch (selection.state) { - case OmniboxPopupSelection::FOCUSED_BUTTON_HEADER: { - DCHECK(match.suggestion_group_id.has_value()); - - const bool current_visibility = result().IsSuggestionGroupHidden( - GetPrefService(), match.suggestion_group_id.value()); - result().SetSuggestionGroupHidden(GetPrefService(), - match.suggestion_group_id.value(), - !current_visibility); - break; - } - case OmniboxPopupSelection::NORMAL: { - return ExecuteTakeoverAction(selection.line, disposition, timestamp); - } - case OmniboxPopupSelection::FOCUSED_BUTTON_TAB_SWITCH: { - DCHECK(timestamp != base::TimeTicks()); - OpenMatch(match, WindowOpenDisposition::SWITCH_TO_TAB, GURL(), - std::u16string(), GetPopupSelection().line, timestamp); - break; - } - case OmniboxPopupSelection::FOCUSED_BUTTON_ACTION: { - DCHECK(timestamp != base::TimeTicks()); - ExecuteAction(selection, disposition, timestamp); - break; - } - case OmniboxPopupSelection::FOCUSED_BUTTON_REMOVE_SUGGESTION: { - TryDeletingPopupLine(selection.line); - break; - } - default: { - // Behavior is not yet supported. - return false; - } - } - - return true; -} - void OmniboxEditModel::TryDeletingPopupLine(size_t line) { DCHECK(popup_view_);
diff --git a/components/omnibox/browser/omnibox_edit_model.h b/components/omnibox/browser/omnibox_edit_model.h index c9a49e2..2ff3af9 100644 --- a/components/omnibox/browser/omnibox_edit_model.h +++ b/components/omnibox/browser/omnibox_edit_model.h
@@ -251,6 +251,19 @@ size_t index, base::TimeTicks match_selection_timestamp = base::TimeTicks()); + // Opens given selection. Most kinds of selection invoke an action or + // otherwise call `OpenMatch`, but some may `AcceptInput`. + void OpenSelection( + OmniboxPopupSelection selection, + base::TimeTicks timestamp = base::TimeTicks(), + WindowOpenDisposition disposition = WindowOpenDisposition::CURRENT_TAB); + + // A simplified version of OpenSelection that opens the model's current + // selection. + void OpenSelection( + base::TimeTicks timestamp = base::TimeTicks(), + WindowOpenDisposition disposition = WindowOpenDisposition::CURRENT_TAB); + OmniboxFocusState focus_state() const { return focus_state_; } bool has_focus() const { return focus_state_ != OMNIBOX_FOCUS_NONE; } @@ -464,18 +477,6 @@ // should query to decide whether or not to draw the control. bool IsPopupControlPresentOnMatch(OmniboxPopupSelection selection) const; - // On popup, triggers the action on |selection| (usually an auxiliary button). - // If the popup model supports the action and performs it, this returns true. - // This can't handle all actions currently, and returns false in those cases. - // The timestamp parameter is currently only used by FOCUSED_BUTTON_TAB_SWITCH - // and FOCUSED_BUTTON_ACTION, so is set by default for other use cases. - // The `disposition` can be used to respect keyboard state for opening - // actions in background tabs, new windows, etc. - bool TriggerPopupSelectionAction( - OmniboxPopupSelection selection, - base::TimeTicks timestamp = base::TimeTicks(), - WindowOpenDisposition disposition = WindowOpenDisposition::CURRENT_TAB); - // From popup, tries to erase the suggestion at |line|. This should determine // if the item at |line| can be removed from history, and if so, remove it // and update the popup.
diff --git a/components/optimization_guide/proto/autocomplete_scoring_model_metadata.proto b/components/optimization_guide/proto/autocomplete_scoring_model_metadata.proto index 388f0d93..b5349561 100644 --- a/components/optimization_guide/proto/autocomplete_scoring_model_metadata.proto +++ b/components/optimization_guide/proto/autocomplete_scoring_model_metadata.proto
@@ -25,8 +25,8 @@ SCORING_SIGNAL_TYPE_TOTAL_PATH_MATCH_LENGTH = 10; SCORING_SIGNAL_TYPE_TOTAL_QUERY_OR_REF_MATCH_LENGTH = 11; SCORING_SIGNAL_TYPE_TOTAL_TITLE_MATCH_LENGTH = 12; - SCORING_SIGNAL_TYPE_TITLE_MATCH_RATIO = 13; - SCORING_SIGNAL_TYPE_URL_MATCH_RATIO = 14; + SCORING_SIGNAL_TYPE_NUM_INPUT_TERMS_MATCHED_BY_TITLE = 13; + SCORING_SIGNAL_TYPE_NUM_INPUT_TERMS_MATCHED_BY_URL = 14; SCORING_SIGNAL_TYPE_ALLOWED_TO_BE_DEFAULT_MATCH = 15; SCORING_SIGNAL_TYPE_HAS_NON_SCHEME_WWW_MATCH = 16; SCORING_SIGNAL_TYPE_TOTAL_BOOKMARK_TITLE_MATCH_LENGTH = 17; @@ -41,7 +41,7 @@ enum ScoringSignalTransformation { // No transformation. SCORING_SIGNAL_TRANSFORMATION_UNKNOWN = 0; - // log2(x). + // log2(1+x). SCORING_SIGNAL_TRANSFORMATION_LOG_2 = 1; } @@ -53,6 +53,10 @@ optional float missing_value = 2; // Transformation to apply to this signal. optional ScoringSignalTransformation transformation = 3; + // Minimum value of valid signals. + optional float min_value = 4; + // Maximum value of valid signals. + optional float max_value = 5; } // The message contains a set of params to run a specific autocomplete scoring
diff --git a/components/paint_preview/browser/file_manager_unittest.cc b/components/paint_preview/browser/file_manager_unittest.cc index 4303f183..b591de7e 100644 --- a/components/paint_preview/browser/file_manager_unittest.cc +++ b/components/paint_preview/browser/file_manager_unittest.cc
@@ -69,8 +69,7 @@ base::FilePath file_path = out.AppendASCII("test"); std::string test_str = "Hello World!"; - EXPECT_EQ(static_cast<int>(test_str.length()), - base::WriteFile(file_path, test_str.data(), test_str.length())); + EXPECT_TRUE(base::WriteFile(file_path, test_str)); EXPECT_EQ(manager->GetSizeOfArtifacts(valid_key), test_str.length()); } @@ -92,9 +91,7 @@ EXPECT_FALSE(directory.empty()); base::FilePath test_file = directory.AppendASCII("test"); std::string test_str = "Hello World!"; - EXPECT_EQ( - static_cast<int>(test_str.length()), - base::WriteFile(test_file, test_str.data(), test_str.length())); + EXPECT_TRUE(base::WriteFile(test_file, test_str)); // Open an existing directory and don't clear. base::FilePath existing_directory = @@ -126,8 +123,7 @@ // A file needs to exist for compression to work. base::FilePath test_file = directory.AppendASCII("test"); std::string test_str = "Hello World!"; - EXPECT_EQ(static_cast<int>(test_str.length()), - base::WriteFile(test_file, test_str.data(), test_str.length())); + EXPECT_TRUE(base::WriteFile(test_file, test_str)); EXPECT_TRUE(base::PathExists(test_file)); base::FilePath test_file_empty = directory.AppendASCII("foo.txt"); {
diff --git a/components/paint_preview/common/file_utils.cc b/components/paint_preview/common/file_utils.cc index 719222c9..424807e 100644 --- a/components/paint_preview/common/file_utils.cc +++ b/components/paint_preview/common/file_utils.cc
@@ -18,7 +18,7 @@ std::string proto_str; if (!proto.SerializeToString(&proto_str)) return false; - return base::WriteFile(file_path, proto_str.data(), proto_str.size()) > 0; + return base::WriteFile(file_path, proto_str); } std::unique_ptr<PaintPreviewProto> ReadProtoFromFile(
diff --git a/components/paint_preview/player/player_compositor_delegate_unittest.cc b/components/paint_preview/player/player_compositor_delegate_unittest.cc index 580d871..4a1110d 100644 --- a/components/paint_preview/player/player_compositor_delegate_unittest.cc +++ b/components/paint_preview/player/player_compositor_delegate_unittest.cc
@@ -297,7 +297,7 @@ auto root_file = directory->AppendASCII("0.skp"); proto->mutable_root_frame()->set_file_path( root_file.AsUTF8Unsafe()); - base::WriteFile(root_file, fake_data.data(), fake_data.size()); + base::WriteFile(root_file, fake_data); if (!skip_proto_serialization) { file_manager->SerializePaintPreviewProto(key, *proto, false); @@ -366,12 +366,12 @@ auto root_file = directory->AppendASCII("0.skp"); proto->mutable_root_frame()->set_file_path( root_file.AsUTF8Unsafe()); - base::WriteFile(root_file, fake_data.data(), fake_data.size()); + base::WriteFile(root_file, fake_data); auto subframe_file = directory->AppendASCII("1.skp"); proto->mutable_subframes(0)->set_file_path( subframe_file.AsUTF8Unsafe()); - base::WriteFile(subframe_file, fake_data.data(), fake_data.size()); + base::WriteFile(subframe_file, fake_data); file_manager->SerializePaintPreviewProto(key, *proto, false); std::move(quit).Run(); @@ -420,7 +420,7 @@ auto directory = file_manager->CreateOrGetDirectory(key, true); std::string fake_data = "Hello World!"; auto proto_file = directory->AppendASCII("proto.pb"); - base::WriteFile(proto_file, fake_data.data(), fake_data.size()); + base::WriteFile(proto_file, fake_data); }, loop.QuitClosure(), file_manager, key)); @@ -670,8 +670,7 @@ base::Unretained(&dir))); env.RunUntilIdle(); std::string data = "foo"; - EXPECT_TRUE( - base::WriteFile(dir.AppendASCII("test_file"), data.data(), data.size())); + EXPECT_TRUE(base::WriteFile(dir.AppendASCII("test_file"), data)); { PlayerCompositorDelegateImpl player_compositor_delegate; player_compositor_delegate.SetExpected(CompositorStatus::NO_CAPTURE, 0.0);
diff --git a/components/password_manager/core/browser/ui/passwords_grouper.cc b/components/password_manager/core/browser/ui/passwords_grouper.cc index 61c13e0..fe0c78a 100644 --- a/components/password_manager/core/browser/ui/passwords_grouper.cc +++ b/components/password_manager/core/browser/ui/passwords_grouper.cc
@@ -21,17 +21,19 @@ namespace { +// Returns signon_realm for regular forms and formatted url for federated forms. std::string GetSignonRealm(const PasswordForm& form) { + std::string result = form.signon_realm; if (form.IsFederatedCredential()) { - return base::UTF16ToUTF8(url_formatter::FormatUrlForSecurityDisplay( + result = base::UTF16ToUTF8(url_formatter::FormatUrlForSecurityDisplay( form.url, url_formatter::SchemeDisplay::SHOW)); } - // Remove trailing '/' because facets don't have it. - if (base::EndsWith(form.signon_realm, "/")) { - return form.signon_realm.substr(0, form.signon_realm.size() - 1); + // Remove trailing '/' because FacetURIs don't have it. + if (base::EndsWith(result, "/")) { + return result.substr(0, result.size() - 1); } - return form.signon_realm; + return result; } // An implementation of the disjoint-set data structure @@ -360,12 +362,12 @@ DCHECK(map_facet_to_group_id.contains(signon_realm)); GroupId group_id = map_facet_to_group_id[signon_realm]; + // Store group id for sign-on realm. + map_signon_realm_to_group_id[SignonRealm(form.signon_realm)] = group_id; + + // Store form for username/password key. UsernamePasswordKey key(CreateUsernamePasswordSortKey(form)); map_group_id_to_forms[group_id][key].push_back(std::move(form)); - - // Store group id for sign-on realm. Append "/" because - // PasswordForm::signon_realms should always has trailing '/'. - map_signon_realm_to_group_id[SignonRealm(signon_realm + "/")] = group_id; } }
diff --git a/components/password_manager/core/browser/ui/passwords_grouper_unittest.cc b/components/password_manager/core/browser/ui/passwords_grouper_unittest.cc index 7740241f..7372bca 100644 --- a/components/password_manager/core/browser/ui/passwords_grouper_unittest.cc +++ b/components/password_manager/core/browser/ui/passwords_grouper_unittest.cc
@@ -55,10 +55,11 @@ blocked_form.blocked_by_user = true; PasswordForm federated_form; - federated_form.signon_realm = "https://federated.com/"; - federated_form.username_value = u"example@gmail.com"; + federated_form.url = GURL("https://test.org/"); + federated_form.signon_realm = "federation://test.com/accounts.federation.com"; + federated_form.username_value = u"username2"; federated_form.federation_origin = - url::Origin::Create(GURL(u"federatedOrigin.com")); + url::Origin::Create(GURL("https://accounts.federation.com")); EXPECT_CALL(affiliation_service(), GetAllGroups) .WillRepeatedly( @@ -92,10 +93,11 @@ blocked_form.blocked_by_user = true; PasswordForm federated_form; - federated_form.signon_realm = "https://federated.com/"; - federated_form.username_value = u"example@gmail.com"; + federated_form.url = GURL("https://test.org/"); + federated_form.signon_realm = "federation://test.com/accounts.federation.com"; + federated_form.username_value = u"username2"; federated_form.federation_origin = - url::Origin::Create(GURL(u"federatedOrigin.com")); + url::Origin::Create(GURL("https://accounts.federation.com")); GroupedFacets group; group.facets = { @@ -132,10 +134,11 @@ blocked_form.blocked_by_user = true; PasswordForm federated_form; - federated_form.signon_realm = "https://federated.com/"; - federated_form.username_value = u"example@gmail.com"; + federated_form.url = GURL("https://test.org/"); + federated_form.signon_realm = "federation://test.com/accounts.federation.com"; + federated_form.username_value = u"username2"; federated_form.federation_origin = - url::Origin::Create(GURL(u"federatedOrigin.com")); + url::Origin::Create(GURL("https://accounts.federation.com")); EXPECT_CALL(affiliation_service(), GetAllGroups) .WillRepeatedly( @@ -286,4 +289,38 @@ ElementsAre(AffiliatedGroup({credential}, {GetShownOrigin(credential)}))); } +TEST_F(PasswordsGrouperTest, FederatedAndroidAppGroupedWithRegularPasswords) { + PasswordForm form = CreateForm("https://test.app.com/"); + PasswordForm federated_android_form; + federated_android_form.signon_realm = + "android://" + "5Z0D_o6B8BqileZyWhXmqO_wkO8uO0etCEXvMn5tUzEqkWUgfTSjMcTM7eMMTY_" + "FGJC9RlpRNt_8Qp5tgDocXw==@com.bambuna.podcastaddict/"; + federated_android_form.username_value = u"test@gmail.com"; + federated_android_form.url = GURL(federated_android_form.signon_realm); + federated_android_form.federation_origin = + url::Origin::Create(GURL(u"https://federatedOrigin.com")); + + GroupedFacets group; + group.facets = { + Facet(FacetURI::FromPotentiallyInvalidSpec( + "android://" + "5Z0D_o6B8BqileZyWhXmqO_wkO8uO0etCEXvMn5tUzEqkWUgfTSjMcTM7eMMTY_" + "FGJC9RlpRNt_8Qp5tgDocXw==@com.bambuna.podcastaddict")), + Facet(FacetURI::FromPotentiallyInvalidSpec("https://test.app.com")), + }; + + EXPECT_CALL(affiliation_service(), GetAllGroups) + .WillRepeatedly( + base::test::RunOnceCallback<0>(std::vector<GroupedFacets>{group})); + grouper().GroupPasswords({form, federated_android_form}, base::DoNothing()); + + CredentialUIEntry credential({form}), + federated_credential({federated_android_form}); + EXPECT_THAT( + grouper().GetAffiliatedGroupsWithGroupingInfo(), + ElementsAre(AffiliatedGroup({federated_credential, credential}, + {GetShownOrigin(federated_credential)}))); +} + } // namespace password_manager
diff --git a/components/policy/core/common/BUILD.gn b/components/policy/core/common/BUILD.gn index d4b9fa5..8ee2bca 100644 --- a/components/policy/core/common/BUILD.gn +++ b/components/policy/core/common/BUILD.gn
@@ -558,12 +558,13 @@ "android/policy_converter_unittest.cc", "android/policy_map_android_unittest.cc", "android/policy_service_android_unittest.cc", - "policy_logger_unittest.cc", ] } else { sources += [ "async_policy_provider_unittest.cc" ] } - if (!is_android && !is_ios) { + if (is_android || is_ios) { + sources += [ "policy_logger_unittest.cc" ] + } else { sources += [ "cloud/cloud_external_data_store_unittest.cc", "cloud/component_cloud_policy_service_unittest.cc",
diff --git a/components/policy/core/common/features.cc b/components/policy/core/common/features.cc index d02a5bf..54a5444 100644 --- a/components/policy/core/common/features.cc +++ b/components/policy/core/common/features.cc
@@ -44,6 +44,12 @@ "PolicyMergeMultiSource", base::FEATURE_DISABLED_BY_DEFAULT); +#if BUILDFLAG(IS_IOS) +BASE_FEATURE(kPolicyLogsPageIOS, + "PolicyLogsPageIOS", + base::FEATURE_DISABLED_BY_DEFAULT); +#endif // BUILDFLAG(IS_IOS) + } // namespace features } // namespace policy
diff --git a/components/policy/core/common/features.h b/components/policy/core/common/features.h index 02ee846..831fa66 100644 --- a/components/policy/core/common/features.h +++ b/components/policy/core/common/features.h
@@ -47,6 +47,11 @@ // Prevent policies set by a single source from being treated as merged. POLICY_EXPORT BASE_DECLARE_FEATURE(kPolicyMergeMultiSource); +#if BUILDFLAG(IS_IOS) +// Enable logging and chrome://policy/logs page on IOS. +POLICY_EXPORT BASE_DECLARE_FEATURE(kPolicyLogsPageIOS); +#endif // BUILDFLAG(IS_IOS) + } // namespace features } // namespace policy
diff --git a/components/policy/core/common/policy_logger.cc b/components/policy/core/common/policy_logger.cc index 2fa5a56e..ab8a64b 100644 --- a/components/policy/core/common/policy_logger.cc +++ b/components/policy/core/common/policy_logger.cc
@@ -188,6 +188,8 @@ bool PolicyLogger::IsPolicyLoggingEnabled() const { #if BUILDFLAG(IS_ANDROID) return base::FeatureList::IsEnabled(policy::features::kPolicyLogsPageAndroid); +#elif BUILDFLAG(IS_IOS) + return base::FeatureList::IsEnabled(policy::features::kPolicyLogsPageIOS); #else return false; #endif // BUILDFLAG(IS_ANDROID)
diff --git a/components/policy/core/common/policy_logger.h b/components/policy/core/common/policy_logger.h index 2c2f9950..cfface8b 100644 --- a/components/policy/core/common/policy_logger.h +++ b/components/policy/core/common/policy_logger.h
@@ -20,7 +20,7 @@ // messages logged with DLOG are still important to be seen on the // chrome://policy/logs page in release mode. The DLOG call in StreamLog() will // do the check as usual for command line logging. -#if BUILDFLAG(IS_ANDROID) +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS) #define LOG_POLICY(log_severity, log_source) \ LOG_POLICY_##log_severity(::policy::PolicyLogger::LogHelper::LogType::kLog, \ log_source)
diff --git a/components/policy/core/common/policy_logger_unittest.cc b/components/policy/core/common/policy_logger_unittest.cc index 2fec90da..e2cf528 100644 --- a/components/policy/core/common/policy_logger_unittest.cc +++ b/components/policy/core/common/policy_logger_unittest.cc
@@ -25,8 +25,13 @@ TEST(PolicyLoggerTest, PolicyLoggingEnabled) { base::test::ScopedFeatureList scoped_feature_list_; +#if BUILDFLAG(IS_ANDROID) scoped_feature_list_.InitWithFeatureState( policy::features::kPolicyLogsPageAndroid, true); +#elif BUILDFLAG(IS_IOS) + scoped_feature_list_.InitWithFeatureState( + policy::features::kPolicyLogsPageIOS, true); +#endif PolicyLogger* policy_logger = policy::PolicyLogger::GetInstance(); @@ -42,8 +47,13 @@ TEST(PolicyLoggerTest, PolicyLoggingDisabled) { base::test::ScopedFeatureList scoped_feature_list_; +#if BUILDFLAG(IS_ANDROID) scoped_feature_list_.InitWithFeatureState( policy::features::kPolicyLogsPageAndroid, false); +#elif BUILDFLAG(IS_IOS) + scoped_feature_list_.InitWithFeatureState( + policy::features::kPolicyLogsPageIOS, false); +#endif PolicyLogger* policy_logger = policy::PolicyLogger::GetInstance(); @@ -53,4 +63,4 @@ logs_size_before_adding); } -} // namespace policy \ No newline at end of file +} // namespace policy
diff --git a/components/policy/core/common/schema.cc b/components/policy/core/common/schema.cc index def7970..11450543 100644 --- a/components/policy/core/common/schema.cc +++ b/components/policy/core/common/schema.cc
@@ -1065,9 +1065,9 @@ return false; } schema_node->extra = static_cast<int>(restriction_nodes_.size()); - restriction_nodes_.emplace_back(); - restriction_nodes_.back().enumeration_restriction.offset_begin = offset_begin; - restriction_nodes_.back().enumeration_restriction.offset_end = offset_end; + restriction_nodes_.push_back(RestrictionNode{ + .enumeration_restriction = RestrictionNode::EnumerationRestriction{ + .offset_begin = offset_begin, .offset_end = offset_end}}); return true; } @@ -1081,9 +1081,9 @@ return false; } schema_node->extra = static_cast<int>(restriction_nodes_.size()); - restriction_nodes_.emplace_back(); - restriction_nodes_.back().ranged_restriction.max_value = max_value; - restriction_nodes_.back().ranged_restriction.min_value = min_value; + restriction_nodes_.push_back( + RestrictionNode{.ranged_restriction = RestrictionNode::RangedRestriction{ + .max_value = max_value, .min_value = min_value}}); return true; } @@ -1105,10 +1105,9 @@ strings_.push_back(*pattern); string_enums_.push_back(strings_.back().c_str()); schema_node->extra = static_cast<int>(restriction_nodes_.size()); - restriction_nodes_.emplace_back(); - restriction_nodes_.back().string_pattern_restriction.pattern_index = index; - restriction_nodes_.back().string_pattern_restriction.pattern_index_backup = - index; + restriction_nodes_.push_back(RestrictionNode{ + .string_pattern_restriction = RestrictionNode::StringPatternRestriction{ + .pattern_index = index, .pattern_index_backup = index}}); return true; }
diff --git a/components/policy/resources/webui/BUILD.gn b/components/policy/resources/webui/BUILD.gn index 2442e16..4a6e024 100644 --- a/components/policy/resources/webui/BUILD.gn +++ b/components/policy/resources/webui/BUILD.gn
@@ -16,7 +16,7 @@ "policy.html", ] -if (is_android) { +if (is_android || is_ios) { static_files += [ "logs/policy_logs.html" ] } @@ -45,7 +45,7 @@ "policy.js", ] -if (is_android) { +if (is_android || is_ios) { non_web_component_files += [ "logs/types.ts", "logs/policy_logs.ts",
diff --git a/components/policy/resources/webui/logs/policy_logs.ts b/components/policy/resources/webui/logs/policy_logs.ts index ab0f1e6d..e6dfb00 100644 --- a/components/policy/resources/webui/logs/policy_logs.ts +++ b/components/policy/resources/webui/logs/policy_logs.ts
@@ -2,6 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// <if expr="is_ios"> +import 'chrome://resources/js/ios/web_ui.js'; +// </if> + + import '../strings.m.js'; import {sendWithPromise} from 'chrome://resources/js/cr.js'; @@ -29,10 +34,14 @@ } function displayList() { - logs = logs; - const logMessageContainer = getRequiredElement('logs-container'); - logMessageContainer.innerHTML = window.trustedTypes!.emptyHTML; + + // TrustedTypes is not supported on iOS + if (window.trustedTypes) { + logMessageContainer.innerHTML = window.trustedTypes!.emptyHTML; + } else { + logMessageContainer.innerHTML = ''; + } logs.forEach(log => { const logMessage = document.createElement('li'); logMessage.textContent = log.message; @@ -81,4 +90,4 @@ .addEventListener('click', fetchLogsAndDisplay); } -document.addEventListener('DOMContentLoaded', initialize); \ No newline at end of file +document.addEventListener('DOMContentLoaded', initialize);
diff --git a/components/policy/tools/generate_policy_source.py b/components/policy/tools/generate_policy_source.py index 6535cc3..d7fb08ce 100755 --- a/components/policy/tools/generate_policy_source.py +++ b/components/policy/tools/generate_policy_source.py
@@ -399,7 +399,9 @@ if args.cloud_policy_proto_path: GenerateFile(args.cloud_policy_proto_path, _WriteCloudPolicyProtobuf) if args.chrome_settings_proto_path: - GenerateFile(args.chrome_settings_proto_path, _WriteChromeSettingsProtobuf) + GenerateFile(args.chrome_settings_proto_path, + _WriteChromeSettingsProtobuf, + sorted=True) if target_platform == 'android' and args.app_restrictions_path: GenerateFile(args.app_restrictions_path, _WriteAppRestrictions, xml=True)
diff --git a/components/prefs/json_pref_store_unittest.cc b/components/prefs/json_pref_store_unittest.cc index 3f770a4a..2be6b46 100644 --- a/components/prefs/json_pref_store_unittest.cc +++ b/components/prefs/json_pref_store_unittest.cc
@@ -224,8 +224,7 @@ // Test fallback behavior for an invalid file. TEST_P(JsonPrefStoreTest, InvalidFile) { base::FilePath invalid_file = temp_dir_.GetPath().AppendASCII("invalid.json"); - ASSERT_LT(0, base::WriteFile(invalid_file, kInvalidJson, - std::size(kInvalidJson) - 1)); + ASSERT_TRUE(base::WriteFile(invalid_file, kInvalidJson)); auto pref_store = base::MakeRefCounted<JsonPrefStore>(invalid_file); EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_JSON_PARSE, @@ -313,8 +312,7 @@ TEST_P(JsonPrefStoreTest, Basic) { base::FilePath input_file = temp_dir_.GetPath().AppendASCII("write.json"); - ASSERT_LT(0, - base::WriteFile(input_file, kReadJson, std::size(kReadJson) - 1)); + ASSERT_TRUE(base::WriteFile(input_file, kReadJson)); // Test that the persistent value can be loaded. ASSERT_TRUE(PathExists(input_file)); @@ -340,8 +338,7 @@ TEST_P(JsonPrefStoreTest, BasicAsync) { base::FilePath input_file = temp_dir_.GetPath().AppendASCII("write.json"); - ASSERT_LT(0, - base::WriteFile(input_file, kReadJson, std::size(kReadJson) - 1)); + ASSERT_TRUE(base::WriteFile(input_file, kReadJson)); // Test that the persistent value can be loaded. auto pref_store = base::MakeRefCounted<JsonPrefStore>(input_file); @@ -448,8 +445,7 @@ TEST_P(JsonPrefStoreTest, ReadWithInterceptor) { base::FilePath input_file = temp_dir_.GetPath().AppendASCII("write.json"); - ASSERT_LT(0, - base::WriteFile(input_file, kReadJson, std::size(kReadJson) - 1)); + ASSERT_TRUE(base::WriteFile(input_file, kReadJson)); std::unique_ptr<InterceptingPrefFilter> intercepting_pref_filter( new InterceptingPrefFilter()); @@ -490,8 +486,7 @@ TEST_P(JsonPrefStoreTest, ReadAsyncWithInterceptor) { base::FilePath input_file = temp_dir_.GetPath().AppendASCII("write.json"); - ASSERT_LT(0, - base::WriteFile(input_file, kReadJson, std::size(kReadJson) - 1)); + ASSERT_TRUE(base::WriteFile(input_file, kReadJson)); std::unique_ptr<InterceptingPrefFilter> intercepting_pref_filter( new InterceptingPrefFilter()); @@ -884,8 +879,7 @@ TEST_F(JsonPrefStoreCallbackTest, TestSerializeDataCallbacks) { base::FilePath input_file = temp_dir_.GetPath().AppendASCII("write.json"); - ASSERT_LT(0, - base::WriteFile(input_file, kReadJson, std::size(kReadJson) - 1)); + ASSERT_TRUE(base::WriteFile(input_file, kReadJson)); std::unique_ptr<InterceptingPrefFilter> intercepting_pref_filter( new InterceptingPrefFilter(write_callback_observer_.GetCallbackPair()));
diff --git a/components/remote_cocoa/app_shim/immersive_mode_tabbed_controller.h b/components/remote_cocoa/app_shim/immersive_mode_tabbed_controller.h index 1135a3e..12add8f 100644 --- a/components/remote_cocoa/app_shim/immersive_mode_tabbed_controller.h +++ b/components/remote_cocoa/app_shim/immersive_mode_tabbed_controller.h
@@ -28,6 +28,7 @@ // ImmersiveModeController overrides void Enable() override; void UpdateToolbarVisibility(mojom::ToolbarVisibilityStyle style) override; + void OnTopViewBoundsChanged(const gfx::Rect& bounds) override; void RevealLock() override; void RevealUnlock() override; void TitlebarLock() override;
diff --git a/components/remote_cocoa/app_shim/immersive_mode_tabbed_controller.mm b/components/remote_cocoa/app_shim/immersive_mode_tabbed_controller.mm index 6e23e95..7f87af0 100644 --- a/components/remote_cocoa/app_shim/immersive_mode_tabbed_controller.mm +++ b/components/remote_cocoa/app_shim/immersive_mode_tabbed_controller.mm
@@ -42,22 +42,23 @@ overlay_window, std::move(callback)), tab_window_(tab_window) { - if (@available(macOS 11.0, *)) { - // TODO(https://crbug.com/1414521): Support macOS versions older than - // macOS 11. - browser_window.toolbarStyle = NSWindowToolbarStyleUnifiedCompact; - } browser_window.titleVisibility = NSWindowTitleHidden; browser_window.toolbar = [[[NSToolbar alloc] init] autorelease]; tab_titlebar_view_controller_.reset([[TabTitlebarViewController alloc] init]); tab_titlebar_view_controller_.get().view = [[[NSView alloc] init] autorelease]; + + // The view is pinned to the opposite side of the traffic lights. A view long + // enough is able to paint underneath the traffic lights. This also works with + // RTL setups. tab_titlebar_view_controller_.get().layoutAttribute = - (browser_window.windowTitlebarLayoutDirection == - NSUserInterfaceLayoutDirectionRightToLeft) - ? NSLayoutAttributeRight - : NSLayoutAttributeLeft; + NSLayoutAttributeTrailing; + + // TODO(https://crbug.com/1414521): Fix window tab parent. Currently the tab + // window is parented to the browser window. Instead it should be parented to + // the AppKit fullscreen window as a sibling of the overlay window. This will + // involve some changes to ImmersiveModeDelegate. } ImmersiveModeTabbedController::~ImmersiveModeTabbedController() { @@ -105,11 +106,21 @@ TitlebarHide(); break; case mojom::ToolbarVisibilityStyle::kNone: - browser_window().toolbar = nil; + TitlebarHide(); break; } } +void ImmersiveModeTabbedController::OnTopViewBoundsChanged( + const gfx::Rect& bounds) { + ImmersiveModeController::OnTopViewBoundsChanged(bounds); + NSRect frame = NSRectFromCGRect(bounds.ToCGRect()); + [tab_titlebar_view_controller_.get().view + setFrameSize:NSMakeSize(frame.size.width, + tab_titlebar_view_controller_.get() + .view.frame.size.height)]; +} + void ImmersiveModeTabbedController::RevealLock() { ImmersiveModeController::RevealLock(); TitlebarReveal(); @@ -130,7 +141,7 @@ if (@available(macOS 10.15, *)) { browser_window().titlebarHeight = tab_window_.frame.size.height - 1; } - browser_window().toolbar = [[[NSToolbar alloc] init] autorelease]; + browser_window().toolbar.visible = YES; if (@available(macOS 10.15, *)) { browser_window().titlebarHeight = tab_window_.frame.size.height; } @@ -142,7 +153,7 @@ if (@available(macOS 10.15, *)) { browser_window().titlebarHeight = tab_window_.frame.size.height - 1; } - browser_window().toolbar = nil; + browser_window().toolbar.visible = NO; if (@available(macOS 10.15, *)) { browser_window().titlebarHeight = tab_window_.frame.size.height; }
diff --git a/components/sessions/core/command_storage_backend_unittest.cc b/components/sessions/core/command_storage_backend_unittest.cc index d3b477c..f9e3612 100644 --- a/components/sessions/core/command_storage_backend_unittest.cc +++ b/components/sessions/core/command_storage_backend_unittest.cc
@@ -587,7 +587,7 @@ base::FilePath(kSessionsDirectory) .Append(FILE_PATH_LITERAL("Session_13235178308836991"))); ASSERT_TRUE(base::CreateDirectory(prev_path.DirName())); - ASSERT_EQ(0, base::WriteFile(prev_path, "", 0)); + ASSERT_TRUE(base::WriteFile(prev_path, "")); scoped_refptr<CommandStorageBackend> backend = CreateBackendWithRestoreType(); auto last_session_info = GetLastSessionInfo(backend.get()); @@ -607,9 +607,9 @@ sessions_dir.Append(FILE_PATH_LITERAL("Session_13235178308548874")); const auto old_path_2 = sessions_dir.Append(FILE_PATH_LITERAL("Session_0")); ASSERT_TRUE(base::CreateDirectory(prev_path.DirName())); - ASSERT_EQ(0, base::WriteFile(prev_path, "", 0)); - ASSERT_EQ(0, base::WriteFile(old_path_1, "", 0)); - ASSERT_EQ(0, base::WriteFile(old_path_2, "", 0)); + ASSERT_TRUE(base::WriteFile(prev_path, "")); + ASSERT_TRUE(base::WriteFile(old_path_1, "")); + ASSERT_TRUE(base::WriteFile(old_path_2, "")); scoped_refptr<CommandStorageBackend> backend = CreateBackendWithRestoreType(); auto last_session_info = GetLastSessionInfo(backend.get()); @@ -624,7 +624,7 @@ restore_path().Append(base::FilePath(kSessionsDirectory) .Append(FILE_PATH_LITERAL("Session_invalid"))); ASSERT_TRUE(base::CreateDirectory(prev_path.DirName())); - ASSERT_EQ(0, base::WriteFile(prev_path, "", 0)); + ASSERT_TRUE(base::WriteFile(prev_path, "")); scoped_refptr<CommandStorageBackend> backend = CreateBackendWithRestoreType(); auto last_session_info = GetLastSessionInfo(backend.get()); @@ -639,7 +639,7 @@ const auto last_session = sessions_dir.Append(FILE_PATH_LITERAL("Session_13235178308548874")); ASSERT_TRUE(base::CreateDirectory(last_session.DirName())); - ASSERT_EQ(0, base::WriteFile(last_session, "", 0)); + ASSERT_TRUE(base::WriteFile(last_session, "")); scoped_refptr<CommandStorageBackend> backend = CreateBackendWithRestoreType(); char buffer[1]; @@ -652,16 +652,16 @@ EXPECT_TRUE(CommandStorageBackend::GetSessionFilePaths( file_path(), CommandStorageManager::kOther) .empty()); - ASSERT_EQ(0, base::WriteFile(file_path(), "", 0)); + ASSERT_TRUE(base::WriteFile(file_path(), "")); // Not a valid name, as doesn't contain timestamp separator. - ASSERT_EQ(0, base::WriteFile(file_path().DirName().AppendASCII("Session 123"), - "", 0)); + ASSERT_TRUE( + base::WriteFile(file_path().DirName().AppendASCII("Session 123"), "")); // Valid name. - ASSERT_EQ(0, base::WriteFile(file_path().DirName().AppendASCII("Session_124"), - "", 0)); + ASSERT_TRUE( + base::WriteFile(file_path().DirName().AppendASCII("Session_124"), "")); // Valid name, but should not be returned as beginning doesn't match. - ASSERT_EQ( - 0, base::WriteFile(file_path().DirName().AppendASCII("Foo_125"), "", 0)); + ASSERT_TRUE( + base::WriteFile(file_path().DirName().AppendASCII("Foo_125"), "")); auto paths = CommandStorageBackend::GetSessionFilePaths( file_path(), CommandStorageManager::kOther); ASSERT_EQ(1u, paths.size()); @@ -674,14 +674,14 @@ } TEST_F(CommandStorageBackendTest, GetSessionFilesAreSortedByReverseTimestamp) { - ASSERT_EQ(0, base::WriteFile(file_path().DirName().AppendASCII("Session_130"), - "", 0)); - ASSERT_EQ(0, base::WriteFile(file_path().DirName().AppendASCII("Session_120"), - "", 0)); - ASSERT_EQ(0, base::WriteFile(file_path().DirName().AppendASCII("Session_125"), - "", 0)); - ASSERT_EQ(0, base::WriteFile(file_path().DirName().AppendASCII("Session_128"), - "", 0)); + ASSERT_TRUE( + base::WriteFile(file_path().DirName().AppendASCII("Session_130"), "")); + ASSERT_TRUE( + base::WriteFile(file_path().DirName().AppendASCII("Session_120"), "")); + ASSERT_TRUE( + base::WriteFile(file_path().DirName().AppendASCII("Session_125"), "")); + ASSERT_TRUE( + base::WriteFile(file_path().DirName().AppendASCII("Session_128"), "")); auto paths = GetSessionFilePathsSortedByReverseTimestamp(); ASSERT_EQ(4u, paths.size()); EXPECT_EQ("Session_130", paths[0].BaseName().MaybeAsASCII());
diff --git a/components/shared_highlighting/ios/parsing_utils.mm b/components/shared_highlighting/ios/parsing_utils.mm index fc21709..4970ac3f 100644 --- a/components/shared_highlighting/ios/parsing_utils.mm +++ b/components/shared_highlighting/ios/parsing_utils.mm
@@ -28,21 +28,17 @@ return absl::nullopt; } - const base::Value* xValue = - value->FindKeyOfType("x", base::Value::Type::DOUBLE); - const base::Value* yValue = - value->FindKeyOfType("y", base::Value::Type::DOUBLE); - const base::Value* widthValue = - value->FindKeyOfType("width", base::Value::Type::DOUBLE); - const base::Value* heightValue = - value->FindKeyOfType("height", base::Value::Type::DOUBLE); + const base::Value::Dict& dict = value->GetDict(); + absl::optional<double> xValue = dict.FindDouble("x"); + absl::optional<double> yValue = dict.FindDouble("y"); + absl::optional<double> widthValue = dict.FindDouble("width"); + absl::optional<double> heightValue = dict.FindDouble("height"); if (!xValue || !yValue || !widthValue || !heightValue) { return absl::nullopt; } - return CGRectMake(xValue->GetDouble(), yValue->GetDouble(), - widthValue->GetDouble(), heightValue->GetDouble()); + return CGRectMake(*xValue, *yValue, *widthValue, *heightValue); } absl::optional<GURL> ParseURL(const std::string* url_value) {
diff --git a/components/storage_monitor/image_capture_device_manager_unittest.mm b/components/storage_monitor/image_capture_device_manager_unittest.mm index 3ed2c58..0d99e1e 100644 --- a/components/storage_monitor/image_capture_device_manager_unittest.mm +++ b/components/storage_monitor/image_capture_device_manager_unittest.mm
@@ -97,9 +97,7 @@ // filename. Do that here to require a rename. saveAsFilename += ".jpg"; base::FilePath toBeSaved = saveDir.Append(saveAsFilename); - ASSERT_EQ(static_cast<int>(strlen(kTestFileContents)), - base::WriteFile(toBeSaved, kTestFileContents, - strlen(kTestFileContents))); + ASSERT_TRUE(base::WriteFile(toBeSaved, kTestFileContents)); NSMutableDictionary* returnOptions = [NSMutableDictionary dictionaryWithDictionary:options];
diff --git a/components/subresource_filter/content/browser/ruleset_publisher_impl_unittest.cc b/components/subresource_filter/content/browser/ruleset_publisher_impl_unittest.cc index 724eefd..9dc01f7 100644 --- a/components/subresource_filter/content/browser/ruleset_publisher_impl_unittest.cc +++ b/components/subresource_filter/content/browser/ruleset_publisher_impl_unittest.cc
@@ -137,8 +137,7 @@ TEST_F(SubresourceFilterRulesetPublisherImplTest, PublishedRuleset_IsDistributedToExistingAndNewRenderers) { const char kTestFileContents[] = "foobar"; - base::WriteFile(scoped_temp_file(), kTestFileContents, - strlen(kTestFileContents)); + base::WriteFile(scoped_temp_file(), kTestFileContents); RulesetFilePtr file( new base::File(scoped_temp_file(),
diff --git a/components/subresource_filter/content/browser/ruleset_service.cc b/components/subresource_filter/content/browser/ruleset_service.cc index 0ea1935..c0ebdf4 100644 --- a/components/subresource_filter/content/browser/ruleset_service.cc +++ b/components/subresource_filter/content/browser/ruleset_service.cc
@@ -7,6 +7,7 @@ #include <utility> #include "base/check_op.h" +#include "base/containers/span.h" #include "base/files/file_enumerator.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" @@ -15,6 +16,7 @@ #include "base/metrics/histogram_macros.h" #include "base/numerics/safe_conversions.h" #include "base/strings/string_number_conversions.h" +#include "base/strings/string_piece.h" #include "base/task/sequenced_task_runner.h" #include "base/task/thread_pool.h" #include "base/threading/scoped_blocking_call.h" @@ -77,7 +79,7 @@ SentinelFile& operator=(const SentinelFile&) = delete; bool IsPresent() { return base::PathExists(path_); } - bool Create() { return base::WriteFile(path_, nullptr, 0) == 0; } + bool Create() { return base::WriteFile(path_, base::StringPiece()); } bool Remove() { return base::DeleteFile(path_); } private: @@ -378,11 +380,9 @@ } static_assert(sizeof(uint8_t) == sizeof(char), "Expected char = byte."); - const int data_size_in_chars = base::checked_cast<int>(indexed_ruleset_size); - if (base::WriteFile( + if (!base::WriteFile( IndexedRulesetLocator::GetRulesetDataFilePath(scratch_dir.GetPath()), - reinterpret_cast<const char*>(indexed_ruleset_data), - data_size_in_chars) != data_size_in_chars) { + base::make_span(indexed_ruleset_data, indexed_ruleset_size))) { return IndexAndWriteRulesetResult::FAILED_WRITING_RULESET_DATA; }
diff --git a/components/subresource_filter/content/browser/ruleset_service_unittest.cc b/components/subresource_filter/content/browser/ruleset_service_unittest.cc index 51abccc..c8b8daf 100644 --- a/components/subresource_filter/content/browser/ruleset_service_unittest.cc +++ b/components/subresource_filter/content/browser/ruleset_service_unittest.cc
@@ -24,6 +24,7 @@ #include "base/numerics/safe_conversions.h" #include "base/run_loop.h" #include "base/strings/string_number_conversions.h" +#include "base/strings/string_piece.h" #include "base/task/sequenced_task_runner.h" #include "base/task/single_thread_task_runner.h" #include "base/test/metrics/histogram_tester.h" @@ -252,9 +253,7 @@ base::FilePath* path) { ASSERT_NO_FATAL_FAILURE( test_ruleset_creator()->GetUniqueTemporaryPath(path)); - ASSERT_EQ(static_cast<int>(contents.size()), - base::WriteFile(*path, contents.data(), - static_cast<int>(contents.size()))); + ASSERT_TRUE(base::WriteFile(*path, contents)); } void IndexAndStoreAndPublishUpdatedRuleset( @@ -598,13 +597,13 @@ WriteRuleset(test_ruleset_1(), legacy_format_content_version_1); WriteRuleset(test_ruleset_2(), legacy_format_content_version_2); base::WriteFile(GetExpectedSentinelFilePath(legacy_format_content_version_2), - nullptr, 0); + base::StringPiece()); WriteRuleset(test_ruleset_1(), current_format_content_version_1); WriteRuleset(test_ruleset_2(), current_format_content_version_2); WriteRuleset(test_ruleset_3(), current_format_content_version_3); base::WriteFile(GetExpectedSentinelFilePath(current_format_content_version_3), - nullptr, 0); + base::StringPiece()); DeleteObsoleteRulesets(base_dir(), current_format_content_version_2);
diff --git a/components/subresource_filter/core/common/test_ruleset_creator.cc b/components/subresource_filter/core/common/test_ruleset_creator.cc index a02f0a0..59cebf4 100644 --- a/components/subresource_filter/core/common/test_ruleset_creator.cc +++ b/components/subresource_filter/core/common/test_ruleset_creator.cc
@@ -31,11 +31,7 @@ void WriteRulesetContents(const std::vector<uint8_t>& contents, base::FilePath path) { base::ScopedAllowBlockingForTesting allow_blocking; - int ruleset_size_as_int = base::checked_cast<int>(contents.size()); - int num_bytes_written = - base::WriteFile(path, reinterpret_cast<const char*>(contents.data()), - ruleset_size_as_int); - ASSERT_EQ(ruleset_size_as_int, num_bytes_written); + ASSERT_TRUE(base::WriteFile(path, contents)); } std::vector<uint8_t> SerializeUnindexedRulesetWithMultipleRules(
diff --git a/components/subresource_filter/tools/indexing_tool.cc b/components/subresource_filter/tools/indexing_tool.cc index 5b0631e..e5c7b7b 100644 --- a/components/subresource_filter/tools/indexing_tool.cc +++ b/components/subresource_filter/tools/indexing_tool.cc
@@ -6,6 +6,7 @@ #include <utility> +#include "base/containers/span.h" #include "base/files/file.h" #include "base/files/file_util.h" #include "base/numerics/safe_conversions.h" @@ -45,8 +46,7 @@ indexer.Finish(); - base::WriteFile(indexed_path, reinterpret_cast<const char*>(indexer.data()), - base::checked_cast<int>(indexer.size())); + base::WriteFile(indexed_path, base::make_span(indexer)); if (out_checksum) *out_checksum = indexer.GetChecksum(); @@ -69,7 +69,7 @@ std::string version = base::StringPrintf( version_format, content_version.c_str(), subresource_filter::RulesetIndexer::kIndexedFormatVersion, checksum); - base::WriteFile(path, version.data(), version.size()); + base::WriteFile(path, version); } } // namespace subresource_filter
diff --git a/components/subresource_filter/tools/indexing_tool_unittest.cc b/components/subresource_filter/tools/indexing_tool_unittest.cc index db23797..1482da5 100644 --- a/components/subresource_filter/tools/indexing_tool_unittest.cc +++ b/components/subresource_filter/tools/indexing_tool_unittest.cc
@@ -70,8 +70,7 @@ // Write the test unindexed data to a file. const std::vector<uint8_t>& unindexed_data = test_ruleset_pair_.unindexed.contents; - base::WriteFile(path, reinterpret_cast<const char*>(unindexed_data.data()), - base::checked_cast<int>(unindexed_data.size())); + base::WriteFile(path, unindexed_data); } int file_count_ = 0;
diff --git a/components/subresource_filter/tools/ruleset_converter/rule_stream_unittest.cc b/components/subresource_filter/tools/ruleset_converter/rule_stream_unittest.cc index c043688..e37c1d2c 100644 --- a/components/subresource_filter/tools/ruleset_converter/rule_stream_unittest.cc +++ b/components/subresource_filter/tools/ruleset_converter/rule_stream_unittest.cc
@@ -329,8 +329,7 @@ // Output all the rules to the |source_ruleset| file. std::string joined_rules = base::JoinString(text_rules, "\n"); - base::WriteFile(source_ruleset.ruleset_path(), joined_rules.data(), - joined_rules.size()); + base::WriteFile(source_ruleset.ruleset_path(), joined_rules); // Filter out the rules with parse errors, and save the rest to |contents|. TestRulesetContents contents;
diff --git a/components/upload_list/combining_upload_list_unittest.cc b/components/upload_list/combining_upload_list_unittest.cc index 229e316..ee116be 100644 --- a/components/upload_list/combining_upload_list_unittest.cc +++ b/components/upload_list/combining_upload_list_unittest.cc
@@ -53,22 +53,19 @@ 1614008000,ddee0008 1614012000,ddee0012 )"; - ASSERT_GT(base::WriteFile(first_log_path(), kFirstList, strlen(kFirstList)), - 0); + ASSERT_TRUE(base::WriteFile(first_log_path(), kFirstList)); constexpr char kSecondList[] = R"( {"upload_time":"1614002000","upload_id":"ddee0002"} {"upload_time":"1614006000","upload_id":"ddee0006"} {"upload_time":"1614010000","upload_id":"ddee0010"} )"; - ASSERT_GT( - base::WriteFile(second_log_path(), kSecondList, strlen(kSecondList)), 0); + ASSERT_TRUE(base::WriteFile(second_log_path(), kSecondList)); constexpr char kThirdList[] = R"( {"upload_time":"1614014000","upload_id":"ddee0014"} )"; - ASSERT_GT(base::WriteFile(third_log_path(), kThirdList, strlen(kThirdList)), - 0); + ASSERT_TRUE(base::WriteFile(third_log_path(), kThirdList)); std::vector<scoped_refptr<UploadList>> sublists = { first_reader_, second_reader_, third_reader_}; @@ -138,25 +135,19 @@ {"capture_time":"1614004000","upload_id":"ddee0004","upload_time":"1614999999"} {"capture_time":"1614007000","upload_id":"ddee0007","upload_time":"1600000000"} )"; - ASSERT_GT(base::WriteFile(first_log_path(), kUploadAndCaptureTimes, - strlen(kUploadAndCaptureTimes)), - 0); + ASSERT_TRUE(base::WriteFile(first_log_path(), kUploadAndCaptureTimes)); constexpr char kJustCaptureTimes[] = R"( {"capture_time":"1614002000","upload_id":"ddee0002"} {"capture_time":"1614005000","upload_id":"ddee0005"} {"capture_time":"1614008000","upload_id":"ddee0008"} )"; - ASSERT_GT(base::WriteFile(second_log_path(), kJustCaptureTimes, - strlen(kJustCaptureTimes)), - 0); + ASSERT_TRUE(base::WriteFile(second_log_path(), kJustCaptureTimes)); constexpr char kJustUploadTimes[] = R"( {"upload_time":"1614003000","upload_id":"ddee0003"} {"upload_time":"1614006000","upload_id":"ddee0006"} {"upload_time":"1614009000","upload_id":"ddee0009"} )"; - ASSERT_GT(base::WriteFile(third_log_path(), kJustUploadTimes, - strlen(kJustUploadTimes)), - 0); + ASSERT_TRUE(base::WriteFile(third_log_path(), kJustUploadTimes)); std::vector<scoped_refptr<UploadList>> sublists = { first_reader_, second_reader_, third_reader_}; @@ -222,25 +213,19 @@ {"capture_time":"1614004000","upload_id":"ddee0004","upload_time":"1614999999"} {"capture_time":"1614007000","upload_id":"ddee0007","upload_time":"1600000000"} )"; - ASSERT_GT(base::WriteFile(first_log_path(), kUploadAndCaptureTimes, - strlen(kUploadAndCaptureTimes)), - 0); + ASSERT_TRUE(base::WriteFile(first_log_path(), kUploadAndCaptureTimes)); constexpr char kJustCaptureTimes[] = R"( {"capture_time":"1614002000","upload_id":"ddee0002"} {"capture_time":"1614005000","upload_id":"ddee0005"} {"capture_time":"1614008000","upload_id":"ddee0008"} )"; - ASSERT_GT(base::WriteFile(second_log_path(), kJustCaptureTimes, - strlen(kJustCaptureTimes)), - 0); + ASSERT_TRUE(base::WriteFile(second_log_path(), kJustCaptureTimes)); constexpr char kJustUploadTimes[] = R"( {"upload_time":"1614003000","upload_id":"ddee0003"} {"upload_time":"1614006000","upload_id":"ddee0006"} {"upload_time":"1614009000","upload_id":"ddee0009"} )"; - ASSERT_GT(base::WriteFile(third_log_path(), kJustUploadTimes, - strlen(kJustUploadTimes)), - 0); + ASSERT_TRUE(base::WriteFile(third_log_path(), kJustUploadTimes)); std::vector<scoped_refptr<UploadList>> sublists = { first_reader_, second_reader_, third_reader_};
diff --git a/components/upload_list/text_log_upload_list.cc b/components/upload_list/text_log_upload_list.cc index 1c698df4..151d15d 100644 --- a/components/upload_list/text_log_upload_list.cc +++ b/components/upload_list/text_log_upload_list.cc
@@ -238,8 +238,7 @@ if (new_contents.size() == 0) { base::DeleteFile(upload_log_path_); } else { - base::WriteFile(upload_log_path_, new_contents.c_str(), - new_contents.size()); + base::WriteFile(upload_log_path_, new_contents); } }
diff --git a/components/upload_list/text_log_upload_list_unittest.cc b/components/upload_list/text_log_upload_list_unittest.cc index 3764af80..4c883c259 100644 --- a/components/upload_list/text_log_upload_list_unittest.cc +++ b/components/upload_list/text_log_upload_list_unittest.cc
@@ -39,9 +39,7 @@ protected: void WriteUploadLog(const std::string& log_data) { - ASSERT_GT(base::WriteFile(log_path(), log_data.c_str(), - static_cast<int>(log_data.size())), - 0); + ASSERT_TRUE(base::WriteFile(log_path(), log_data)); } base::FilePath log_path() {
diff --git a/components/visitedlink/browser/visitedlink_event_listener.cc b/components/visitedlink/browser/visitedlink_event_listener.cc index 7808ff0..641f2f0e 100644 --- a/components/visitedlink/browser/visitedlink_event_listener.cc +++ b/components/visitedlink/browser/visitedlink_event_listener.cc
@@ -122,8 +122,6 @@ content::BrowserContext* browser_context) : coalesce_timer_(&default_coalesce_timer_), browser_context_(browser_context) { - registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, - content::NotificationService::AllBrowserContextsAndSources()); registrar_.Add(this, content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED, content::NotificationService::AllBrowserContextsAndSources()); } @@ -199,6 +197,18 @@ updaters_[rph->GetID()] = std::make_unique<VisitedLinkUpdater>(rph->GetID()); updaters_[rph->GetID()]->SendVisitedLinkTable(&table_region_); + + if (!host_observation_.IsObservingSource(rph)) { + host_observation_.AddObservation(rph); + } +} + +void VisitedLinkEventListener::RenderProcessHostDestroyed( + content::RenderProcessHost* host) { + if (host_observation_.IsObservingSource(host)) { + updaters_.erase(host->GetID()); + host_observation_.RemoveObservation(host); + } } void VisitedLinkEventListener::Observe( @@ -206,14 +216,6 @@ const content::NotificationSource& source, const content::NotificationDetails& details) { switch (type) { - case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: { - content::RenderProcessHost* process = - content::Source<content::RenderProcessHost>(source).ptr(); - if (updaters_.count(process->GetID())) { - updaters_.erase(process->GetID()); - } - break; - } case content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED: { RenderWidgetHost* widget = content::Source<RenderWidgetHost>(source).ptr();
diff --git a/components/visitedlink/browser/visitedlink_event_listener.h b/components/visitedlink/browser/visitedlink_event_listener.h index 3df9903..b148c0c 100644 --- a/components/visitedlink/browser/visitedlink_event_listener.h +++ b/components/visitedlink/browser/visitedlink_event_listener.h
@@ -10,11 +10,13 @@ #include "base/memory/raw_ptr.h" #include "base/memory/read_only_shared_memory_region.h" +#include "base/scoped_multi_source_observation.h" #include "base/timer/timer.h" #include "components/visitedlink/browser/visitedlink_writer.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" #include "content/public/browser/render_process_host_creation_observer.h" +#include "content/public/browser/render_process_host_observer.h" namespace content { class BrowserContext; @@ -30,6 +32,7 @@ class VisitedLinkEventListener : public VisitedLinkWriter::Listener, public content::NotificationObserver, + public content::RenderProcessHostObserver, public content::RenderProcessHostCreationObserver { public: explicit VisitedLinkEventListener(content::BrowserContext* browser_context); @@ -50,6 +53,9 @@ // content::RenderProcessHostCreationObserver: void OnRenderProcessHostCreated(content::RenderProcessHost* rph) override; + // content::RenderProcessHostObserver: + void RenderProcessHostDestroyed(content::RenderProcessHost* host) override; + private: void CommitVisitedLinks(); @@ -67,11 +73,14 @@ raw_ptr<base::OneShotTimer> coalesce_timer_; VisitedLinkCommon::Fingerprints pending_visited_links_; + base::ScopedMultiSourceObservation<content::RenderProcessHost, + content::RenderProcessHostObserver> + host_observation_{this}; + content::NotificationRegistrar registrar_; // Map between renderer child ids and their VisitedLinkUpdater. - typedef std::map<int, std::unique_ptr<VisitedLinkUpdater>> Updaters; - Updaters updaters_; + std::map<int, std::unique_ptr<VisitedLinkUpdater>> updaters_; base::ReadOnlySharedMemoryRegion table_region_;
diff --git a/components/visitedlink/browser/visitedlink_writer.cc b/components/visitedlink/browser/visitedlink_writer.cc index 0be6871..ca49f06e 100644 --- a/components/visitedlink/browser/visitedlink_writer.cc +++ b/components/visitedlink/browser/visitedlink_writer.cc
@@ -1104,7 +1104,7 @@ WriteToFile(scoped_file_holder_.get(), first_hash * sizeof(Fingerprint) + kFileHeaderSize, &hash_table_[first_hash], - (table_length_ - first_hash + 1) * sizeof(Fingerprint)); + (table_length_ - first_hash) * sizeof(Fingerprint)); // Now do 0->last_lash. WriteToFile(scoped_file_holder_.get(), kFileHeaderSize, hash_table_,
diff --git a/components/visitedlink/browser/visitedlink_writer.h b/components/visitedlink/browser/visitedlink_writer.h index 03e3a9d0..31981ba 100644 --- a/components/visitedlink/browser/visitedlink_writer.h +++ b/components/visitedlink/browser/visitedlink_writer.h
@@ -177,6 +177,7 @@ FRIEND_TEST_ALL_PREFIXES(VisitedLinkTest, Delete); FRIEND_TEST_ALL_PREFIXES(VisitedLinkTest, BigDelete); FRIEND_TEST_ALL_PREFIXES(VisitedLinkTest, BigImport); + FRIEND_TEST_ALL_PREFIXES(VisitedLinkTest, HashRangeWraparound); // Keeps the result of loading the table from the database file to the UI // thread.
diff --git a/components/visitedlink/test/visitedlink_unittest.cc b/components/visitedlink/test/visitedlink_unittest.cc index 79a80ef..a71483d 100644 --- a/components/visitedlink/test/visitedlink_unittest.cc +++ b/components/visitedlink/test/visitedlink_unittest.cc
@@ -26,10 +26,9 @@ #include "components/visitedlink/browser/visitedlink_event_listener.h" #include "components/visitedlink/browser/visitedlink_writer.h" #include "components/visitedlink/common/visitedlink.mojom.h" +#include "components/visitedlink/common/visitedlink_common.h" #include "components/visitedlink/renderer/visitedlink_reader.h" #include "content/public/browser/browser_thread.h" -#include "content/public/browser/notification_service.h" -#include "content/public/browser/notification_types.h" #include "content/public/test/browser_task_environment.h" #include "content/public/test/mock_render_process_host.h" #include "content/public/test/test_browser_context.h" @@ -546,6 +545,39 @@ EXPECT_EQ(1, listener->completely_reset_count()); } +TEST_F(VisitedLinkTest, HashRangeWraparound) { + ASSERT_TRUE(InitVisited(0, true, true)); + + // Create two fingerprints that, when added, will create a wraparound hash + // range. + const VisitedLinkCommon::Fingerprint kFingerprint0 = + writer_->DefaultTableSize() - 1; + const VisitedLinkCommon::Fingerprint kFingerprint1 = kFingerprint0 + 1; + + // Add the two fingerprints. + const VisitedLinkCommon::Hash hash0 = + writer_->AddFingerprint(kFingerprint0, false); + const VisitedLinkCommon::Hash hash1 = + writer_->AddFingerprint(kFingerprint1, false); + + // Verify the hashes form a range that wraps around. + EXPECT_EQ(hash0, VisitedLinkCommon::Hash(writer_->DefaultTableSize() - 1)); + EXPECT_EQ(hash1, 0); + + // Write the database to file. + writer_->WriteUsedItemCountToFile(); + writer_->WriteHashRangeToFile(hash0, hash1); + + // Close and reopen the database. + ClearDB(); + ASSERT_TRUE(InitVisited(0, true, true)); + + // Verify database contents. + ASSERT_EQ(writer_->GetUsedCount(), 2); + ASSERT_TRUE(writer_->IsVisited(kFingerprint0)); + ASSERT_TRUE(writer_->IsVisited(kFingerprint1)); +} + class VisitCountingContext : public mojom::VisitedLinkNotificationSink { public: VisitCountingContext() @@ -636,13 +668,6 @@ delete; VisitRelayingRenderProcessHost& operator=( const VisitRelayingRenderProcessHost&) = delete; - - ~VisitRelayingRenderProcessHost() override { - content::NotificationService::current()->Notify( - content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, - content::Source<content::RenderProcessHost>(this), - content::NotificationService::NoDetails()); - } }; class VisitedLinkRenderProcessHostFactory
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index d05a7e6..473b1ada 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -1193,8 +1193,6 @@ "loader/prefetch_url_loader.h", "loader/prefetch_url_loader_service.cc", "loader/prefetch_url_loader_service.h", - "loader/resource_timing_utils.cc", - "loader/resource_timing_utils.h", "loader/shared_cors_origin_access_list_impl.cc", "loader/shared_cors_origin_access_list_impl.h", "loader/url_loader_throttles.cc",
diff --git a/content/browser/background_fetch/mock_background_fetch_delegate.cc b/content/browser/background_fetch/mock_background_fetch_delegate.cc index f241493..f5f33ca 100644 --- a/content/browser/background_fetch/mock_background_fetch_delegate.cc +++ b/content/browser/background_fetch/mock_background_fetch_delegate.cc
@@ -147,9 +147,7 @@ CHECK(base::CreateTemporaryFileInDir(temp_directory_.GetPath(), &response_path)); - CHECK_NE(/* error= */ -1, - base::WriteFile(response_path, test_response->data.c_str(), - test_response->data.size())); + CHECK(base::WriteFile(response_path, test_response->data)); PostAbortCheckingTask( job_unique_id,
diff --git a/content/browser/cache_storage/cache_storage.cc b/content/browser/cache_storage/cache_storage.cc index fcd718e8..f686806 100644 --- a/content/browser/cache_storage/cache_storage.cc +++ b/content/browser/cache_storage/cache_storage.cc
@@ -399,8 +399,7 @@ const std::string& data, scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy, const storage::BucketLocator& bucket_locator) { - int bytes_written = base::WriteFile(tmp_path, data.c_str(), data.size()); - if (bytes_written != base::checked_cast<int>(data.size())) { + if (!base::WriteFile(tmp_path, data)) { base::DeleteFile(tmp_path); quota_manager_proxy->NotifyWriteFailed(bucket_locator.storage_key); return false;
diff --git a/content/browser/devtools/devtools_http_handler.cc b/content/browser/devtools/devtools_http_handler.cc index b91c420..3083bd8 100644 --- a/content/browser/devtools/devtools_http_handler.cc +++ b/content/browser/devtools/devtools_http_handler.cc
@@ -301,8 +301,7 @@ output_directory.Append(kDevToolsActivePortFileName); std::string port_target_string = base::StringPrintf( "%d\n%s", ip_address->port(), browser_guid.c_str()); - if (base::WriteFile(path, port_target_string.c_str(), - static_cast<int>(port_target_string.length())) < 0) { + if (!base::WriteFile(path, port_target_string)) { PLOG(ERROR) << "Error writing DevTools active port to file " << path; } }
diff --git a/content/browser/download/download_browsertest.cc b/content/browser/download/download_browsertest.cc index d0eacd2..a84e713 100644 --- a/content/browser/download/download_browsertest.cc +++ b/content/browser/download/download_browsertest.cc
@@ -3235,8 +3235,7 @@ parameters.pattern_generator_seed, 0, kIntermediateSize); { base::ScopedAllowBlockingForTesting allow_blocking; - ASSERT_EQ(kIntermediateSize, base::WriteFile(intermediate_file_path, - output.data(), output.size())); + ASSERT_TRUE(base::WriteFile(intermediate_file_path, output)); } url_chain.push_back(server_url); @@ -3291,8 +3290,7 @@ parameters.pattern_generator_seed + 1, 0, kIntermediateSize); { base::ScopedAllowBlockingForTesting allow_blocking; - ASSERT_EQ(kIntermediateSize, base::WriteFile(intermediate_file_path, - output.data(), output.size())); + ASSERT_TRUE(base::WriteFile(intermediate_file_path, output)); } url_chain.push_back(server_url); @@ -3348,8 +3346,7 @@ parameters.pattern_generator_seed, 0, kIntermediateSize); { base::ScopedAllowBlockingForTesting allow_blocking; - ASSERT_EQ(kIntermediateSize, base::WriteFile(intermediate_file_path, - output.data(), output.size())); + ASSERT_TRUE(base::WriteFile(intermediate_file_path, output)); } // SHA-256 hash of the pattern bytes in buffer. static const uint8_t kPartialHash[] = { @@ -3416,8 +3413,8 @@ std::vector<char> buffer(kIntermediateSize); { base::ScopedAllowBlockingForTesting allow_blocking; - ASSERT_EQ(kIntermediateSize, base::WriteFile(intermediate_file_path, - buffer.data(), buffer.size())); + ASSERT_TRUE(base::WriteFile(intermediate_file_path, + {buffer.data(), buffer.size()})); } // SHA-256 hash of the expected pattern bytes in buffer. This doesn't match // the current contents of the intermediate file which should all be 0. @@ -3501,9 +3498,7 @@ parameters.pattern_generator_seed, 0, kIntermediateSize - 100); { base::ScopedAllowBlockingForTesting allow_blocking; - ASSERT_EQ( - kIntermediateSize - 100, - base::WriteFile(intermediate_file_path, output.data(), output.size())); + ASSERT_TRUE(base::WriteFile(intermediate_file_path, output)); } url_chain.push_back(server_url); @@ -3577,9 +3572,7 @@ parameters.pattern_generator_seed, 0, kIntermediateSize + 100); { base::ScopedAllowBlockingForTesting allow_blocking; - ASSERT_EQ( - kIntermediateSize + 100, - base::WriteFile(intermediate_file_path, output.data(), output.size())); + ASSERT_TRUE(base::WriteFile(intermediate_file_path, output)); } url_chain.push_back(server_url);
diff --git a/content/browser/indexed_db/indexed_db_browsertest.cc b/content/browser/indexed_db/indexed_db_browsertest.cc index 9f0de33..d4a1cf9a 100644 --- a/content/browser/indexed_db/indexed_db_browsertest.cc +++ b/content/browser/indexed_db/indexed_db_browsertest.cc
@@ -1348,7 +1348,7 @@ EXPECT_TRUE(base::PathExists(first_blob)); EXPECT_FALSE(base::PathExists(corrupt_blob)); const char kCorruptData[] = "corrupt"; - base::WriteFile(corrupt_blob, kCorruptData, sizeof(kCorruptData)); + base::WriteFile(corrupt_blob, kCorruptData); } SimpleTest(embedded_test_server()->GetURL(test_file));
diff --git a/content/browser/interest_group/ad_auction_service_impl_unittest.cc b/content/browser/interest_group/ad_auction_service_impl_unittest.cc index edfda65f9..afc96d4 100644 --- a/content/browser/interest_group/ad_auction_service_impl_unittest.cc +++ b/content/browser/interest_group/ad_auction_service_impl_unittest.cc
@@ -1148,10 +1148,9 @@ interest_group.priority_signals_overrides = {{{"old1", 1}, {"old2", 2}}}; interest_group.seller_capabilities.emplace(); interest_group.seller_capabilities->insert(std::make_pair( - kOriginA, - blink::InterestGroup::SellerCapabilities::kInterestGroupCounts)); + kOriginA, blink::SellerCapabilities::kInterestGroupCounts)); interest_group.all_sellers_capabilities = - blink::InterestGroup::SellerCapabilities::kLatencyStats; + blink::SellerCapabilities::kLatencyStats; interest_group.daily_update_url = kUpdateUrlA; interest_group.bidding_url = kBiddingLogicUrlA; interest_group.trusted_bidding_signals_url = kTrustedBiddingSignalsUrlA; @@ -1198,11 +1197,11 @@ expected_priority_signals_overrides); EXPECT_EQ(group.all_sellers_capabilities, - blink::InterestGroup::SellerCapabilities::kInterestGroupCounts); + blink::SellerCapabilities::kInterestGroupCounts); ASSERT_TRUE(group.seller_capabilities); ASSERT_EQ(group.seller_capabilities->size(), 1u); EXPECT_EQ(group.seller_capabilities->at(kOriginA), - blink::InterestGroup::SellerCapabilities::kLatencyStats); + blink::SellerCapabilities::kLatencyStats); ASSERT_TRUE(group.bidding_url.has_value()); EXPECT_EQ(group.bidding_url->spec(), base::StringPrintf("%s/interest_group/new_bidding_logic.js", @@ -2015,8 +2014,7 @@ GetInterestGroupsForOwner(kOriginA); ASSERT_EQ(groups.size(), 1u); const auto& group = groups[0].interest_group; - EXPECT_EQ(group.all_sellers_capabilities, - blink::InterestGroup::SellerCapabilitiesType()); + EXPECT_EQ(group.all_sellers_capabilities, blink::SellerCapabilitiesType()); EXPECT_FALSE(group.seller_capabilities); EXPECT_EQ(group.bidding_url, kBiddingLogicUrlA); }
diff --git a/content/browser/interest_group/auction_runner_unittest.cc b/content/browser/interest_group/auction_runner_unittest.cc index a4865c86..02d5d7b 100644 --- a/content/browser/interest_group/auction_runner_unittest.cc +++ b/content/browser/interest_group/auction_runner_unittest.cc
@@ -1298,8 +1298,9 @@ blink::AuctionConfig::BuyerTimeouts buyer_cumulative_timeouts; buyer_cumulative_timeouts.per_buyer_timeouts.emplace(); buyer_cumulative_timeouts.per_buyer_timeouts.value()[kBidder1] = - base::Milliseconds(12345); - buyer_cumulative_timeouts.all_buyers_timeout = base::Milliseconds(23456); + kBidder1CumulativeTimeout; + buyer_cumulative_timeouts.all_buyers_timeout = + kAllBuyersCumulativeTimeout; return blink::AuctionConfig::MaybePromiseBuyerTimeouts::FromValue( std::move(buyer_cumulative_timeouts)); } @@ -1444,11 +1445,10 @@ base::Unretained(this))); } - const Result& RunAuctionAndWait(const GURL& seller_decision_logic_url, - std::vector<StorageInterestGroup> bidders) { + void RunAuctionAndWait(const GURL& seller_decision_logic_url, + std::vector<StorageInterestGroup> bidders) { StartAuction(seller_decision_logic_url, std::move(bidders)); auction_run_loop_->Run(); - return result_; } void OnAuctionComplete( @@ -1662,20 +1662,23 @@ StartAuction(kSellerUrl, std::move(bidders)); } - const Result& RunStandardAuction( - bool request_trusted_bidding_signals = true) { + void RunStandardAuction(bool request_trusted_bidding_signals = true) { StartStandardAuction(request_trusted_bidding_signals); auction_run_loop_->Run(); - return result_; } // Starts the standard auction with the mock worklet service, and waits for // the service to receive the worklet construction calls. - void StartStandardAuctionWithMockService() { + // + // `num_expected_bidder_worklets` is the number of bidder worklets that are + // expected to be created. + void StartStandardAuctionWithMockService( + int num_expected_bidder_worklets = 2) { UseMockWorkletService(); StartStandardAuction(); mock_auction_process_manager_->WaitForWorklets( - /*num_bidders=*/2, /*num_sellers=*/1 + component_auctions_.size()); + /*num_bidders=*/num_expected_bidder_worklets, + /*num_sellers=*/1 + component_auctions_.size()); } // Runs an auction that exercises the extended private aggregation buyers @@ -2031,6 +2034,7 @@ const url::Origin kBidder1 = url::Origin::Create(kBidder1Url); const InterestGroupKey kBidder1Key{kBidder1, kBidder1Name}; const GURL kBidder1TrustedSignalsUrl{"https://adplatform.com/signals1"}; + const base::TimeDelta kBidder1CumulativeTimeout = base::Milliseconds(12345); const GURL kBidder2Url{"https://anotheradthing.com/bids.js"}; const url::Origin kBidder2 = url::Origin::Create(kBidder2Url); @@ -2038,6 +2042,13 @@ const InterestGroupKey kBidder2Key{kBidder2, kBidder2Name}; const GURL kBidder2TrustedSignalsUrl{"https://anotheradthing.com/signals2"}; + const base::TimeDelta kAllBuyersCumulativeTimeout = base::Milliseconds(23456); + + // Timeout tests can wait until this amount before a timeout, make sure + // nothing has happened, and then wait this amount, and check the timeout + // happened. + const base::TimeDelta kTinyTime = base::Milliseconds(1); + absl::optional<std::vector<url::Origin>> interest_group_buyers_ = { {kBidder1, kBidder2}}; @@ -2465,20 +2476,20 @@ "&interestGroupNames=Another+Ad+Thing"), kBidder2SignalsJson); - const Result& res = RunStandardAuction(); - EXPECT_FALSE(res.manually_aborted); + RunStandardAuction(); + EXPECT_FALSE(result_.manually_aborted); EXPECT_EQ(kBidder2Key, result_.winning_group_id); - EXPECT_EQ(GURL("https://ad2.com/"), res.ad_url); + EXPECT_EQ(GURL("https://ad2.com/"), result_.ad_url); EXPECT_EQ(std::vector<GURL>{GURL("https://ad2.com-component1.com")}, - res.ad_component_urls); + result_.ad_component_urls); EXPECT_THAT( - res.report_urls, + result_.report_urls, testing::UnorderedElementsAre( GURL("https://reporting.example.com/?highestScoringOtherBid=1&bid=2"), ReportWinUrl(/*bid=*/2, /*highest_scoring_other_bid=*/1, /*made_highest_scoring_other_bid=*/false))); EXPECT_THAT( - res.ad_beacon_map, + result_.ad_beacon_map, testing::UnorderedElementsAre( testing::Pair(ReportingDestination::kSeller, testing::ElementsAre(testing::Pair( @@ -2507,7 +2518,7 @@ kExpectedReportResultPrivateAggregationRequest)))); EXPECT_THAT( - res.private_aggregation_event_map, + result_.private_aggregation_event_map, testing::UnorderedElementsAre(testing::Pair( "click", ElementsAreRequests( @@ -2518,7 +2529,7 @@ testing::UnorderedElementsAre(kBidder1Key, kBidder2Key)); EXPECT_EQ(R"({"render_url":"https://ad2.com/"})", result_.winning_group_ad_metadata); - EXPECT_TRUE(res.errors.empty()); + EXPECT_TRUE(result_.errors.empty()); CheckHistograms(InterestGroupAuction::AuctionResult::kSuccess, /*expected_interest_groups=*/2, /*expected_owners=*/2, /*expected_sellers=*/1); @@ -3889,12 +3900,12 @@ "&interestGroupNames=Another+Ad+Thing"), kBidder2SignalsJson); - const Result& res = RunStandardAuction(); + RunStandardAuction(); EXPECT_EQ(kBidder1Key, result_.winning_group_id); - EXPECT_EQ(GURL("https://ad1.com/"), res.ad_url); + EXPECT_EQ(GURL("https://ad1.com/"), result_.ad_url); EXPECT_EQ(std::vector<GURL>{GURL("https://ad1.com-component1.com")}, - res.ad_component_urls); - EXPECT_THAT(res.report_urls, + result_.ad_component_urls); + EXPECT_THAT(result_.report_urls, testing::UnorderedElementsAre( GURL("https://reporting.example.com/1"), GURL("https://buyer-reporting.example.com/1"))); @@ -3934,7 +3945,7 @@ EXPECT_EQ(R"({"render_url":"https://ad1.com/","metadata":{"ads": true}})", result_.winning_group_ad_metadata); EXPECT_THAT( - res.errors, + result_.errors, testing::ElementsAre("Failed to load https://anotheradthing.com/bids.js " "HTTP status = 404 Not Found.")); CheckHistograms(InterestGroupAuction::AuctionResult::kSuccess, @@ -4048,12 +4059,12 @@ "&interestGroupNames=Another+Ad+Thing"), kBidder2SignalsJson); - const Result& res = RunStandardAuction(); + RunStandardAuction(); EXPECT_EQ(kBidder1Key, result_.winning_group_id); - EXPECT_EQ(GURL("https://ad1.com/"), res.ad_url); + EXPECT_EQ(GURL("https://ad1.com/"), result_.ad_url); EXPECT_EQ(std::vector<GURL>{GURL("https://ad1.com-component1.com")}, - res.ad_component_urls); - EXPECT_THAT(res.report_urls, + result_.ad_component_urls); + EXPECT_THAT(result_.report_urls, testing::UnorderedElementsAre( GURL("https://reporting.example.com/1"), GURL("https://buyer-reporting.example.com/1"))); @@ -4092,7 +4103,7 @@ testing::UnorderedElementsAre(kBidder1Key)); EXPECT_EQ(R"({"render_url":"https://ad1.com/","metadata":{"ads": true}})", result_.winning_group_ad_metadata); - EXPECT_THAT(res.errors, + EXPECT_THAT(result_.errors, testing::ElementsAre("https://anotheradthing.com/bids.js " "`generateBid` is not a function.")); CheckHistograms(InterestGroupAuction::AuctionResult::kSuccess, @@ -4119,15 +4130,16 @@ "&interestGroupNames=Another+Ad+Thing"), kBidder2SignalsJson); - const Result& res = RunStandardAuction(); - EXPECT_FALSE(res.winning_group_id); - EXPECT_FALSE(res.ad_url); - EXPECT_TRUE(res.ad_component_urls.empty()); + RunStandardAuction(); + EXPECT_FALSE(result_.winning_group_id); + EXPECT_FALSE(result_.ad_url); + EXPECT_TRUE(result_.ad_component_urls.empty()); EXPECT_TRUE( private_aggregation_manager_.TakePrivateAggregationRequests().empty()); - EXPECT_TRUE(res.private_aggregation_event_map.empty()); - EXPECT_THAT(res.interest_groups_that_bid, testing::UnorderedElementsAre()); - EXPECT_THAT(res.errors, + EXPECT_TRUE(result_.private_aggregation_event_map.empty()); + EXPECT_THAT(result_.interest_groups_that_bid, + testing::UnorderedElementsAre()); + EXPECT_THAT(result_.errors, testing::UnorderedElementsAre( "Failed to load https://adplatform.com/offers.js " "HTTP status = 404 Not Found.", @@ -4160,16 +4172,17 @@ "&interestGroupNames=Another+Ad+Thing"), kBidder2SignalsJson); - const Result& res = RunStandardAuction(); - EXPECT_FALSE(res.winning_group_id); - EXPECT_FALSE(res.ad_url); - EXPECT_TRUE(res.ad_component_urls.empty()); + RunStandardAuction(); + EXPECT_FALSE(result_.winning_group_id); + EXPECT_FALSE(result_.ad_url); + EXPECT_TRUE(result_.ad_component_urls.empty()); EXPECT_TRUE( private_aggregation_manager_.TakePrivateAggregationRequests().empty()); - EXPECT_TRUE(res.private_aggregation_event_map.empty()); - EXPECT_THAT(res.interest_groups_that_bid, testing::UnorderedElementsAre()); + EXPECT_TRUE(result_.private_aggregation_event_map.empty()); + EXPECT_THAT(result_.interest_groups_that_bid, + testing::UnorderedElementsAre()); EXPECT_THAT( - res.errors, + result_.errors, testing::UnorderedElementsAre( "https://adplatform.com/offers.js `generateBid` is not a function.", "https://anotheradthing.com/bids.js `generateBid` is not a " @@ -4209,10 +4222,10 @@ "&interestGroupNames=Another+Ad+Thing"), kBidder2SignalsJson); - const Result& res = RunStandardAuction(); - EXPECT_FALSE(res.winning_group_id); - EXPECT_FALSE(res.ad_url); - EXPECT_TRUE(res.ad_component_urls.empty()); + RunStandardAuction(); + EXPECT_FALSE(result_.winning_group_id); + EXPECT_FALSE(result_.ad_url); + EXPECT_TRUE(result_.ad_component_urls.empty()); EXPECT_THAT( private_aggregation_manager_.TakePrivateAggregationRequests(), testing::UnorderedElementsAre( @@ -4225,11 +4238,11 @@ EXPECT_TRUE(result_.private_aggregation_event_map.empty()); EXPECT_THAT(result_.interest_groups_that_bid, testing::UnorderedElementsAre(kBidder1Key, kBidder2Key)); - EXPECT_THAT(res.errors, testing::UnorderedElementsAre( - "https://adstuff.publisher1.com/auction.js " - "`scoreAd` is not a function.", - "https://adstuff.publisher1.com/auction.js " - "`scoreAd` is not a function.")); + EXPECT_THAT(result_.errors, testing::UnorderedElementsAre( + "https://adstuff.publisher1.com/auction.js " + "`scoreAd` is not a function.", + "https://adstuff.publisher1.com/auction.js " + "`scoreAd` is not a function.")); CheckHistograms(InterestGroupAuction::AuctionResult::kAllBidsRejected, /*expected_interest_groups=*/2, /*expected_owners=*/2, /*expected_sellers=*/1); @@ -4262,12 +4275,12 @@ "&interestGroupNames=Another+Ad+Thing"), kBidder2SignalsJson); - const Result& res = RunStandardAuction(); + RunStandardAuction(); EXPECT_EQ(kBidder1Key, result_.winning_group_id); - EXPECT_EQ(GURL("https://ad1.com/"), res.ad_url); + EXPECT_EQ(GURL("https://ad1.com/"), result_.ad_url); EXPECT_EQ(std::vector<GURL>{GURL("https://ad1.com-component1.com")}, - res.ad_component_urls); - EXPECT_THAT(res.report_urls, + result_.ad_component_urls); + EXPECT_THAT(result_.report_urls, testing::UnorderedElementsAre( GURL("https://reporting.example.com/1"), GURL("https://buyer-reporting.example.com/1"))); @@ -4310,7 +4323,7 @@ testing::UnorderedElementsAre(kBidder1Key, kBidder2Key)); EXPECT_EQ(R"({"render_url":"https://ad1.com/","metadata":{"ads": true}})", result_.winning_group_ad_metadata); - EXPECT_THAT(res.errors, testing::ElementsAre()); + EXPECT_THAT(result_.errors, testing::ElementsAre()); CheckHistograms(InterestGroupAuction::AuctionResult::kSuccess, /*expected_interest_groups=*/2, /*expected_owners=*/2, /*expected_sellers=*/1); @@ -4321,17 +4334,18 @@ // Tests to make sure that if seller script fails the other fetches are // cancelled, too. url_loader_factory_.AddResponse(kSellerUrl.spec(), "", net::HTTP_NOT_FOUND); - const Result& res = RunStandardAuction(); - EXPECT_FALSE(res.winning_group_id); - EXPECT_FALSE(res.ad_url); - EXPECT_TRUE(res.ad_component_urls.empty()); + RunStandardAuction(); + EXPECT_FALSE(result_.winning_group_id); + EXPECT_FALSE(result_.ad_url); + EXPECT_TRUE(result_.ad_component_urls.empty()); EXPECT_TRUE( private_aggregation_manager_.TakePrivateAggregationRequests().empty()); - EXPECT_TRUE(res.private_aggregation_event_map.empty()); + EXPECT_TRUE(result_.private_aggregation_event_map.empty()); EXPECT_EQ(0, url_loader_factory_.NumPending()); - EXPECT_THAT(res.interest_groups_that_bid, testing::UnorderedElementsAre()); - EXPECT_THAT(res.errors, + EXPECT_THAT(result_.interest_groups_that_bid, + testing::UnorderedElementsAre()); + EXPECT_THAT(result_.errors, testing::ElementsAre( "Failed to load https://adstuff.publisher1.com/auction.js " "HTTP status = 404 Not Found.")); @@ -4363,12 +4377,12 @@ absl::nullopt, {"l1", "l2"}, GURL("https://ad2.com"))); - const Result& res = RunAuctionAndWait(kSellerUrl, std::move(bidders)); + RunAuctionAndWait(kSellerUrl, std::move(bidders)); EXPECT_EQ(kBidder2Key, result_.winning_group_id); - EXPECT_EQ(GURL("https://ad2.com/"), res.ad_url); + EXPECT_EQ(GURL("https://ad2.com/"), result_.ad_url); EXPECT_TRUE(result_.ad_component_urls.empty()); - EXPECT_THAT(res.report_urls, + EXPECT_THAT(result_.report_urls, testing::UnorderedElementsAre( GURL("https://reporting.example.com/2"), GURL("https://buyer-reporting.example.com/2"))); @@ -4411,7 +4425,7 @@ testing::UnorderedElementsAre(kBidder1Key, kBidder2Key)); EXPECT_EQ(R"({"render_url":"https://ad2.com/"})", result_.winning_group_ad_metadata); - EXPECT_THAT(res.errors, testing::ElementsAre()); + EXPECT_THAT(result_.errors, testing::ElementsAre()); CheckHistograms(InterestGroupAuction::AuctionResult::kSuccess, /*expected_interest_groups=*/2, /*expected_owners=*/2, /*expected_sellers=*/1); @@ -4440,12 +4454,12 @@ auction_worklet::AddJavascriptResponse(&url_loader_factory_, kSellerUrl, MakeAuctionScript()); - const Result& res = RunStandardAuction(); + RunStandardAuction(); EXPECT_EQ(kBidder2Key, result_.winning_group_id); - EXPECT_EQ(GURL("https://ad2.com/"), res.ad_url); + EXPECT_EQ(GURL("https://ad2.com/"), result_.ad_url); EXPECT_EQ(std::vector<GURL>{GURL("https://ad2.com-component1.com")}, - res.ad_component_urls); - EXPECT_THAT(res.report_urls, + result_.ad_component_urls); + EXPECT_THAT(result_.report_urls, testing::UnorderedElementsAre( GURL("https://reporting.example.com/2"), GURL("https://buyer-reporting.example.com/2"))); @@ -4488,17 +4502,17 @@ testing::UnorderedElementsAre(kBidder1Key, kBidder2Key)); EXPECT_EQ(R"({"render_url":"https://ad2.com/"})", result_.winning_group_ad_metadata); - EXPECT_THAT(res.errors, testing::UnorderedElementsAre( - "Failed to load " - "https://adplatform.com/" - "signals1?hostname=publisher1.com&keys=k1,k2&" - "interestGroupNames=Ad+Platform " - "HTTP status = 404 Not Found.", - "Failed to load " - "https://anotheradthing.com/" - "signals2?hostname=publisher1.com&keys=l1,l2" - "&interestGroupNames=Another+Ad+Thing " - "HTTP status = 404 Not Found.")); + EXPECT_THAT(result_.errors, testing::UnorderedElementsAre( + "Failed to load " + "https://adplatform.com/" + "signals1?hostname=publisher1.com&keys=k1,k2&" + "interestGroupNames=Ad+Platform " + "HTTP status = 404 Not Found.", + "Failed to load " + "https://anotheradthing.com/" + "signals2?hostname=publisher1.com&keys=l1,l2" + "&interestGroupNames=Another+Ad+Thing " + "HTTP status = 404 Not Found.")); CheckHistograms(InterestGroupAuction::AuctionResult::kSuccess, /*expected_interest_groups=*/2, /*expected_owners=*/2, /*expected_sellers=*/1); @@ -4531,13 +4545,14 @@ "&interestGroupNames=Another+Ad+Thing"), kBidder2SignalsJson); - const Result& res = RunStandardAuction(); + RunStandardAuction(); EXPECT_EQ(kBidder2Key, result_.winning_group_id); - EXPECT_EQ(GURL("https://ad2.com/"), res.ad_url); + EXPECT_EQ(GURL("https://ad2.com/"), result_.ad_url); EXPECT_EQ(std::vector<GURL>{GURL("https://ad2.com-component1.com")}, - res.ad_component_urls); - EXPECT_THAT(res.report_urls, testing::UnorderedElementsAre(GURL( - "https://buyer-reporting.example.com/2"))); + result_.ad_component_urls); + EXPECT_THAT(result_.report_urls, + testing::UnorderedElementsAre( + GURL("https://buyer-reporting.example.com/2"))); EXPECT_THAT( result_.ad_beacon_map, testing::UnorderedElementsAre( @@ -4575,7 +4590,7 @@ testing::UnorderedElementsAre(kBidder1Key, kBidder2Key)); EXPECT_EQ(R"({"render_url":"https://ad2.com/"})", result_.winning_group_ad_metadata); - EXPECT_THAT(res.errors, testing::ElementsAre()); + EXPECT_THAT(result_.errors, testing::ElementsAre()); CheckHistograms(InterestGroupAuction::AuctionResult::kSuccess, /*expected_interest_groups=*/2, /*expected_owners=*/2, /*expected_sellers=*/1); @@ -4610,13 +4625,14 @@ "&interestGroupNames=Another+Ad+Thing"), kBidder2SignalsJson); - const Result& res = RunStandardAuction(); + RunStandardAuction(); EXPECT_EQ(kBidder2Key, result_.winning_group_id); - EXPECT_EQ(GURL("https://ad2.com/"), res.ad_url); + EXPECT_EQ(GURL("https://ad2.com/"), result_.ad_url); EXPECT_EQ(std::vector<GURL>{GURL("https://ad2.com-component1.com")}, - res.ad_component_urls); - EXPECT_THAT(res.report_urls, testing::UnorderedElementsAre( - GURL("https://reporting.example.com/2"))); + result_.ad_component_urls); + EXPECT_THAT( + result_.report_urls, + testing::UnorderedElementsAre(GURL("https://reporting.example.com/2"))); EXPECT_THAT( result_.ad_beacon_map, testing::UnorderedElementsAre( @@ -4650,7 +4666,7 @@ testing::UnorderedElementsAre(kBidder1Key, kBidder2Key)); EXPECT_EQ(R"({"render_url":"https://ad2.com/"})", result_.winning_group_ad_metadata); - EXPECT_THAT(res.errors, testing::ElementsAre()); + EXPECT_THAT(result_.errors, testing::ElementsAre()); CheckHistograms(InterestGroupAuction::AuctionResult::kSuccess, /*expected_interest_groups=*/2, /*expected_owners=*/2, /*expected_sellers=*/1); @@ -4685,13 +4701,13 @@ "&interestGroupNames=Another+Ad+Thing"), kBidder2SignalsJson); - const Result& res = RunStandardAuction(); + RunStandardAuction(); EXPECT_EQ(kBidder2Key, result_.winning_group_id); - EXPECT_EQ(GURL("https://ad2.com/"), res.ad_url); + EXPECT_EQ(GURL("https://ad2.com/"), result_.ad_url); EXPECT_EQ(std::vector<GURL>{GURL("https://ad2.com-component1.com")}, - res.ad_component_urls); - EXPECT_THAT(res.report_urls, testing::UnorderedElementsAre()); - EXPECT_THAT(res.ad_beacon_map, + result_.ad_component_urls); + EXPECT_THAT(result_.report_urls, testing::UnorderedElementsAre()); + EXPECT_THAT(result_.ad_beacon_map, testing::UnorderedElementsAreArray(kEmptyAdBeaconMap)); EXPECT_THAT( private_aggregation_manager_.TakePrivateAggregationRequests(), @@ -4717,7 +4733,7 @@ testing::UnorderedElementsAre(kBidder1Key, kBidder2Key)); EXPECT_EQ(R"({"render_url":"https://ad2.com/"})", result_.winning_group_ad_metadata); - EXPECT_THAT(res.errors, testing::ElementsAre()); + EXPECT_THAT(result_.errors, testing::ElementsAre()); CheckHistograms(InterestGroupAuction::AuctionResult::kSuccess, /*expected_interest_groups=*/2, /*expected_owners=*/2, /*expected_sellers=*/1); @@ -4759,14 +4775,15 @@ "&interestGroupNames=Another+Ad+Thing"), kBidder2SignalsJson); - const Result& res = RunStandardAuction(); + RunStandardAuction(); EXPECT_EQ(kBidder2Key, result_.winning_group_id); - EXPECT_EQ(GURL("https://ad2.com/"), res.ad_url); + EXPECT_EQ(GURL("https://ad2.com/"), result_.ad_url); EXPECT_EQ(std::vector<GURL>{GURL("https://ad2.com-component1.com")}, - res.ad_component_urls); - EXPECT_THAT(res.report_urls, testing::UnorderedElementsAre(GURL( - "https://seller.signals.were.null.test/"))); - EXPECT_THAT(res.ad_beacon_map, + result_.ad_component_urls); + EXPECT_THAT(result_.report_urls, + testing::UnorderedElementsAre( + GURL("https://seller.signals.were.null.test/"))); + EXPECT_THAT(result_.ad_beacon_map, testing::UnorderedElementsAreArray(kEmptyAdBeaconMap)); EXPECT_THAT( private_aggregation_manager_.TakePrivateAggregationRequests(), @@ -4790,9 +4807,9 @@ testing::UnorderedElementsAre(kBidder1Key, kBidder2Key)); EXPECT_EQ(R"({"render_url":"https://ad2.com/"})", result_.winning_group_ad_metadata); - EXPECT_THAT(res.errors, testing::ElementsAre(base::StringPrintf( - "%s `reportResult` is not a function.", - kSellerUrl.spec().c_str()))); + EXPECT_THAT(result_.errors, testing::ElementsAre(base::StringPrintf( + "%s `reportResult` is not a function.", + kSellerUrl.spec().c_str()))); CheckHistograms(InterestGroupAuction::AuctionResult::kSuccess, /*expected_interest_groups=*/2, /*expected_owners=*/2, /*expected_sellers=*/1); @@ -8414,6 +8431,280 @@ testing::ElementsAre(GURL("https://adplatform.com/metrics/5"))); } +// Test the case where the only bidder times out due to the +// perBuyerCumulativeTimeouts. +TEST_F(AuctionRunnerTest, PerBuyerCumulativeTimeouts) { + interest_group_buyers_ = {{kBidder1}}; + StartStandardAuctionWithMockService(/*num_expected_bidder_worklets=*/1); + + auto seller_worklet = mock_auction_process_manager_->TakeSellerWorklet(); + ASSERT_TRUE(seller_worklet); + auto bidder1_worklet = + mock_auction_process_manager_->TakeBidderWorklet(kBidder1Url); + ASSERT_TRUE(bidder1_worklet); + + task_environment()->FastForwardBy(kBidder1CumulativeTimeout - kTinyTime); + EXPECT_FALSE(auction_complete_); + task_environment()->FastForwardBy(kTinyTime); + EXPECT_TRUE(auction_complete_); + auction_run_loop_->Run(); + EXPECT_THAT(result_.errors, + testing::UnorderedElementsAre( + "https://adplatform.com/offers.js perBuyerCumulativeTimeout " + "exceeded during bid generation.")); + EXPECT_EQ(absl::nullopt, result_.winning_group_id); +} + +// Test the case where the perBuyerCumulativeTimeout expires during the +// scoreAd() call. The bid should not be timed out. +TEST_F(AuctionRunnerTest, + PerBuyerCumulativeTimeoutsTimeoutPassesDuringScoreAd) { + interest_group_buyers_ = {{kBidder1}}; + StartStandardAuctionWithMockService(/*num_expected_bidder_worklets=*/1); + + auto seller_worklet = mock_auction_process_manager_->TakeSellerWorklet(); + ASSERT_TRUE(seller_worklet); + auto bidder1_worklet = + mock_auction_process_manager_->TakeBidderWorklet(kBidder1Url); + ASSERT_TRUE(bidder1_worklet); + + // The timeout isn't quite hit. + task_environment()->FastForwardBy(kBidder1CumulativeTimeout - kTinyTime); + EXPECT_FALSE(auction_complete_); + + // Bid generation completes. + bidder1_worklet->InvokeGenerateBidCallback(/*bid=*/2, + GURL("https://ad1.com/")); + + // More than the timeout time passes, but since the bid is being blocked on + // the seller, there should be no timeout. + task_environment()->FastForwardBy(2 * kBidder1CumulativeTimeout); + EXPECT_FALSE(auction_complete_); + + // Score the ad. + auto score_ad_params = seller_worklet->WaitForScoreAd(); + EXPECT_EQ(kBidder1, score_ad_params.interest_group_owner); + EXPECT_EQ(2, score_ad_params.bid); + mojo::Remote<auction_worklet::mojom::ScoreAdClient>( + std::move(score_ad_params.score_ad_client)) + ->OnScoreAdComplete( + /*score=*/10, + /*reject_reason=*/ + auction_worklet::mojom::RejectReason::kNotAvailable, + auction_worklet::mojom::ComponentAuctionModifiedBidParamsPtr(), + /*scoring_signals_data_version=*/0, + /*has_scoring_signals_data_version=*/false, + /*debug_loss_report_url=*/absl::nullopt, + /*debug_win_report_url=*/absl::nullopt, /*pa_requests=*/{}, + /*errors=*/{}); + + // Finish the auction. + seller_worklet->WaitForReportResult(); + seller_worklet->InvokeReportResultCallback(); + mock_auction_process_manager_->WaitForWinningBidderReload(); + bidder1_worklet = + mock_auction_process_manager_->TakeBidderWorklet(kBidder1Url); + bidder1_worklet->WaitForReportWin(); + bidder1_worklet->InvokeReportWinCallback(); + auction_run_loop_->Run(); + + EXPECT_THAT(result_.errors, testing::UnorderedElementsAre()); + EXPECT_EQ(kBidder1Key, result_.winning_group_id); + EXPECT_EQ(GURL("https://ad1.com/"), result_.ad_url); +} + +// Test the case where a pending promise delays the start of the +// perBuyerCumulativeTimeout, but generating a bid still times out since +// perBuyerCumulativeTimeout passes after promise resolution. +TEST_F(AuctionRunnerTest, + PerBuyerCumulativeTimeoutsPromiseDelaysTimeoutButStillTimesOut) { + use_promise_for_buyer_cumulative_timeouts_ = true; + interest_group_buyers_ = {{kBidder1}}; + StartStandardAuctionWithMockService(/*num_expected_bidder_worklets=*/1); + + auto seller_worklet = mock_auction_process_manager_->TakeSellerWorklet(); + ASSERT_TRUE(seller_worklet); + auto bidder1_worklet = + mock_auction_process_manager_->TakeBidderWorklet(kBidder1Url); + ASSERT_TRUE(bidder1_worklet); + + // The timeout duration passes, but since the seller is being waited on, too, + // this doesn't count towards the timeout. + task_environment()->FastForwardBy(2 * kBidder1CumulativeTimeout); + EXPECT_FALSE(auction_complete_); + + // Feed in perBuyerCumulativeTimeouts. + abortable_ad_auction_->ResolvedBuyerTimeoutsPromise( + blink::mojom::AuctionAdConfigAuctionId::NewMainAuction(0), + blink::mojom::AuctionAdConfigBuyerTimeoutField:: + kPerBuyerCumulativeTimeouts, + MakeBuyerCumulativeTimeouts(/*use_promise=*/false).value()); + + // The timeout passes again, but this time, it counts towards the cumulative + // timeout. + task_environment()->FastForwardBy(kBidder1CumulativeTimeout - kTinyTime); + EXPECT_FALSE(auction_complete_); + task_environment()->FastForwardBy(kTinyTime); + EXPECT_TRUE(auction_complete_); + + auction_run_loop_->Run(); + EXPECT_THAT(result_.errors, + testing::UnorderedElementsAre( + "https://adplatform.com/offers.js perBuyerCumulativeTimeout " + "exceeded during bid generation.")); + EXPECT_EQ(absl::nullopt, result_.winning_group_id); +} + +// Test the case where a pending promise delays the start of the +// perBuyerCumulativeTimeout, and a bid is ultimately generated successfully +// because of the delayed promise resolution. +TEST_F(AuctionRunnerTest, + PerBuyerCumulativeTimeoutsPromiseDelaysTimeoutAndNoTimeout) { + use_promise_for_buyer_cumulative_timeouts_ = true; + interest_group_buyers_ = {{kBidder1}}; + StartStandardAuctionWithMockService(/*num_expected_bidder_worklets=*/1); + + auto seller_worklet = mock_auction_process_manager_->TakeSellerWorklet(); + ASSERT_TRUE(seller_worklet); + auto bidder1_worklet = + mock_auction_process_manager_->TakeBidderWorklet(kBidder1Url); + ASSERT_TRUE(bidder1_worklet); + + // The timeout duration passes, but since the seller is being waited on, too, + // this doesn't count towards the timeout. + task_environment()->FastForwardBy(2 * kBidder1CumulativeTimeout); + EXPECT_FALSE(auction_complete_); + + // Feed in perBuyerCumulativeTimeouts. + abortable_ad_auction_->ResolvedBuyerTimeoutsPromise( + blink::mojom::AuctionAdConfigAuctionId::NewMainAuction(0), + blink::mojom::AuctionAdConfigBuyerTimeoutField:: + kPerBuyerCumulativeTimeouts, + MakeBuyerCumulativeTimeouts(/*use_promise=*/false).value()); + + // The timeout doesn't quite pass after the promise is resolved. + task_environment()->FastForwardBy(kBidder1CumulativeTimeout - kTinyTime); + EXPECT_FALSE(auction_complete_); + + // Bid generation completes. + bidder1_worklet->InvokeGenerateBidCallback(/*bid=*/2, + GURL("https://ad1.com/")); + + // Score the ad. + auto score_ad_params = seller_worklet->WaitForScoreAd(); + EXPECT_EQ(kBidder1, score_ad_params.interest_group_owner); + EXPECT_EQ(2, score_ad_params.bid); + mojo::Remote<auction_worklet::mojom::ScoreAdClient>( + std::move(score_ad_params.score_ad_client)) + ->OnScoreAdComplete( + /*score=*/10, + /*reject_reason=*/ + auction_worklet::mojom::RejectReason::kNotAvailable, + auction_worklet::mojom::ComponentAuctionModifiedBidParamsPtr(), + /*scoring_signals_data_version=*/0, + /*has_scoring_signals_data_version=*/false, + /*debug_loss_report_url=*/absl::nullopt, + /*debug_win_report_url=*/absl::nullopt, /*pa_requests=*/{}, + /*errors=*/{}); + + // Finish the auction. + seller_worklet->WaitForReportResult(); + seller_worklet->InvokeReportResultCallback(); + mock_auction_process_manager_->WaitForWinningBidderReload(); + bidder1_worklet = + mock_auction_process_manager_->TakeBidderWorklet(kBidder1Url); + bidder1_worklet->WaitForReportWin(); + bidder1_worklet->InvokeReportWinCallback(); + auction_run_loop_->Run(); + + EXPECT_THAT(result_.errors, testing::UnorderedElementsAre()); + EXPECT_EQ(kBidder1Key, result_.winning_group_id); + EXPECT_EQ(GURL("https://ad1.com/"), result_.ad_url); +} + +// Test that the cumulative timeout only starts once a process is assigned. +TEST_F(AuctionRunnerTest, PerBuyerCumulativeTimeoutsWaitForProcess) { + // Create AuctionProcessManager in advance of starting the auction so can + // create worklets before the auction starts. + UseMockWorkletService(); + + // Fill up all bidding process slots. + std::vector<std::unique_ptr<AuctionProcessManager::ProcessHandle>> + busy_processes; + for (size_t i = 0; i < AuctionProcessManager::kMaxBidderProcesses; ++i) { + busy_processes.push_back( + std::make_unique<AuctionProcessManager::ProcessHandle>()); + url::Origin origin = url::Origin::Create( + GURL(base::StringPrintf("https://blocking.bidder.%zu.test", i))); + EXPECT_TRUE(auction_process_manager_->RequestWorkletService( + AuctionProcessManager::WorkletType::kBidder, origin, + scoped_refptr<SiteInstance>(), &*busy_processes.back(), + base::BindOnce( + []() { ADD_FAILURE() << "This should not be called"; }))); + } + task_environment()->RunUntilIdle(); + + // Start a 1-bidder auction. + interest_group_buyers_ = {{kBidder1}}; + StartStandardAuction(); + + // The timeout should not have started, since the bidder is still waiting on a + // process slot. + task_environment()->FastForwardBy(2 * kBidder1CumulativeTimeout); + EXPECT_FALSE(auction_complete_); + + // Free up a process slot. + busy_processes.erase(busy_processes.begin()); + + // Wait for all worklet requests. + mock_auction_process_manager_->WaitForWorklets(/*num_bidders=*/1, + /*num_sellers=*/1); + + auto seller_worklet = mock_auction_process_manager_->TakeSellerWorklet(); + ASSERT_TRUE(seller_worklet); + auto bidder1_worklet = + mock_auction_process_manager_->TakeBidderWorklet(kBidder1Url); + ASSERT_TRUE(bidder1_worklet); + + // Wait for the timeout to pass again. This time, it should result in the + // bidder timing out. + task_environment()->FastForwardBy(kBidder1CumulativeTimeout - kTinyTime); + EXPECT_FALSE(auction_complete_); + task_environment()->FastForwardBy(kTinyTime); + EXPECT_TRUE(auction_complete_); + + auction_run_loop_->Run(); + EXPECT_THAT(result_.errors, + testing::UnorderedElementsAre( + "https://adplatform.com/offers.js perBuyerCumulativeTimeout " + "exceeded during bid generation.")); + EXPECT_EQ(absl::nullopt, result_.winning_group_id); +} + +// Test the case where the only bidder times out due to the +// perBuyerCumulativeTimeout's "*" field. +TEST_F(AuctionRunnerTest, PerBuyerCumulativeTimeoutsAllBuyersTimeout) { + interest_group_buyers_ = {{kBidder2}}; + StartStandardAuctionWithMockService(/*num_expected_bidder_worklets=*/1); + + auto seller_worklet = mock_auction_process_manager_->TakeSellerWorklet(); + ASSERT_TRUE(seller_worklet); + auto bidder2_worklet = + mock_auction_process_manager_->TakeBidderWorklet(kBidder2Url); + ASSERT_TRUE(bidder2_worklet); + + task_environment()->FastForwardBy(kAllBuyersCumulativeTimeout - kTinyTime); + EXPECT_FALSE(auction_complete_); + task_environment()->FastForwardBy(kTinyTime); + EXPECT_TRUE(auction_complete_); + auction_run_loop_->Run(); + EXPECT_THAT(result_.errors, + testing::UnorderedElementsAre( + "https://anotheradthing.com/bids.js " + "perBuyerCumulativeTimeout exceeded during bid generation.")); + EXPECT_EQ(absl::nullopt, result_.winning_group_id); +} + // Auction with only one interest group participating. The priority calculated // using its priority vector is negative, so it should be filtered out, and // there should be no winner. @@ -9340,10 +9631,10 @@ // Want AuctionRunner still around to make sure that it handles Abort() OK // in that timing. dont_reset_auction_runner_ = true; - const Result& result = RunAuctionAndWait(kSellerUrl, std::move(bidders)); - EXPECT_EQ(kBidder1Name, result.winning_group_id->name); - EXPECT_FALSE(result.manually_aborted); - EXPECT_THAT(result.errors, testing::ElementsAre()); + RunAuctionAndWait(kSellerUrl, std::move(bidders)); + EXPECT_EQ(kBidder1Name, result_.winning_group_id->name); + EXPECT_FALSE(result_.manually_aborted); + EXPECT_THAT(result_.errors, testing::ElementsAre()); abortable_ad_auction_->Abort(); task_environment()->RunUntilIdle(); auction_runner_.reset(); @@ -10122,9 +10413,8 @@ .SetTrustedBiddingSignalsKeys({{"k1", "k2"}}) .SetAds({{blink::InterestGroup::Ad(GURL("https://ad1.com"), absl::nullopt)}}) - .SetSellerCapabilities( - {{{url::Origin::Create(kSellerUrl), - blink::InterestGroup::SellerCapabilities::kLatencyStats}}}) + .SetSellerCapabilities({{{url::Origin::Create(kSellerUrl), + blink::SellerCapabilities::kLatencyStats}}}) .Build())); RunExtendedPABuyersAuction(bidders, {kTrustedSignalsFetchDuration}); @@ -10158,9 +10448,8 @@ .SetTrustedBiddingSignalsKeys({{"k1", "k2"}}) .SetAds({{blink::InterestGroup::Ad(GURL("https://ad1.com"), absl::nullopt)}}) - .SetSellerCapabilities( - {{{url::Origin::Create(kSellerUrl), - blink::InterestGroup::SellerCapabilities::kLatencyStats}}}) + .SetSellerCapabilities({{{url::Origin::Create(kSellerUrl), + blink::SellerCapabilities::kLatencyStats}}}) .Build())); RunExtendedPABuyersAuction(bidders, @@ -10197,8 +10486,7 @@ .SetTrustedBiddingSignalsKeys({{"k1", "k2"}}) .SetAds({{blink::InterestGroup::Ad(GURL("https://ad1.com"), absl::nullopt)}}) - .SetAllSellerCapabilities( - blink::InterestGroup::SellerCapabilities::kLatencyStats) + .SetAllSellerCapabilities(blink::SellerCapabilities::kLatencyStats) .Build())); RunExtendedPABuyersAuction(bidders, {kTrustedSignalsFetchDuration}); @@ -10235,9 +10523,8 @@ .SetTrustedBiddingSignalsKeys({{"k1", "k2"}}) .SetAds({{blink::InterestGroup::Ad(GURL("https://ad1.com"), absl::nullopt)}}) - .SetSellerCapabilities( - {{{url::Origin::Create(kSellerUrl), - blink::InterestGroup::SellerCapabilities::kLatencyStats}}}) + .SetSellerCapabilities({{{url::Origin::Create(kSellerUrl), + blink::SellerCapabilities::kLatencyStats}}}) .Build())); RunExtendedPABuyersAuction(bidders, {kTrustedSignalsFetchDuration}); @@ -10274,9 +10561,8 @@ .SetTrustedBiddingSignalsKeys({{"k1", "k2"}}) .SetAds({{blink::InterestGroup::Ad(GURL("https://ad1.com"), absl::nullopt)}}) - .SetSellerCapabilities( - {{{url::Origin::Create(kSellerUrl), - blink::InterestGroup::SellerCapabilities::kLatencyStats}}}) + .SetSellerCapabilities({{{url::Origin::Create(kSellerUrl), + blink::SellerCapabilities::kLatencyStats}}}) .Build())); RunExtendedPABuyersAuction(bidders, {kTrustedSignalsFetchDuration}); @@ -10310,9 +10596,8 @@ .SetTrustedBiddingSignalsKeys({{"k1", "k2"}}) .SetAds({{blink::InterestGroup::Ad(GURL("https://ad1.com"), absl::nullopt)}}) - .SetSellerCapabilities( - {{{url::Origin::Create(kSellerUrl), - blink::InterestGroup::SellerCapabilities::kLatencyStats}}}) + .SetSellerCapabilities({{{url::Origin::Create(kSellerUrl), + blink::SellerCapabilities::kLatencyStats}}}) .Build())); RunExtendedPABuyersAuction(bidders, {kTrustedSignalsFetchDuration}); @@ -10346,9 +10631,8 @@ .SetTrustedBiddingSignalsKeys({{"k1", "k2"}}) .SetAds({{blink::InterestGroup::Ad(GURL("https://ad1.com"), absl::nullopt)}}) - .SetSellerCapabilities( - {{{url::Origin::Create(kSellerUrl), - blink::InterestGroup::SellerCapabilities::kLatencyStats}}}) + .SetSellerCapabilities({{{url::Origin::Create(kSellerUrl), + blink::SellerCapabilities::kLatencyStats}}}) .Build())); RunExtendedPABuyersAuction(bidders, {kTrustedSignalsFetchDuration}); @@ -10383,9 +10667,8 @@ .SetTrustedBiddingSignalsKeys({{"k1", "k2"}}) .SetAds({{blink::InterestGroup::Ad(GURL("https://ad1.com"), absl::nullopt)}}) - .SetSellerCapabilities( - {{{url::Origin::Create(kSellerUrl), - blink::InterestGroup::SellerCapabilities::kLatencyStats}}}) + .SetSellerCapabilities({{{url::Origin::Create(kSellerUrl), + blink::SellerCapabilities::kLatencyStats}}}) .Build())); RunExtendedPABuyersAuction(bidders, {kTrustedSignalsFetchDuration}); @@ -10443,9 +10726,8 @@ .SetTrustedBiddingSignalsKeys({{"k1", "k2"}}) .SetAds({{blink::InterestGroup::Ad(GURL("https://ad1.com"), absl::nullopt)}}) - .SetSellerCapabilities( - {{{url::Origin::Create(kSellerUrl), - blink::InterestGroup::SellerCapabilities::kLatencyStats}}}) + .SetSellerCapabilities({{{url::Origin::Create(kSellerUrl), + blink::SellerCapabilities::kLatencyStats}}}) .Build())); RunExtendedPABuyersAuction(bidders, {kTrustedSignalsFetchDuration}); @@ -10470,9 +10752,8 @@ .SetTrustedBiddingSignalsKeys({{"k1", "k2"}}) .SetAds({{blink::InterestGroup::Ad(GURL("https://ad1.com"), absl::nullopt)}}) - .SetSellerCapabilities( - {{{url::Origin::Create(kSellerUrl), - blink::InterestGroup::SellerCapabilities::kLatencyStats}}}) + .SetSellerCapabilities({{{url::Origin::Create(kSellerUrl), + blink::SellerCapabilities::kLatencyStats}}}) .Build())); RunExtendedPABuyersAuction(bidders, {kTrustedSignalsFetchDuration}); @@ -10503,9 +10784,8 @@ .SetTrustedBiddingSignalsKeys({{"k1", "k2"}}) .SetAds({{blink::InterestGroup::Ad(GURL("https://ad1.com"), absl::nullopt)}}) - .SetSellerCapabilities( - {{{url::Origin::Create(kSellerUrl), - blink::InterestGroup::SellerCapabilities::kLatencyStats}}}) + .SetSellerCapabilities({{{url::Origin::Create(kSellerUrl), + blink::SellerCapabilities::kLatencyStats}}}) .Build())); RunExtendedPABuyersAuction(bidders, {kTrustedSignalsFetchDuration}); @@ -10538,9 +10818,8 @@ .SetTrustedBiddingSignalsKeys({{"k1", "k2"}}) .SetAds({{blink::InterestGroup::Ad(GURL("https://ad1.com"), absl::nullopt)}}) - .SetSellerCapabilities( - {{{url::Origin::Create(kSellerUrl), - blink::InterestGroup::SellerCapabilities::kLatencyStats}}}) + .SetSellerCapabilities({{{url::Origin::Create(kSellerUrl), + blink::SellerCapabilities::kLatencyStats}}}) .Build())); bidders.emplace_back(MakeInterestGroup( blink::TestInterestGroupBuilder(kBidder2, kBidder2Name) @@ -10549,9 +10828,8 @@ .SetTrustedBiddingSignalsKeys({{"k1", "k2"}}) .SetAds({{blink::InterestGroup::Ad(GURL("https://ad1.com"), absl::nullopt)}}) - .SetSellerCapabilities( - {{{url::Origin::Create(kSellerUrl), - blink::InterestGroup::SellerCapabilities::kLatencyStats}}}) + .SetSellerCapabilities({{{url::Origin::Create(kSellerUrl), + blink::SellerCapabilities::kLatencyStats}}}) .Build())); RunExtendedPABuyersAuction( @@ -10599,9 +10877,8 @@ .SetTrustedBiddingSignalsKeys({{"k1", "k2"}}) .SetAds({{blink::InterestGroup::Ad(GURL("https://ad1.com"), absl::nullopt)}}) - .SetSellerCapabilities( - {{{url::Origin::Create(kSellerUrl), - blink::InterestGroup::SellerCapabilities::kLatencyStats}}}) + .SetSellerCapabilities({{{url::Origin::Create(kSellerUrl), + blink::SellerCapabilities::kLatencyStats}}}) .Build())); bidders.emplace_back(MakeInterestGroup( blink::TestInterestGroupBuilder(kBidder2, kBidder2Name) @@ -10610,9 +10887,8 @@ .SetTrustedBiddingSignalsKeys({{"k1", "k2"}}) .SetAds({{blink::InterestGroup::Ad(GURL("https://ad1.com"), absl::nullopt)}}) - .SetSellerCapabilities( - {{{url::Origin::Create(kSellerUrl), - blink::InterestGroup::SellerCapabilities::kLatencyStats}}}) + .SetSellerCapabilities({{{url::Origin::Create(kSellerUrl), + blink::SellerCapabilities::kLatencyStats}}}) .Build())); RunExtendedPABuyersAuction( @@ -10650,9 +10926,9 @@ .SetTrustedBiddingSignalsKeys({{"k1", "k2"}}) .SetAds({{blink::InterestGroup::Ad(GURL("https://ad1.com"), absl::nullopt)}}) - .SetSellerCapabilities({{{url::Origin::Create(kSellerUrl), - blink::InterestGroup::SellerCapabilities:: - kInterestGroupCounts}}}) + .SetSellerCapabilities( + {{{url::Origin::Create(kSellerUrl), + blink::SellerCapabilities::kInterestGroupCounts}}}) .Build())); bidders.emplace_back(MakeInterestGroup( blink::TestInterestGroupBuilder(kBidder2, kBidder2Name) @@ -10661,9 +10937,9 @@ .SetTrustedBiddingSignalsKeys({{"k1", "k2"}}) .SetAds({{blink::InterestGroup::Ad(GURL("https://ad1.com"), absl::nullopt)}}) - .SetSellerCapabilities({{{url::Origin::Create(kSellerUrl), - blink::InterestGroup::SellerCapabilities:: - kInterestGroupCounts}}}) + .SetSellerCapabilities( + {{{url::Origin::Create(kSellerUrl), + blink::SellerCapabilities::kInterestGroupCounts}}}) .Build())); RunExtendedPABuyersAuction( @@ -10706,9 +10982,9 @@ .SetTrustedBiddingSignalsKeys({{"k1", "k2"}}) .SetAds({{blink::InterestGroup::Ad(GURL("https://ad1.com"), absl::nullopt)}}) - .SetSellerCapabilities({{{url::Origin::Create(kSellerUrl), - blink::InterestGroup::SellerCapabilities:: - kInterestGroupCounts}}}) + .SetSellerCapabilities( + {{{url::Origin::Create(kSellerUrl), + blink::SellerCapabilities::kInterestGroupCounts}}}) .Build())); bidders.emplace_back(MakeInterestGroup( blink::TestInterestGroupBuilder(kBidder2, kBidder2Name) @@ -10717,9 +10993,9 @@ .SetTrustedBiddingSignalsKeys({{"k1", "k2"}}) .SetAds({{blink::InterestGroup::Ad(GURL("https://ad1.com"), absl::nullopt)}}) - .SetSellerCapabilities({{{url::Origin::Create(kSellerUrl), - blink::InterestGroup::SellerCapabilities:: - kInterestGroupCounts}}}) + .SetSellerCapabilities( + {{{url::Origin::Create(kSellerUrl), + blink::SellerCapabilities::kInterestGroupCounts}}}) .Build())); RunExtendedPABuyersAuction( @@ -10933,17 +11209,17 @@ /*trusted_bidding_signals_url=*/absl::nullopt, /*trusted_bidding_signals_keys=*/{}, GURL("https://ad3.com"))); - const Result& res = RunAuctionAndWait(kSellerUrl, std::move(bidders)); + RunAuctionAndWait(kSellerUrl, std::move(bidders)); - EXPECT_EQ(4u, res.debug_loss_report_urls.size()); - EXPECT_EQ(2u, res.debug_win_report_urls.size()); - EXPECT_EQ(2u, res.report_urls.size()); + EXPECT_EQ(4u, result_.debug_loss_report_urls.size()); + EXPECT_EQ(2u, result_.debug_win_report_urls.size()); + EXPECT_EQ(2u, result_.report_urls.size()); // Winner has ad2 or ad3. - if (res.ad_url == "https://ad2.com/") { + if (result_.ad_url == "https://ad2.com/") { seen_ad2_win = true; EXPECT_THAT( - res.debug_loss_report_urls, + result_.debug_loss_report_urls, testing::UnorderedElementsAre( DebugReportUrl( kBidderDebugLossReportBaseUrl, @@ -10975,7 +11251,7 @@ /*bid=*/4))); EXPECT_THAT( - res.debug_win_report_urls, + result_.debug_win_report_urls, testing::UnorderedElementsAre( DebugReportUrl( kBidderDebugWinReportBaseUrl, @@ -10992,16 +11268,16 @@ /*made_highest_scoring_other_bid=*/false), /*bid=*/3))); - EXPECT_THAT(res.report_urls, + EXPECT_THAT(result_.report_urls, testing::UnorderedElementsAre( GURL("https://reporting.example.com/" "?highestScoringOtherBid=4&bid=3"), ReportWinUrl(/*bid=*/3, /*highest_scoring_other_bid=*/4, /*made_highest_scoring_other_bid=*/false))); - } else if (res.ad_url == "https://ad3.com/") { + } else if (result_.ad_url == "https://ad3.com/") { seen_ad3_win = true; EXPECT_THAT( - res.debug_loss_report_urls, + result_.debug_loss_report_urls, testing::UnorderedElementsAre( DebugReportUrl( kBidderDebugLossReportBaseUrl, @@ -11033,7 +11309,7 @@ /*bid=*/3))); EXPECT_THAT( - res.debug_win_report_urls, + result_.debug_win_report_urls, testing::UnorderedElementsAre( DebugReportUrl( kBidderDebugWinReportBaseUrl, @@ -11051,7 +11327,7 @@ /*made_highest_scoring_other_bid=*/false), /*bid=*/4))); - EXPECT_THAT(res.report_urls, + EXPECT_THAT(result_.report_urls, testing::UnorderedElementsAre( GURL("https://reporting.example.com/" "?highestScoringOtherBid=3&bid=4"), @@ -11104,30 +11380,30 @@ /*trusted_bidding_signals_url=*/absl::nullopt, /*trusted_bidding_signals_keys=*/{}, GURL("https://ad3.com"))); - const Result& res = RunAuctionAndWait(kSellerUrl, std::move(bidders)); + RunAuctionAndWait(kSellerUrl, std::move(bidders)); double highest_scoring_other_bid = 0.0; if (base::Contains( - res.report_urls, + result_.report_urls, "https://reporting.example.com/?highestScoringOtherBid=1&bid=3", &GURL::spec)) { highest_scoring_other_bid = 1; - } else if (base::Contains(res.report_urls, + } else if (base::Contains(result_.report_urls, "https://reporting.example.com/" "?highestScoringOtherBid=2&bid=3", &GURL::spec)) { highest_scoring_other_bid = 2; } - EXPECT_EQ(GURL("https://ad3.com/"), res.ad_url); - EXPECT_EQ(4u, res.debug_loss_report_urls.size()); - EXPECT_EQ(2u, res.debug_win_report_urls.size()); - EXPECT_EQ(2u, res.report_urls.size()); + EXPECT_EQ(GURL("https://ad3.com/"), result_.ad_url); + EXPECT_EQ(4u, result_.debug_loss_report_urls.size()); + EXPECT_EQ(2u, result_.debug_win_report_urls.size()); + EXPECT_EQ(2u, result_.report_urls.size()); if (highest_scoring_other_bid == 1) { seen_bid1 = true; EXPECT_THAT( - res.debug_loss_report_urls, + result_.debug_loss_report_urls, testing::UnorderedElementsAre( DebugReportUrl( kBidderDebugLossReportBaseUrl, @@ -11159,7 +11435,7 @@ /*bid=*/2))); EXPECT_THAT( - res.debug_win_report_urls, + result_.debug_win_report_urls, testing::UnorderedElementsAre( DebugReportUrl(kBidderDebugWinReportBaseUrl, PostAuctionSignals( @@ -11176,7 +11452,7 @@ /*made_highest_scoring_other_bid=*/true), /*bid=*/3))); - EXPECT_THAT(res.report_urls, + EXPECT_THAT(result_.report_urls, testing::UnorderedElementsAre( GURL("https://reporting.example.com/" "?highestScoringOtherBid=1&bid=3"), @@ -11185,7 +11461,7 @@ } else if (highest_scoring_other_bid == 2) { seen_bid2 = true; EXPECT_THAT( - res.debug_loss_report_urls, + result_.debug_loss_report_urls, testing::UnorderedElementsAre( DebugReportUrl( kBidderDebugLossReportBaseUrl, @@ -11217,7 +11493,7 @@ /*bid=*/2))); EXPECT_THAT( - res.debug_win_report_urls, + result_.debug_win_report_urls, testing::UnorderedElementsAre( DebugReportUrl(kBidderDebugWinReportBaseUrl, PostAuctionSignals( @@ -11234,7 +11510,7 @@ /*made_highest_scoring_other_bid=*/true), /*bid=*/3))); - EXPECT_THAT(res.report_urls, + EXPECT_THAT(result_.report_urls, testing::UnorderedElementsAre( GURL("https://reporting.example.com/" "?highestScoringOtherBid=2&bid=3"), @@ -11278,19 +11554,19 @@ /*trusted_bidding_signals_url=*/absl::nullopt, /*trusted_bidding_signals_keys=*/{}, GURL("https://ad3.com"))); - const Result& res = RunAuctionAndWait(kSellerUrl, std::move(bidders)); + RunAuctionAndWait(kSellerUrl, std::move(bidders)); - EXPECT_EQ(GURL("https://ad3.com/"), res.ad_url); - EXPECT_EQ(4u, res.debug_loss_report_urls.size()); - EXPECT_EQ(2u, res.debug_win_report_urls.size()); - EXPECT_EQ(2u, res.report_urls.size()); + EXPECT_EQ(GURL("https://ad3.com/"), result_.ad_url); + EXPECT_EQ(4u, result_.debug_loss_report_urls.size()); + EXPECT_EQ(2u, result_.debug_win_report_urls.size()); + EXPECT_EQ(2u, result_.report_urls.size()); double highest_scoring_other_bid = 0.0; if (base::Contains( - res.report_urls, + result_.report_urls, "https://reporting.example.com/?highestScoringOtherBid=1&bid=3", &GURL::spec)) { highest_scoring_other_bid = 1; - } else if (base::Contains(res.report_urls, + } else if (base::Contains(result_.report_urls, "https://reporting.example.com/" "?highestScoringOtherBid=2&bid=3", &GURL::spec)) { @@ -11300,7 +11576,7 @@ if (highest_scoring_other_bid == 1) { seen_bid1 = true; EXPECT_THAT( - res.debug_loss_report_urls, + result_.debug_loss_report_urls, testing::UnorderedElementsAre( DebugReportUrl( kBidderDebugLossReportBaseUrl, @@ -11332,7 +11608,7 @@ /*bid=*/2))); EXPECT_THAT( - res.debug_win_report_urls, + result_.debug_win_report_urls, testing::UnorderedElementsAre( DebugReportUrl( kBidderDebugWinReportBaseUrl, @@ -11349,7 +11625,7 @@ /*made_highest_scoring_other_bid=*/false), /*bid=*/3))); - EXPECT_THAT(res.report_urls, + EXPECT_THAT(result_.report_urls, testing::UnorderedElementsAre( GURL("https://reporting.example.com/" "?highestScoringOtherBid=1&bid=3"), @@ -11358,7 +11634,7 @@ } else if (highest_scoring_other_bid == 2) { seen_bid2 = true; EXPECT_THAT( - res.debug_loss_report_urls, + result_.debug_loss_report_urls, testing::UnorderedElementsAre( DebugReportUrl( kBidderDebugLossReportBaseUrl, @@ -11390,7 +11666,7 @@ /*bid=*/2))); EXPECT_THAT( - res.debug_win_report_urls, + result_.debug_win_report_urls, testing::UnorderedElementsAre( DebugReportUrl( kBidderDebugWinReportBaseUrl, @@ -11407,7 +11683,7 @@ /*made_highest_scoring_other_bid=*/false), /*bid=*/3))); - EXPECT_THAT(res.report_urls, + EXPECT_THAT(result_.report_urls, testing::UnorderedElementsAre( GURL("https://reporting.example.com/" "?highestScoringOtherBid=2&bid=3"), @@ -12500,10 +12776,10 @@ "?hostname=publisher1.com&keys=l1,l2"), kBidder2SignalsJson); - const Result& res = RunStandardAuction(); + RunStandardAuction(); EXPECT_TRUE( private_aggregation_manager_.TakePrivateAggregationRequests().empty()); - EXPECT_TRUE(res.private_aggregation_event_map.empty()); + EXPECT_TRUE(result_.private_aggregation_event_map.empty()); } class AuctionRunnerKAnonTest : public AuctionRunnerTest,
diff --git a/content/browser/interest_group/interest_group_auction.cc b/content/browser/interest_group/interest_group_auction.cc index 1325c81f..5bbb5366 100644 --- a/content/browser/interest_group/interest_group_auction.cc +++ b/content/browser/interest_group/interest_group_auction.cc
@@ -9,6 +9,7 @@ #include <algorithm> #include <cmath> #include <iterator> +#include <list> #include <map> #include <memory> #include <string> @@ -64,7 +65,7 @@ namespace { -constexpr base::TimeDelta kMaxTimeout = base::Milliseconds(500); +constexpr base::TimeDelta kMaxPerBuyerTimeout = base::Milliseconds(500); // For group freshness metrics. constexpr base::TimeDelta kGroupFreshnessMin = base::Minutes(1); @@ -195,7 +196,7 @@ // `interest_group`'s seller capabilities has authorized `capability` for // `seller`. bool CanReportPaBuyersValue(const blink::InterestGroup& interest_group, - blink::InterestGroup::SellerCapabilities capability, + blink::SellerCapabilities capability, const url::Origin& seller) { if (interest_group.seller_capabilities) { auto it = interest_group.seller_capabilities->find(seller); @@ -252,6 +253,47 @@ return it->second; } +// Retrieves the timeout from `buyer_timeouts` associated with `buyer`, if any. +// Used for both `buyer_timeouts` and `buyer_cumulative_timeouts`, stored in +// AuctionConfigs. Callers should use PerBuyerTimeout() and +// PerBuyerCumulativeTimeout() instead, since those apply the timeout limit, +// when applicable. +absl::optional<base::TimeDelta> PerBuyerTimeoutHelper( + const url::Origin& buyer, + const blink::AuctionConfig::MaybePromiseBuyerTimeouts& buyer_timeouts) { + DCHECK(!buyer_timeouts.is_promise()); + const auto& per_buyer_timeouts = buyer_timeouts.value().per_buyer_timeouts; + if (per_buyer_timeouts.has_value()) { + auto it = per_buyer_timeouts->find(buyer); + if (it != per_buyer_timeouts->end()) { + return it->second; + } + } + const auto& all_buyers_timeout = buyer_timeouts.value().all_buyers_timeout; + if (all_buyers_timeout.has_value()) { + return all_buyers_timeout.value(); + } + return absl::nullopt; +} + +absl::optional<base::TimeDelta> PerBuyerTimeout( + const url::Origin& buyer, + const blink::AuctionConfig& auction_config) { + absl::optional<base::TimeDelta> out = PerBuyerTimeoutHelper( + buyer, auction_config.non_shared_params.buyer_timeouts); + if (!out) { + return out; + } + return std::min(*out, kMaxPerBuyerTimeout); +} + +absl::optional<base::TimeDelta> PerBuyerCumulativeTimeout( + const url::Origin& buyer, + const blink::AuctionConfig& auction_config) { + return PerBuyerTimeoutHelper( + buyer, auction_config.non_shared_params.buyer_cumulative_timeouts); +} + } // namespace InterestGroupAuction::BidState::BidState() = default; @@ -501,10 +543,9 @@ std::move(pa_requests), errors); } - // Closes all Mojo pipes and release all weak pointers. + // Closes all Mojo pipes, releases all weak pointers, and stops the timeout + // timer. void ClosePipes() { - // This is needed in addition to closing worklet pipes since the callbacks - // passed to Mojo pipes this class doesn't own aren't cancellable. weak_ptr_factory_.InvalidateWeakPtrs(); for (auto& bid_state : bid_states_) { @@ -513,6 +554,11 @@ // No need to clear `generate_bid_client_receiver_set_`, since // CloseBidStatePipes() should take care of that. DCHECK(generate_bid_client_receiver_set_.empty()); + + // Need to stop the timer - this is called on completion and on certain + // errors. Don't want the timer to trigger anything after there's been a + // failure already. + cumulative_buyer_timeout_timer_.Stop(); } // Returns true if this buyer has any interest groups that will potentially @@ -649,6 +695,18 @@ } void NotifyConfigPromisesResolved() { + DCHECK(auction_->config_promises_resolved_); + + // If there are no outstanding bids, just do nothing. It's safest to exit + // early in the case that bidder worklet process crashed or failed to fetch + // the necessary script(s) before all config promises were resolved, rather + // than rely on everything handling that case correctly. + if (num_outstanding_bids_ == 0) { + return; + } + + MaybeStartCumulativeTimeoutTimer(); + for (const auto& bid_state : bid_states_) { FinishGenerateBidIfReady(bid_state.get()); } @@ -701,13 +759,21 @@ AuctionWorkletManager::FatalErrorType::kWorkletCrash) { // Ignore default error message in case of crash. Instead, use a more // specific one. - auction_->errors_.push_back( - base::StrCat({bid_state->bidder->interest_group.bidding_url->spec(), - " crashed while trying to run generateBid()."})); + OnFatalError( + bid_state, + {base::StrCat({bid_state->bidder->interest_group.bidding_url->spec(), + " crashed while trying to run generateBid()."})}); } else { - auction_->errors_.insert(auction_->errors_.end(), errors.begin(), - errors.end()); + OnFatalError(bid_state, errors); } + } + + // Called in the case of a fatal error that prevents the `bid_state` worklet + // from bidding. + void OnFatalError(BidState* bid_state, std::vector<std::string> errors) { + auction_->errors_.insert(auction_->errors_.end(), + std::make_move_iterator(errors.begin()), + std::make_move_iterator(errors.end())); // If waiting on bidding signals, the bidder needs to be removed in the same // way as if it had a new negative priority value, so reuse that logic. The @@ -771,6 +837,13 @@ // Invoked whenever the AuctionWorkletManager has provided a BidderWorket // for the bidder identified by `bid_state`. Starts generating a bid. void OnBidderWorkletReceived(BidState* bid_state) { + if (!bidder_process_received_) { + // All bidder worklets are expected to be loaded in the same process, so + // as soon as any worklet has been received, can set this to true. + bidder_process_received_ = true; + MaybeStartCumulativeTimeoutTimer(); + } + const blink::InterestGroup& interest_group = bid_state->bidder->interest_group; @@ -859,7 +932,7 @@ auction_->config_->non_shared_params.auction_signals.value(), GetPerBuyerSignals(*auction_->config_, bid_state->bidder->interest_group.owner), - auction_->PerBuyerTimeout(bid_state), + PerBuyerTimeout(owner_, *auction_->config_), GetDirectFromSellerPerBuyerSignals( url_builder, bid_state->bidder->interest_group.owner), GetDirectFromSellerAuctionSignals(url_builder)); @@ -1125,10 +1198,79 @@ --num_outstanding_bids_; if (num_outstanding_bids_ == 0) { DCHECK_EQ(num_outstanding_bidding_signals_received_calls_, 0); + // Pipes should already be closed at this point, but the + // `cumulative_buyer_timeout_timer_` needs to be stopped if it's running, + // and it's safest to keep all logic to stop everything `this` may be + // doing in one place. + ClosePipes(); + auction_->OnBidSourceDone(); } } + void MaybeStartCumulativeTimeoutTimer() { + // This should only be called when there are outstanding bids. + DCHECK_GT(num_outstanding_bids_, 0); + + // Do nothing if still waiting on the seller to provide more of the + // AuctionConfig, or waiting on a process to be assigned (which would mean + // that this may be waiting behind other buyers). + if (!auction_->config_promises_resolved_ || !bidder_process_received_) { + return; + } + + DCHECK(!cumulative_buyer_timeout_timer_.IsRunning()); + + // Get cumulative buyer timeout. Note that this must be done after the + // `config_promises_resolved_` check above. + absl::optional<base::TimeDelta> cumulative_buyer_timeout = + PerBuyerCumulativeTimeout(owner_, *auction_->config_); + + // Nothing to do if there's no cumulative timeout. + if (!cumulative_buyer_timeout) { + return; + } + + cumulative_buyer_timeout_timer_.Start( + FROM_HERE, *cumulative_buyer_timeout, + base::BindOnce(&BuyerHelper::OnTimeout, base::Unretained(this))); + } + + // Called when the `cumulative_buyer_timeout_timer_` expires. + void OnTimeout() { + // If there are no outstanding bids, then the timer should not still be + // running. + DCHECK_GT(num_outstanding_bids_, 0); + + // Assemble a list of interest groups that haven't bid yet - have to do + // this, since calling OnGenerateBidCompleteInternal() on the last + // incomplete bid may delete `this`, if it ends the auction. + std::list<BidState*> pending_bids; + for (auto& bid_state : bid_states_) { + if (!bid_state->worklet_handle) { + continue; + } + // Put the IGs that have received signals first, since cancelling the last + // bid that has not received signals could cause a bid that has received + // signals to start running Javascript. + if (bid_state->bidding_signals_received) { + pending_bids.push_front(bid_state.get()); + } else { + pending_bids.push_back(bid_state.get()); + } + } + + for (auto* pending_bid : pending_bids) { + // Fail bids individually, with errors. This does potentially do extra + // work over just failing the entire auction directly, but ensures there's + // a single failure path, reducing the chance of future breakages. + OnFatalError( + pending_bid, /*errors=*/{base::StrCat( + {pending_bid->bidder->interest_group.bidding_url->spec(), + " perBuyerCumulativeTimeout exceeded during bid generation."})}); + } + } + // Calls SendPendingSignalsRequests() for the BidderWorklet of `bid_state`, // if it hasn't been destroyed. This is done asynchronously, so that // BidStates that share a BidderWorklet all call GenerateBid() before this @@ -1256,6 +1398,17 @@ BidState*> generate_bid_client_receiver_set_; + // Set to true once a single bidder worklet has been received (and thus, since + // all bidder worklets managed by a BuyerHelper use the same process, `this` + // is no longer blocked waiting on other bidders to complete). + bool bidder_process_received_ = false; + + // Timer for applying the perBidderCumulativeTimeout, if one is applicable. + // Starts once `bidder_process_received_` and + // `auction_->config_promises_resolved_` are true, if + // `cumulative_buyer_timeout_` is not nullopt. + base::OneShotTimer cumulative_buyer_timeout_timer_; + int num_outstanding_bidding_signals_received_calls_ = 0; int num_outstanding_bids_ = 0; @@ -1620,8 +1773,6 @@ } void InterestGroupAuction::ClosePipes() { - // This is needed in addition to closing worklet pipes since the callbacks - // passed to Mojo pipes this class doesn't own aren't cancellable. weak_ptr_factory_.InvalidateWeakPtrs(); score_ad_receivers_.Clear(); @@ -1747,7 +1898,7 @@ bool InterestGroupAuction::ReportPaBuyersValueIfAllowed( const blink::InterestGroup& interest_group, - blink::InterestGroup::SellerCapabilities capability, + blink::SellerCapabilities capability, blink::AuctionConfig::NonSharedParams::BuyerReportType buyer_report_type, int value) { if (!CanReportPaBuyersValue(interest_group, capability, config_->seller)) { @@ -1989,8 +2140,7 @@ const blink::InterestGroup& interest_group, size_t count) { return ReportPaBuyersValueIfAllowed( - interest_group, - blink::InterestGroup::SellerCapabilities::kInterestGroupCounts, + interest_group, blink::SellerCapabilities::kInterestGroupCounts, blink::AuctionConfig::NonSharedParams::BuyerReportType:: kInterestGroupCount, count); @@ -2000,29 +2150,28 @@ const blink::InterestGroup& interest_group, size_t count) { return ReportPaBuyersValueIfAllowed( - interest_group, - blink::InterestGroup::SellerCapabilities::kInterestGroupCounts, + interest_group, blink::SellerCapabilities::kInterestGroupCounts, blink::AuctionConfig::NonSharedParams::BuyerReportType::kBidCount, count); } void InterestGroupAuction::ReportTrustedSignalsFetchLatency( const blink::InterestGroup& interest_group, base::TimeDelta trusted_signals_fetch_latency) { - ReportPaBuyersValueIfAllowed( - interest_group, blink::InterestGroup::SellerCapabilities::kLatencyStats, - blink::AuctionConfig::NonSharedParams::BuyerReportType:: - kTotalSignalsFetchLatency, - trusted_signals_fetch_latency.InMilliseconds()); + ReportPaBuyersValueIfAllowed(interest_group, + blink::SellerCapabilities::kLatencyStats, + blink::AuctionConfig::NonSharedParams:: + BuyerReportType::kTotalSignalsFetchLatency, + trusted_signals_fetch_latency.InMilliseconds()); } void InterestGroupAuction::ReportBiddingLatency( const blink::InterestGroup& interest_group, base::TimeDelta bidding_latency) { - ReportPaBuyersValueIfAllowed( - interest_group, blink::InterestGroup::SellerCapabilities::kLatencyStats, - blink::AuctionConfig::NonSharedParams::BuyerReportType:: - kTotalGenerateBidLatency, - bidding_latency.InMilliseconds()); + ReportPaBuyersValueIfAllowed(interest_group, + blink::SellerCapabilities::kLatencyStats, + blink::AuctionConfig::NonSharedParams:: + BuyerReportType::kTotalGenerateBidLatency, + bidding_latency.InMilliseconds()); } base::flat_set<std::string> InterestGroupAuction::GetKAnonKeysToJoin() const { @@ -2753,28 +2902,10 @@ leader_info.highest_scoring_other_bid = bid_value; } -absl::optional<base::TimeDelta> InterestGroupAuction::PerBuyerTimeout( - const BidState* state) { - DCHECK(!config_->non_shared_params.buyer_timeouts.is_promise()); - const auto& per_buyer_timeouts = - config_->non_shared_params.buyer_timeouts.value().per_buyer_timeouts; - if (per_buyer_timeouts.has_value()) { - auto it = per_buyer_timeouts->find(state->bidder->interest_group.owner); - if (it != per_buyer_timeouts->end()) { - return std::min(it->second, kMaxTimeout); - } - } - const auto& all_buyers_timeout = - config_->non_shared_params.buyer_timeouts.value().all_buyers_timeout; - if (all_buyers_timeout.has_value()) - return std::min(all_buyers_timeout.value(), kMaxTimeout); - return absl::nullopt; -} - absl::optional<base::TimeDelta> InterestGroupAuction::SellerTimeout() { if (config_->non_shared_params.seller_timeout.has_value()) { return std::min(config_->non_shared_params.seller_timeout.value(), - kMaxTimeout); + kMaxPerBuyerTimeout); } return absl::nullopt; }
diff --git a/content/browser/interest_group/interest_group_auction.h b/content/browser/interest_group/interest_group_auction.h index 12d34cb..5168506 100644 --- a/content/browser/interest_group/interest_group_auction.h +++ b/content/browser/interest_group/interest_group_auction.h
@@ -779,7 +779,6 @@ const url::Origin* owner, LeaderInfo& leader_info); - absl::optional<base::TimeDelta> PerBuyerTimeout(const BidState* state); absl::optional<base::TimeDelta> SellerTimeout(); // If AllBidsScored() is true, completes the bidding and scoring phase. @@ -857,7 +856,7 @@ // the server. bool ReportPaBuyersValueIfAllowed( const blink::InterestGroup& interest_group, - blink::InterestGroup::SellerCapabilities capability, + blink::SellerCapabilities capability, blink::AuctionConfig::NonSharedParams::BuyerReportType buyer_report_type, int value);
diff --git a/content/browser/interest_group/interest_group_browsertest.cc b/content/browser/interest_group/interest_group_browsertest.cc index c4fca50f..f528463c 100644 --- a/content/browser/interest_group/interest_group_browsertest.cc +++ b/content/browser/interest_group/interest_group_browsertest.cc
@@ -141,14 +141,12 @@ } base::Value::List SellerCapabilitiesToList( - blink::InterestGroup::SellerCapabilitiesType capabilities) { + blink::SellerCapabilitiesType capabilities) { base::Value::List list; - for (blink::InterestGroup::SellerCapabilities capability : capabilities) { - if (capability == - blink::InterestGroup::SellerCapabilities::kInterestGroupCounts) { + for (blink::SellerCapabilities capability : capabilities) { + if (capability == blink::SellerCapabilities::kInterestGroupCounts) { list.Append("interestGroupCounts"); - } else if (capability == - blink::InterestGroup::SellerCapabilities::kLatencyStats) { + } else if (capability == blink::SellerCapabilities::kLatencyStats) { list.Append("latencyStats"); } else { ADD_FAILURE() << "Unknown seller capability " @@ -160,9 +158,8 @@ base::Value::Dict SellerCapabilitiesToDict( const absl::optional< - base::flat_map<url::Origin, - blink::InterestGroup::SellerCapabilitiesType>>& map, - blink::InterestGroup::SellerCapabilitiesType all_sellers_capabilities) { + base::flat_map<url::Origin, blink::SellerCapabilitiesType>>& map, + blink::SellerCapabilitiesType all_sellers_capabilities) { base::Value::Dict dict; if (map) { for (const auto& [origin, capabilities] : *map) { @@ -2649,10 +2646,9 @@ /*name=*/"cars") .SetSellerCapabilities( {{{url::Origin::Create(GURL("https://example.test")), - blink::InterestGroup::SellerCapabilities:: - kInterestGroupCounts}}}) + blink::SellerCapabilities::kInterestGroupCounts}}}) .SetAllSellerCapabilities( - blink::InterestGroup::SellerCapabilities::kLatencyStats) + blink::SellerCapabilities::kLatencyStats) .Build())); WaitForAccessObserved({}); @@ -2661,12 +2657,12 @@ ASSERT_EQ(groups.size(), 1u); const blink::InterestGroup& group = groups[0].interest_group; EXPECT_EQ(group.all_sellers_capabilities, - blink::InterestGroup::SellerCapabilities::kLatencyStats); + blink::SellerCapabilities::kLatencyStats); ASSERT_TRUE(group.seller_capabilities); ASSERT_EQ(group.seller_capabilities->size(), 1u); EXPECT_EQ(group.seller_capabilities->at( url::Origin::Create(GURL("https://example.test"))), - blink::InterestGroup::SellerCapabilities::kInterestGroupCounts); + blink::SellerCapabilities::kInterestGroupCounts); } IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest, @@ -2687,8 +2683,7 @@ /*priority_signals_overrides=*/absl::nullopt, /*seller_capabilities=*/{}, /*all_sellers_capabilities=*/ - blink::InterestGroup::SellerCapabilities:: - kLatencyStats, /*execution_mode=*/ + blink::SellerCapabilities::kLatencyStats, /*execution_mode=*/ blink::InterestGroup::ExecutionMode::kCompatibilityMode, /*bidding_url=*/absl::nullopt, /*bidding_wasm_helper_url=*/absl::nullopt, @@ -7690,7 +7685,7 @@ sellerTimeout: 200, perBuyerSignals: {$4: {signalsForBuyer: 1}, $5: {signalsForBuyer: 2}}, perBuyerTimeouts: {$4: 110, $5: 120, '*': 150}, - perBuyerCumulativeTimeouts: {$4: 130, $5: 140, '*': 160}, + perBuyerCumulativeTimeouts: {$4: 13000, $5: 14000, '*': 16000}, perBuyerPrioritySignals: {$4: {foo: 1}, '*': {BaR: -2}} }); })())", @@ -7821,7 +7816,7 @@ sellerTimeout: 200, perBuyerSignals: {$4: {signalsForBuyer: 1}, $5: {signalsForBuyer: 2}}, perBuyerTimeouts: {$4: 110, $5: 120, '*': 150}, - perBuyerCumulativeTimeouts: {$4: 130, $5: 140, '*': 160}, + perBuyerCumulativeTimeouts: {$4: 13000, $5: 14000, '*': 16000}, perBuyerPrioritySignals: {$4: {foo: 1}, '*': {BaR: -2}} }); })())", @@ -7999,7 +7994,7 @@ sellerTimeout: 300, perBuyerSignals: maybePromise({$8: ["top-level buyer signals"]}), perBuyerTimeouts: maybePromise({$8: 110, '*': 150}), - perBuyerCumulativeTimeouts: maybePromise({$8: 111, '*': 151}), + perBuyerCumulativeTimeouts: maybePromise({$8: 11100, '*': 15100}), perBuyerPrioritySignals: {'*': {foo: 3}}, componentAuctions: [{ seller: $5, @@ -8012,7 +8007,7 @@ sellerTimeout: 200, perBuyerSignals: maybePromise({$8: ["component buyer signals"]}), perBuyerTimeouts: maybePromise({$8: 200}), - perBuyerCumulativeTimeouts: maybePromise({$8: 201}), + perBuyerCumulativeTimeouts: maybePromise({$8: 20100}), perBuyerPrioritySignals: {$8: {bar: 1}, '*': {BaZ: -2}}, }], }); @@ -8671,13 +8666,13 @@ let ok = 0; for (key in perBuyerCumulativeTimeouts) { if (key.startsWith("https://a.test") && - perBuyerCumulativeTimeouts[key] === 70) { + perBuyerCumulativeTimeouts[key] === 7000) { ++ok; } else if (key === "https://c.test" && - perBuyerCumulativeTimeouts[key] === 80) { + perBuyerCumulativeTimeouts[key] === 8000) { ++ok; } else if (key === '*' && - perBuyerCumulativeTimeouts[key] === 76) { + perBuyerCumulativeTimeouts[key] === 7600) { ++ok; } else { throw 'Wrong key in perCumulativeBuyerTimeouts ' + @@ -8733,7 +8728,7 @@ }), perBuyerCumulativeTimeouts: new Promise((resolve, reject) => { setTimeout( - () => { resolve({$1: 70, 'https://c.test': 80, '*': 76}); }, 1) + () => { resolve({$1: 7000, 'https://c.test': 8000, '*': 7600}); }, 1) }) }); })())",
diff --git a/content/browser/interest_group/interest_group_storage.cc b/content/browser/interest_group/interest_group_storage.cc index b738851..b01a04a 100644 --- a/content/browser/interest_group/interest_group_storage.cc +++ b/content/browser/interest_group/interest_group_storage.cc
@@ -51,7 +51,7 @@ using auction_worklet::mojom::BiddingBrowserSignalsPtr; using auction_worklet::mojom::PreviousWinPtr; -using SellerCapabilitiesType = blink::InterestGroup::SellerCapabilitiesType; +using SellerCapabilitiesType = blink::SellerCapabilitiesType; const base::FilePath::CharType kDatabasePath[] = FILE_PATH_LITERAL("InterestGroups");
diff --git a/content/browser/interest_group/interest_group_storage_unittest.cc b/content/browser/interest_group/interest_group_storage_unittest.cc index 10d8cbb4..90601c41 100644 --- a/content/browser/interest_group/interest_group_storage_unittest.cc +++ b/content/browser/interest_group/interest_group_storage_unittest.cc
@@ -43,8 +43,8 @@ using testing::Field; using testing::UnorderedElementsAre; using testing::UnorderedElementsAreArray; -using SellerCapabilities = blink::InterestGroup::SellerCapabilities; -using SellerCapabilitiesType = blink::InterestGroup::SellerCapabilitiesType; +using SellerCapabilities = blink::SellerCapabilities; +using SellerCapabilitiesType = blink::SellerCapabilitiesType; class InterestGroupStorageTest : public testing::Test { public:
diff --git a/content/browser/interest_group/interest_group_update.h b/content/browser/interest_group/interest_group_update.h index 1677b3f..cb84663 100644 --- a/content/browser/interest_group/interest_group_update.h +++ b/content/browser/interest_group/interest_group_update.h
@@ -38,11 +38,9 @@ // old overrides around. Keys mapped to nullopt are deleted. absl::optional<base::flat_map<std::string, absl::optional<double>>> priority_signals_overrides; - absl::optional< - base::flat_map<url::Origin, blink::InterestGroup::SellerCapabilitiesType>> + absl::optional<base::flat_map<url::Origin, blink::SellerCapabilitiesType>> seller_capabilities; - absl::optional<blink::InterestGroup::SellerCapabilitiesType> - all_sellers_capabilities; + absl::optional<blink::SellerCapabilitiesType> all_sellers_capabilities; absl::optional<blink::InterestGroup::ExecutionMode> execution_mode; absl::optional<GURL> bidding_url; absl::optional<GURL> bidding_wasm_helper_url;
diff --git a/content/browser/interest_group/interest_group_update_manager.cc b/content/browser/interest_group/interest_group_update_manager.cc index 196d1f3..04604459 100644 --- a/content/browser/interest_group/interest_group_update_manager.cc +++ b/content/browser/interest_group/interest_group_update_manager.cc
@@ -176,24 +176,21 @@ if (!maybe_dict->is_dict()) return false; - std::vector< - std::pair<url::Origin, blink::InterestGroup::SellerCapabilitiesType>> + std::vector<std::pair<url::Origin, blink::SellerCapabilitiesType>> seller_capabilities_vec; for (const std::pair<const std::string&, const base::Value&> pair : maybe_dict->GetDict()) { if (!pair.second.is_list()) return false; - blink::InterestGroup::SellerCapabilitiesType capabilities; + blink::SellerCapabilitiesType capabilities; for (const base::Value& maybe_capability : pair.second.GetList()) { if (!maybe_capability.is_string()) return false; const std::string& capability = maybe_capability.GetString(); if (capability == "interestGroupCounts") { - capabilities.Put( - blink::InterestGroup::SellerCapabilities::kInterestGroupCounts); + capabilities.Put(blink::SellerCapabilities::kInterestGroupCounts); } else if (capability == "latencyStats") { - capabilities.Put( - blink::InterestGroup::SellerCapabilities::kLatencyStats); + capabilities.Put(blink::SellerCapabilities::kLatencyStats); } else { return false; }
diff --git a/content/browser/loader/navigation_url_loader_impl_unittest.cc b/content/browser/loader/navigation_url_loader_impl_unittest.cc index 43df28f..35521b4 100644 --- a/content/browser/loader/navigation_url_loader_impl_unittest.cc +++ b/content/browser/loader/navigation_url_loader_impl_unittest.cc
@@ -237,7 +237,8 @@ base::TimeTicks() /* renderer_before_unload_end */, absl::nullopt /* web_bundle_token */, blink::mojom::NavigationInitiatorActivationAndAdStatus:: - kDidNotStartWithTransientActivation); + kDidNotStartWithTransientActivation, + false /* is_container_initiated */); auto common_params = blink::CreateCommonNavigationParams(); common_params->url = url;
diff --git a/content/browser/loader/navigation_url_loader_unittest.cc b/content/browser/loader/navigation_url_loader_unittest.cc index 3df6640..229b08c 100644 --- a/content/browser/loader/navigation_url_loader_unittest.cc +++ b/content/browser/loader/navigation_url_loader_unittest.cc
@@ -98,7 +98,8 @@ base::TimeTicks() /* renderer_before_unload_end */, absl::nullopt /* web_bundle_token */, blink::mojom::NavigationInitiatorActivationAndAdStatus:: - kDidNotStartWithTransientActivation); + kDidNotStartWithTransientActivation, + false /* is_container_initiated */); auto common_params = blink::CreateCommonNavigationParams(); common_params->url = url; common_params->initiator_origin = url::Origin::Create(url);
diff --git a/content/browser/loader/object_navigation_fallback_body_loader.cc b/content/browser/loader/object_navigation_fallback_body_loader.cc index f7b0f41..57405999 100644 --- a/content/browser/loader/object_navigation_fallback_body_loader.cc +++ b/content/browser/loader/object_navigation_fallback_body_loader.cc
@@ -10,7 +10,6 @@ #include "base/containers/contains.h" #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" -#include "content/browser/loader/resource_timing_utils.h" #include "content/browser/renderer_host/frame_tree_node.h" #include "content/browser/renderer_host/navigation_request.h" #include "content/browser/renderer_host/render_frame_host_impl.h" @@ -32,35 +31,15 @@ namespace content { -namespace { - -std::string ExtractServerTimingValueIfNeeded( - const network::mojom::URLResponseHead& response_head) { - std::string value; - if (!response_head.timing_allow_passed) - return value; - - // Note: the renderer will be responsible for parsing the actual server - // timing values. - response_head.headers->GetNormalizedHeader("Server-Timing", &value); - return value; -} - -} // namespace - NAVIGATION_HANDLE_USER_DATA_KEY_IMPL(ObjectNavigationFallbackBodyLoader); // static void ObjectNavigationFallbackBodyLoader::CreateAndStart( NavigationRequest& navigation_request, - const blink::mojom::CommonNavigationParams& common_params, - const blink::mojom::CommitNavigationParams& commit_params, - const network::mojom::URLResponseHead& response_head, mojo::ScopedDataPipeConsumerHandle response_body, network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints, base::OnceClosure completion_closure) { // This should only be called for HTTP errors. - DCHECK(response_head.headers); RenderFrameHostImpl* render_frame_host = navigation_request.frame_tree_node()->current_frame_host(); // A frame owned by <object> should always have a parent. @@ -68,25 +47,15 @@ // It's safe to snapshot the parent origin in the calculation here; if the // parent frame navigates, `render_frame_host_` will be deleted, which // triggers deletion of `this`, cancelling all remaining work. - blink::mojom::ResourceTimingInfoPtr timing_info = - GenerateResourceTimingForNavigation( - render_frame_host->GetParent()->GetLastCommittedOrigin(), - common_params, commit_params, response_head); - std::string server_timing_value = - ExtractServerTimingValueIfNeeded(response_head); - - CreateForNavigationHandle( - navigation_request, std::move(timing_info), - std::move(server_timing_value), std::move(response_body), - std::move(url_loader_client_endpoints), std::move(completion_closure)); + CreateForNavigationHandle(navigation_request, std::move(response_body), + std::move(url_loader_client_endpoints), + std::move(completion_closure)); } ObjectNavigationFallbackBodyLoader::~ObjectNavigationFallbackBodyLoader() {} ObjectNavigationFallbackBodyLoader::ObjectNavigationFallbackBodyLoader( NavigationHandle& navigation_handle, - blink::mojom::ResourceTimingInfoPtr timing_info, - std::string server_timing_value, mojo::ScopedDataPipeConsumerHandle response_body, network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints, base::OnceClosure completion_closure) @@ -98,8 +67,6 @@ response_body_drainer_( std::make_unique<mojo::DataPipeDrainer>(this, std::move(response_body))), - timing_info_(std::move(timing_info)), - server_timing_value_(std::move(server_timing_value)), completion_closure_(std::move(completion_closure)) { // Unretained is safe; `url_loader_` is owned by `this` and will not dispatch // callbacks after it is destroyed. @@ -165,25 +132,9 @@ // `completion_closure_` will delete the NavigationRequest, which will delete // `this`. base::ScopedClosureRunner cleanup(std::move(completion_closure_)); - - timing_info_->response_end = status.completion_time; - timing_info_->encoded_body_size = status.encoded_body_length; - timing_info_->decoded_body_size = status.decoded_body_length; - - RenderFrameHostManager* render_manager = - navigation_request_->frame_tree_node()->render_manager(); - if (RenderFrameProxyHost* proxy = render_manager->GetProxyToParent()) { - if (proxy->is_render_frame_proxy_live()) { - proxy->GetAssociatedRemoteFrame() - ->RenderFallbackContentWithResourceTiming(std::move(timing_info_), - server_timing_value_); - } - } else { - render_manager->current_frame_host() - ->GetAssociatedLocalFrame() - ->RenderFallbackContentWithResourceTiming(std::move(timing_info_), - server_timing_value_); - } + navigation_request_->AddResourceTimingEntryForFailedSubframeNavigation( + status); + navigation_request_->RenderFallbackContentForObjectTag(); } void ObjectNavigationFallbackBodyLoader::OnDataAvailable(const void* data,
diff --git a/content/browser/loader/object_navigation_fallback_body_loader.h b/content/browser/loader/object_navigation_fallback_body_loader.h index 34acb77..5568126 100644 --- a/content/browser/loader/object_navigation_fallback_body_loader.h +++ b/content/browser/loader/object_navigation_fallback_body_loader.h
@@ -21,12 +21,6 @@ #include "third_party/blink/public/mojom/navigation/navigation_params.mojom-forward.h" #include "third_party/blink/public/mojom/timing/resource_timing.mojom.h" -namespace network { -namespace mojom { -class URLResponseHead; -} // namespace mojom -} // namespace network - namespace content { class NavigationRequest; @@ -59,9 +53,6 @@ public network::mojom::URLLoaderClient, public mojo::DataPipeDrainer::Client { public: - // `common_params, `commit_params`, and `response_head` are used to - // (partially) generate the resource timing info. - // // `response_body` and `url_loader_client_endpoints` are used to drain the // responise body and calculate the body / data size needed for the // performance entry. @@ -75,9 +66,6 @@ // response body is successfully loaded. static void CreateAndStart( NavigationRequest& navigation_request, - const blink::mojom::CommonNavigationParams& common_params, - const blink::mojom::CommitNavigationParams& commit_params, - const network::mojom::URLResponseHead& response_head, mojo::ScopedDataPipeConsumerHandle response_body, network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints, base::OnceClosure completion_closure); @@ -90,8 +78,6 @@ ObjectNavigationFallbackBodyLoader( NavigationHandle& navigation_handle, - blink::mojom::ResourceTimingInfoPtr timing_info, - std::string server_timing_value, mojo::ScopedDataPipeConsumerHandle response_body, network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints, base::OnceClosure completion_closure); @@ -123,8 +109,6 @@ // `response_body_drainer_` will be reset to null when the response body is // completely drained. std::unique_ptr<mojo::DataPipeDrainer> response_body_drainer_; - blink::mojom::ResourceTimingInfoPtr timing_info_; - std::string server_timing_value_; base::OnceClosure completion_closure_; };
diff --git a/content/browser/loader/resource_timing_utils.cc b/content/browser/loader/resource_timing_utils.cc deleted file mode 100644 index 749756ba9a..0000000 --- a/content/browser/loader/resource_timing_utils.cc +++ /dev/null
@@ -1,106 +0,0 @@ -// Copyright 2023 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/browser/loader/resource_timing_utils.h" - -#include <string> -#include <utility> - -#include "base/containers/contains.h" -#include "net/http/http_response_info.h" -#include "third_party/blink/public/mojom/navigation/navigation_params.mojom.h" -#include "third_party/blink/public/mojom/timing/resource_timing.mojom.h" -#include "url/gurl.h" -#include "url/url_util.h" - -namespace { - -// Implements the TimingAllowOrigin check -// This logic is duplicated from Performance::AllowsTimingRedirect(). Ensure -// that any changes are synced between both copies. -bool IsCrossOriginResponseOrHasCrossOriginRedirects( - const url::Origin& parent_origin, - const blink::mojom::CommonNavigationParams& common_params, - const blink::mojom::CommitNavigationParams& commit_params) { - DCHECK_EQ(commit_params.redirect_infos.size(), - commit_params.redirect_response.size()); - for (const auto& info : commit_params.redirect_infos) { - if (!parent_origin.IsSameOriginWith(info.new_url)) { - return true; - } - } - - return !parent_origin.IsSameOriginWith(common_params.url); -} - -} // namespace - -namespace content { - -// This logic is duplicated from blink::CreateResourceTimingInfo(). Ensure -// that any changes are synced between both copies. -blink::mojom::ResourceTimingInfoPtr GenerateResourceTimingForNavigation( - const url::Origin& parent_origin, - const blink::mojom::CommonNavigationParams& common_params, - const blink::mojom::CommitNavigationParams& commit_params, - const network::mojom::URLResponseHead& response_head) { - // TODO(dcheng): There should be a Blink helper for populating the timing info - // that's exposed in //third_party/blink/common. This would allow a lot of the - // boilerplate to be shared. - - auto timing_info = blink::mojom::ResourceTimingInfo::New(); - const GURL& initial_url = !commit_params.original_url.is_empty() - ? commit_params.original_url - : common_params.url; - timing_info->name = initial_url.spec(); - timing_info->start_time = common_params.navigation_start; - timing_info->allow_timing_details = response_head.timing_allow_passed; - - // Only expose the response code when we are same origin and without - // cross-origin redirects - // https://fetch.spec.whatwg.org/#ref-for-concept-response-status%E2%91%A6 - if (!IsCrossOriginResponseOrHasCrossOriginRedirects( - parent_origin, common_params, commit_params)) { - timing_info->response_status = commit_params.http_response_code; - } - - // https://fetch.spec.whatwg.org/#create-an-opaque-timing-info - if (!timing_info->allow_timing_details) { - return timing_info; - } - - timing_info->alpn_negotiated_protocol = - response_head.alpn_negotiated_protocol; - timing_info->connection_info = net::HttpResponseInfo::ConnectionInfoToString( - response_head.connection_info); - - // If there's no received headers end time, don't set load timing. This is the - // case for non-HTTP requests, requests that don't go over the wire, and - // certain error cases. - // TODO(dcheng): Is it actually possible to hit this path if - // `response_head.headers` is populated? - if (!response_head.load_timing.receive_headers_end.is_null()) { - timing_info->timing = response_head.load_timing; - } - // `response_end` will be populated after loading the body. - - DCHECK_EQ(commit_params.redirect_infos.size(), - commit_params.redirect_response.size()); - - if (!commit_params.redirect_infos.empty()) { - timing_info->last_redirect_end_time = - commit_params.redirect_response.back()->load_timing.receive_headers_end; - } else { - timing_info->last_redirect_end_time = base::TimeTicks(); - } - // The final value for `encoded_body_size` and `decoded_body_size` will be - // populated after loading the body. - timing_info->did_reuse_connection = response_head.load_timing.socket_reused; - // Use url::Origin to handle cases like blob:https://. - timing_info->is_secure_transport = base::Contains( - url::GetSecureSchemes(), url::Origin::Create(common_params.url).scheme()); - timing_info->allow_negative_values = false; - return timing_info; -} -} // namespace content
diff --git a/content/browser/loader/resource_timing_utils.h b/content/browser/loader/resource_timing_utils.h deleted file mode 100644 index 764495b..0000000 --- a/content/browser/loader/resource_timing_utils.h +++ /dev/null
@@ -1,24 +0,0 @@ -// Copyright 2023 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_BROWSER_LOADER_RESOURCE_TIMING_UTILS_H_ -#define CONTENT_BROWSER_LOADER_RESOURCE_TIMING_UTILS_H_ - -#include "services/network/public/mojom/url_response_head.mojom-forward.h" -#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-forward.h" -#include "third_party/blink/public/mojom/navigation/navigation_params.mojom-forward.h" -#include "third_party/blink/public/mojom/timing/resource_timing.mojom-forward.h" -#include "url/origin.h" - -namespace content { - -blink::mojom::ResourceTimingInfoPtr GenerateResourceTimingForNavigation( - const url::Origin& parent_origin, - const blink::mojom::CommonNavigationParams& common_params, - const blink::mojom::CommitNavigationParams& commit_params, - const network::mojom::URLResponseHead& response_head); - -} // namespace content - -#endif
diff --git a/content/browser/renderer_host/back_forward_cache_impl.h b/content/browser/renderer_host/back_forward_cache_impl.h index a3f2b7c..92d1ec2 100644 --- a/content/browser/renderer_host/back_forward_cache_impl.h +++ b/content/browser/renderer_host/back_forward_cache_impl.h
@@ -162,6 +162,11 @@ stored_page_->SetDelegate(delegate); } + void SetViewTransitionState( + absl::optional<blink::ViewTransitionState> view_transition_state) { + stored_page_->SetViewTransitionState(std::move(view_transition_state)); + } + // The main document being stored. RenderFrameHostImpl* render_frame_host() { return stored_page_->render_frame_host();
diff --git a/content/browser/renderer_host/ipc_utils.cc b/content/browser/renderer_host/ipc_utils.cc index 3a2dab5..aa8a0028 100644 --- a/content/browser/renderer_host/ipc_utils.cc +++ b/content/browser/renderer_host/ipc_utils.cc
@@ -171,6 +171,16 @@ return false; } + if (params->is_container_initiated) { + if (!current_rfh->GetParent() || + (current_rfh->GetParent()->GetFrameToken() != + params->initiator_frame_token)) { + mojo::ReportBadMessage( + "container initiated navigation from non-parent process"); + return false; + } + } + // Verification succeeded. return true; }
diff --git a/content/browser/renderer_host/navigation_controller_impl.cc b/content/browser/renderer_host/navigation_controller_impl.cc index 358540b..b74775eb 100644 --- a/content/browser/renderer_host/navigation_controller_impl.cc +++ b/content/browser/renderer_host/navigation_controller_impl.cc
@@ -2692,7 +2692,8 @@ base::TimeTicks navigation_start_time, bool is_embedder_initiated_fenced_frame_navigation, bool is_unfenced_top_navigation, - bool force_new_browsing_instance) { + bool force_new_browsing_instance, + bool is_container_initiated) { if (is_renderer_initiated) DCHECK(initiator_origin.has_value()); @@ -2817,7 +2818,7 @@ false /* has_user_gesture */, std::move(source_location), ReloadType::NONE, entry.get(), frame_entry.get(), navigation_start_time, is_embedder_initiated_fenced_frame_navigation, - is_unfenced_top_navigation); + is_unfenced_top_navigation, is_container_initiated); if (!request) return; @@ -3760,7 +3761,8 @@ FrameNavigationEntry* frame_entry, base::TimeTicks navigation_start_time, bool is_embedder_initiated_fenced_frame_navigation, - bool is_unfenced_top_navigation) { + bool is_unfenced_top_navigation, + bool is_container_initiated) { DCHECK_EQ(-1, GetIndexOfEntry(entry)); DCHECK(frame_entry); // All renderer-initiated navigations must have an initiator_origin. @@ -3931,7 +3933,8 @@ params.is_form_submission, params.navigation_ui_data ? params.navigation_ui_data->Clone() : nullptr, params.impression, params.initiator_activation_and_ad_status, - params.is_pdf, is_embedder_initiated_fenced_frame_navigation); + params.is_pdf, is_embedder_initiated_fenced_frame_navigation, + is_container_initiated); navigation_request->set_from_download_cross_origin_redirect( params.from_download_cross_origin_redirect); navigation_request->set_force_new_browsing_instance(
diff --git a/content/browser/renderer_host/navigation_controller_impl.h b/content/browser/renderer_host/navigation_controller_impl.h index ebb6afd8..ccdf116 100644 --- a/content/browser/renderer_host/navigation_controller_impl.h +++ b/content/browser/renderer_host/navigation_controller_impl.h
@@ -227,7 +227,8 @@ base::TimeTicks navigation_start_time, bool is_embedder_initiated_fenced_frame_navigation = false, bool is_unfenced_top_navigation = false, - bool force_new_browsing_instance = false); + bool force_new_browsing_instance = false, + bool is_container_initiated = false); // Navigates to the history entry associated with the given navigation API // |key|. Searches |entries_| for a FrameNavigationEntry associated with @@ -653,7 +654,8 @@ FrameNavigationEntry* frame_entry, base::TimeTicks navigation_start_time, bool is_embedder_initiated_fenced_frame_navigation = false, - bool is_unfenced_top_navigation = false); + bool is_unfenced_top_navigation = false, + bool is_container_initiated = false); // Creates and returns a NavigationRequest for a navigation to |entry|. Will // return nullptr if the parameters are invalid and the navigation cannot
diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc index b50193b..2717fd4 100644 --- a/content/browser/renderer_host/navigation_request.cc +++ b/content/browser/renderer_host/navigation_request.cc
@@ -53,7 +53,6 @@ #include "content/browser/loader/navigation_early_hints_manager.h" #include "content/browser/loader/navigation_url_loader.h" #include "content/browser/loader/object_navigation_fallback_body_loader.h" -#include "content/browser/loader/resource_timing_utils.h" #include "content/browser/navigation_or_document_handle.h" #include "content/browser/network/cross_origin_embedder_policy_reporter.h" #include "content/browser/network/cross_origin_opener_policy_reporter.h" @@ -79,6 +78,7 @@ #include "content/browser/renderer_host/render_process_host_impl.h" #include "content/browser/renderer_host/render_view_host_delegate.h" #include "content/browser/renderer_host/render_view_host_impl.h" +#include "content/browser/runtime_feature_state/runtime_feature_state_document_data.h" #include "content/browser/scoped_active_url.h" #include "content/browser/service_worker/service_worker_context_wrapper.h" #include "content/browser/service_worker/service_worker_main_resource_handle.h" @@ -140,6 +140,7 @@ #include "services/network/public/cpp/web_sandbox_flags.h" #include "services/network/public/mojom/fetch_api.mojom.h" #include "services/network/public/mojom/supports_loading_mode.mojom.h" +#include "services/network/public/mojom/url_response_head.mojom-forward.h" #include "services/network/public/mojom/url_response_head.mojom-shared.h" #include "services/network/public/mojom/url_response_head.mojom.h" #include "services/network/public/mojom/web_client_hints_types.mojom-shared.h" @@ -169,6 +170,7 @@ #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h" #include "third_party/blink/public/mojom/loader/mixed_content.mojom.h" #include "third_party/blink/public/mojom/loader/transferrable_url_loader.mojom.h" +#include "third_party/blink/public/mojom/navigation/navigation_params.mojom-shared.h" #include "third_party/blink/public/mojom/navigation/navigation_params.mojom.h" #include "third_party/blink/public/mojom/navigation/prefetched_signed_exchange_info.mojom.h" #include "third_party/blink/public/mojom/runtime_feature_state/runtime_feature_state.mojom.h" @@ -1098,7 +1100,8 @@ blink::mojom::NavigationInitiatorActivationAndAdStatus initiator_activation_and_ad_status, bool is_pdf, - bool is_embedder_initiated_fenced_frame_navigation) { + bool is_embedder_initiated_fenced_frame_navigation, + bool is_container_initiated) { TRACE_EVENT1("navigation", "NavigationRequest::Create", "browser_initiated", browser_initiated); @@ -1128,7 +1131,8 @@ nullptr /* trust_token_params */, impression, base::TimeTicks() /* renderer_before_unload_start */, base::TimeTicks() /* renderer_before_unload_end */, - std::move(web_bundle_token_params), initiator_activation_and_ad_status); + std::move(web_bundle_token_params), initiator_activation_and_ad_status, + is_container_initiated); // Shift-Reload forces bypassing caches and service workers. if (common_params->navigation_type == @@ -1453,13 +1457,21 @@ } else { // Otherwise we need to derive the top_level_site and ancestor_chain_bit. net::SchemefulSite top_level_site(top_level_origin); + + blink::mojom::AncestorChainBit ancestor_chain_bit = + blink::mojom::AncestorChainBit::kSameSite; + if (render_frame_host->ComputeSiteForCookies().IsNull() || + net::SchemefulSite(origin) != top_level_site || + !top_level_site.opaque() || origin.opaque()) { + ancestor_chain_bit = blink::mojom::AncestorChainBit::kCrossSite; + } + + // Because this is a synchronous commit from the renderer the RFH won't + // change meaning we can always query the main frame RFH for the status of + // storage partitioning. navigation_request->commit_params_->storage_key = blink::StorageKey::Create( - origin, top_level_site, - render_frame_host->ComputeSiteForCookies().IsNull() || - net::SchemefulSite(origin) != top_level_site || - origin.opaque() || top_level_site.opaque() - ? blink::mojom::AncestorChainBit::kCrossSite - : blink::mojom::AncestorChainBit::kSameSite); + origin, top_level_site, ancestor_chain_bit, + render_frame_host->IsMainFrameThirdPartyStoragePartitioningEnabled()); } navigation_request->commit_params_->session_storage_key = frame_tree_node->frame_tree().GetSessionStorageKey( @@ -1623,6 +1635,24 @@ if (initiator_rfh) initiator_document_ = initiator_rfh->GetWeakDocumentPtr(); } + + // Spec: https://github.com/whatwg/html/issues/8846 + // We only allow the parent to access a subframe resource timing if the + // navigation is container-initiated, e.g. iframe changed src. + if (begin_params_->is_container_initiated) { + // Only same-origin navigations without cross-origin redirects can + // expose response details (status-code / mime-type). + // https://github.com/whatwg/fetch/issues/1602 + // Note that this condition checks this navigation is not cross origin. + // Cross-origin redirects are checked as part of OnRequestRedirected(). + commit_params_->navigation_timing->parent_resource_timing_access = + GetParentFrame()->GetLastCommittedOrigin().IsSameOriginWith(GetURL()) + ? blink::mojom::ParentResourceTimingAccess:: + kReportWithResponseDetails + : blink::mojom::ParentResourceTimingAccess:: + kReportWithoutResponseDetails; + } + navigation_or_document_handle_ = NavigationOrDocumentHandle::CreateForNavigation(*this); @@ -3058,6 +3088,18 @@ const bool is_same_origin_redirect = url::Origin::Create(common_params_->url) .IsSameOriginWith(redirect_info.new_url); + + // Only same-origin navigations without cross-origin redirects can + // expose response details (status-code / mime-type). + // https://github.com/whatwg/fetch/issues/1602 + if (!is_same_origin_redirect && + commit_params_->navigation_timing->parent_resource_timing_access == + blink::mojom::ParentResourceTimingAccess:: + kReportWithResponseDetails) { + commit_params_->navigation_timing->parent_resource_timing_access = + blink::mojom::ParentResourceTimingAccess::kReportWithoutResponseDetails; + } + did_receive_early_hints_before_cross_origin_redirect_ |= did_create_early_hints_manager_params_ && !is_same_origin_redirect; @@ -3780,6 +3822,12 @@ return; } + // See https://github.com/whatwg/fetch/pull/1579 + if (!response_head_->timing_allow_passed) { + commit_params_->navigation_timing->parent_resource_timing_access = + blink::mojom::ParentResourceTimingAccess::kDoNotReport; + } + MaybeInjectIsolatedAppHeaders(); { @@ -4709,34 +4757,40 @@ return; } - RenderFrameHostImpl* parent_rfh = GetParentFrame(); - - // Do not add ResourceTiming entries if the navigated URL does not have a - // parent. - if (!parent_rfh) { - return; - } - // Some navigation are cancelled even before requesting and receiving a // response. Those cases are not supported and the ResourceTiming is not // reported to the parent. - if (!response_head_) { + if (!response()) { return; } - if (initiator_document_.AsRenderFrameHostIfValid() != parent_rfh) { + network::URLLoaderCompletionStatus status; + status.encoded_data_length = response()->encoded_data_length; + status.completion_time = base::TimeTicks::Now(); + AddResourceTimingEntryForFailedSubframeNavigation(status); +} + +void NavigationRequest::AddResourceTimingEntryForFailedSubframeNavigation( + const network::URLLoaderCompletionStatus& status) { + // For TAO-fail navigations, we would resort to fallback timing. + // See HTMLFrameOwnerElement::ReportFallbackResourceTimingIfNeeded(). + DCHECK(response()); + if (commit_params().navigation_timing->parent_resource_timing_access == + blink::mojom::ParentResourceTimingAccess::kDoNotReport) { return; } - blink::mojom::ResourceTimingInfoPtr timing_info = - GenerateResourceTimingForNavigation(parent_rfh->GetLastCommittedOrigin(), - *common_params_, *commit_params_, - *response_head_); - timing_info->response_end = base::TimeTicks::Now(); - parent_rfh->GetAssociatedLocalFrame() - ->AddResourceTimingEntryFromNonNavigatedFrame( - std::move(timing_info), - frame_tree_node()->frame_owner_element_type()); + network::mojom::URLResponseHeadPtr response_head = response()->Clone(); + + bool allow_response_details = + commit_params().navigation_timing->parent_resource_timing_access == + blink::mojom::ParentResourceTimingAccess::kReportWithResponseDetails; + + GetParentFrame()->AddResourceTimingEntryForFailedSubframeNavigation( + frame_tree_node(), common_params().navigation_start, + commit_params().navigation_timing->redirect_end, + commit_params().original_url, common_params().url, + std::move(response_head), allow_response_details, status); } void NavigationRequest::OnRedirectChecksComplete( @@ -4984,8 +5038,8 @@ // fallback / resource timing are only reported if the navigation request // is logically still pending. ObjectNavigationFallbackBodyLoader::CreateAndStart( - *this, *common_params_, *commit_params_, *response(), - std::move(response_body_), std::move(url_loader_client_endpoints_), + *this, std::move(response_body_), + std::move(url_loader_client_endpoints_), base::BindOnce(&NavigationRequest::OnRequestFailedInternal, weak_factory_.GetWeakPtr(), network::URLLoaderCompletionStatus(net::ERR_ABORTED), @@ -5007,6 +5061,7 @@ result.action() == NavigationThrottle::CANCEL || !response_should_be_rendered_) { MaybeAddResourceTimingEntryForCancelledNavigation(); + // Reset the RenderFrameHost that had been computed for the commit of the // navigation. render_frame_host_ = nullptr; @@ -5228,8 +5283,22 @@ absl::optional<base::UnguessableToken> nonce = render_frame_host_->ComputeNonce(is_credentialless(), ComputeFencedFrameNonce()); + + // Determine if we should allow partitioned StorageKeys. + // + // If this is a main frame navigation then the value of + // third_party_storage_partitioning_enabled is irrelevant because main frames + // are always first-party by definition. If this is a subframe navigation + // then the main frame will have the correct value. + bool third_party_storage_partitioning_enabled = false; + if (!IsInMainFrame()) { + third_party_storage_partitioning_enabled = + GetRenderFrameHost()->IsMainFrameThirdPartyStoragePartitioningEnabled(); + } + commit_params_->storage_key = render_frame_host_->CalculateStorageKey( - GetOriginToCommit().value(), base::OptionalToPtr(nonce)); + GetOriginToCommit().value(), base::OptionalToPtr(nonce), + third_party_storage_partitioning_enabled); commit_params_->session_storage_key = frame_tree_node()->frame_tree().GetSessionStorageKey( commit_params_->storage_key); @@ -5443,13 +5512,6 @@ commit_params_->pending_history_list_offset; page_restore_params->current_history_list_length = commit_params_->current_history_list_length; - page_restore_params->view_transition_state = - std::move(commit_params_->view_transition_state); - // Since we moved the view transition state to page restore params, we - // should reset the commit params one (move doesn't clear the optional). - // This ensures that we don't erroneously think that view_transition_state - // is unhandled and attempt to clean it up. - commit_params_->view_transition_state.reset(); activated_entry = controller->GetBackForwardCache().RestoreEntry( nav_entry_id_, std::move(page_restore_params)); // The only time activated_entry can be nullptr here, is if the @@ -5492,6 +5554,11 @@ if (!weak_self) return; + // Use std::exchange instead of move, so that we clear out the optional on + // the commit_params. + activated_entry->SetViewTransitionState( + std::exchange(commit_params_->view_transition_state, {})); + // Move the BackForwardCacheImpl::Entry into RenderFrameHostManager, in // preparation for committing. This entry may be either restored from the // backforward cache. @@ -5553,9 +5620,14 @@ if (!weak_self) return; + DCHECK(stored_page); + // Use std::exchange instead of move, so that we clear out the optional on + // the commit_params. + stored_page->SetViewTransitionState( + std::exchange(commit_params_->view_transition_state, {})); + // Move the StoredPage into RenderFrameHostManager, in // preparation for committing. This entry may be used for prerendering. - DCHECK(stored_page); frame_tree_node_->render_manager()->ActivatePrerender( std::move(stored_page)); }
diff --git a/content/browser/renderer_host/navigation_request.h b/content/browser/renderer_host/navigation_request.h index 3d53578..14d3a6c 100644 --- a/content/browser/renderer_host/navigation_request.h +++ b/content/browser/renderer_host/navigation_request.h
@@ -260,7 +260,8 @@ blink::mojom::NavigationInitiatorActivationAndAdStatus initiator_activation_and_ad_status, bool is_pdf, - bool is_embedder_initiated_fenced_frame_navigation = false); + bool is_embedder_initiated_fenced_frame_navigation = false, + bool is_container_initiated = false); // Creates a request for a renderer-initiated navigation. static std::unique_ptr<NavigationRequest> CreateRendererInitiated( @@ -568,6 +569,11 @@ // a request was made. void MaybeAddResourceTimingEntryForCancelledNavigation(); + // Adds a resource timing entry to the parent in case of cancelled navigations + // and failed <object> navigations. + void AddResourceTimingEntryForFailedSubframeNavigation( + const network::URLLoaderCompletionStatus& status); + // Lazily initializes and returns the mojo::NavigationClient interface used // for commit. mojom::NavigationClient* GetCommitNavigationClient();
diff --git a/content/browser/renderer_host/navigation_request_unittest.cc b/content/browser/renderer_host/navigation_request_unittest.cc index 0746732..1a133a80 100644 --- a/content/browser/renderer_host/navigation_request_unittest.cc +++ b/content/browser/renderer_host/navigation_request_unittest.cc
@@ -32,6 +32,7 @@ #include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/public/common/navigation/navigation_params.h" #include "third_party/blink/public/common/origin_trials/scoped_test_origin_trial_policy.h" +#include "third_party/blink/public/common/runtime_feature_state/runtime_feature_state_context.h" #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h" namespace content { @@ -711,6 +712,139 @@ child_document->storage_key()); } +// Test that the StorageKey's value is correctly affected by the +// RuntimeFeatureStateContext. +TEST_F(NavigationRequestTest, RuntimeFeatureStateStorageKey) { + base::test::ScopedFeatureList scoped_feature_list; + // Because the StorageKey's (and Storage Partitioning's) usage of + // RuntimeFeatureState is only meant to disable partitioning (i.e.: + // first-party only), we need the make sure the net::features is always + // enabled. + scoped_feature_list.InitAndEnableFeature( + net::features::kThirdPartyStoragePartitioning); + + // This lambda performs the navigation and compares the commit_params' + // StorageKey against the passed in one. If `disable_sp` is true then it will + // also disable ThirdPartyStoragePartitioningEnabled in the RFSC. It returns + // the new TestRenderFrameHost* to the navigated frame. + auto NavigateAndCompareKeys = + [](NavigationSimulator* navigation, const blink::StorageKey& key, + bool disable_sp = false) -> TestRenderFrameHost* { + navigation->Start(); + + NavigationRequest* request = + NavigationRequest::From(navigation->GetNavigationHandle()); + + if (disable_sp) { + request->GetMutableRuntimeFeatureStateContext() + .SetThirdPartyStoragePartitioningEnabled(false); + } + + navigation->ReadyToCommit(); + + EXPECT_EQ(key, request->commit_params().storage_key); + + navigation->Commit(); + return static_cast<TestRenderFrameHost*>( + navigation->GetFinalRenderFrameHost()); + }; + + // Throughout the test we'll be creating a frame tree with a main frame, a + // child frame, and a grandchild frame. + GURL main_url("https://main.com"); + GURL b_url("https://b.com"); + GURL c_url("https://c.com"); + + url::Origin main_origin = url::Origin::Create(main_url); + url::Origin b_origin = url::Origin::Create(b_url); + url::Origin c_origin = url::Origin::Create(c_url); + + // Begin by testing with Storage Partitioning enabled. + + auto main_navigation = + NavigationSimulatorImpl::CreateBrowserInitiated(main_url, contents()); + + // By definition the main frame's StorageKey will always be first party + blink::StorageKey main_frame_key = + blink::StorageKey::CreateFirstParty(main_origin); + + NavigateAndCompareKeys(main_navigation.get(), main_frame_key); + + TestRenderFrameHost* child_frame = static_cast<TestRenderFrameHost*>( + content::RenderFrameHostTester::For(main_rfh())->AppendChild("child")); + + auto child_navigation = + NavigationSimulatorImpl::CreateRendererInitiated(b_url, child_frame); + + // The child and grandchild should both be third-party keys. + blink::StorageKey child_frame_key = + blink::StorageKey::Create(b_origin, net::SchemefulSite(main_origin), + blink::mojom::AncestorChainBit::kCrossSite); + + child_frame = NavigateAndCompareKeys(child_navigation.get(), child_frame_key); + + TestRenderFrameHost* grandchild_frame = + child_frame->AppendChild("grandchild"); + + auto grandchild_navigation = + NavigationSimulatorImpl::CreateRendererInitiated(c_url, grandchild_frame); + + blink::StorageKey grandchild_frame_key = + blink::StorageKey::Create(c_origin, net::SchemefulSite(main_origin), + blink::mojom::AncestorChainBit::kCrossSite); + grandchild_frame = + NavigateAndCompareKeys(grandchild_navigation.get(), grandchild_frame_key); + + // Only the RuntimeFeatureStateContext in the main frame's matters. So + // disabling Storage Partitioning in the child_frame shouldn't affect the + // child's or the grandchild's StorageKey. + child_navigation = + NavigationSimulatorImpl::CreateRendererInitiated(b_url, child_frame); + + child_frame = NavigateAndCompareKeys(child_navigation.get(), child_frame_key, + /*disable_sp=*/true); + + grandchild_frame = child_frame->AppendChild("grandchild"); + + grandchild_navigation = + NavigationSimulatorImpl::CreateRendererInitiated(c_url, grandchild_frame); + + grandchild_frame = + NavigateAndCompareKeys(grandchild_navigation.get(), grandchild_frame_key); + + // Disabling Storage Partitioning on the main frame should cause the child's + // and grandchild's StorageKey to be first-party. + main_navigation = + NavigationSimulatorImpl::CreateBrowserInitiated(main_url, contents()); + + NavigateAndCompareKeys(main_navigation.get(), main_frame_key, + /*disable_sp=*/true); + + child_frame = static_cast<TestRenderFrameHost*>( + content::RenderFrameHostTester::For(main_rfh())->AppendChild("child")); + + child_navigation = + NavigationSimulatorImpl::CreateRendererInitiated(b_url, child_frame); + + // The child and grandchild should both be first-party keys. + blink::StorageKey child_frame_key_1p = + blink::StorageKey::CreateFirstParty(b_origin); + + child_frame = + NavigateAndCompareKeys(child_navigation.get(), child_frame_key_1p); + + grandchild_frame = child_frame->AppendChild("grandchild"); + + blink::StorageKey grandchild_frame_key_1p = + blink::StorageKey::CreateFirstParty(c_origin); + + grandchild_navigation = + NavigationSimulatorImpl::CreateRendererInitiated(c_url, grandchild_frame); + + grandchild_frame = NavigateAndCompareKeys(grandchild_navigation.get(), + grandchild_frame_key_1p); +} + TEST_F(NavigationRequestTest, NavigationToCredentiallessDocumentNetworkIsolationInfo) { auto* child_frame = static_cast<TestRenderFrameHost*>(
diff --git a/content/browser/renderer_host/navigator.cc b/content/browser/renderer_host/navigator.cc index fc5ddfc..d4868e7 100644 --- a/content/browser/renderer_host/navigator.cc +++ b/content/browser/renderer_host/navigator.cc
@@ -872,7 +872,8 @@ base::TimeTicks navigation_start_time, bool is_embedder_initiated_fenced_frame_navigation, bool is_unfenced_top_navigation, - bool force_new_browsing_instance) { + bool force_new_browsing_instance, + bool is_container_initiated) { // |method != "POST"| should imply absence of |post_body|. if (method != "POST" && post_body) { NOTREACHED(); @@ -917,7 +918,7 @@ std::move(blob_url_loader_factory), is_form_submission, impression, initiator_activation_and_ad_status, navigation_start_time, is_embedder_initiated_fenced_frame_navigation, is_unfenced_top_navigation, - force_new_browsing_instance); + force_new_browsing_instance, is_container_initiated); } void Navigator::BeforeUnloadCompleted(FrameTreeNode* frame_tree_node,
diff --git a/content/browser/renderer_host/navigator.h b/content/browser/renderer_host/navigator.h index e3bd62d..f344ec2 100644 --- a/content/browser/renderer_host/navigator.h +++ b/content/browser/renderer_host/navigator.h
@@ -165,7 +165,8 @@ base::TimeTicks navigation_start_time, bool is_embedder_initiated_fenced_frame_navigation = false, bool is_unfenced_top_navigation = false, - bool force_new_browsing_instance = false); + bool force_new_browsing_instance = false, + bool is_container_initiated = false); // Called after BeforeUnloadCompleted callback is invoked from the renderer. // If |frame_tree_node| has a NavigationRequest waiting for the renderer
diff --git a/content/browser/renderer_host/page_impl.cc b/content/browser/renderer_host/page_impl.cc index 03180d3..a4b876f 100644 --- a/content/browser/renderer_host/page_impl.cc +++ b/content/browser/renderer_host/page_impl.cc
@@ -171,7 +171,8 @@ } void PageImpl::ActivateForPrerendering( - StoredPage::RenderViewHostImplSafeRefSet& render_view_hosts) { + StoredPage::RenderViewHostImplSafeRefSet& render_view_hosts, + absl::optional<blink::ViewTransitionState> view_transition_state) { base::OnceClosure did_activate_render_views = base::BindOnce(&PageImpl::DidActivateAllRenderViewsForPrerendering, weak_factory_.GetWeakPtr()); @@ -179,7 +180,8 @@ base::RepeatingClosure barrier = base::BarrierClosure( render_view_hosts.size(), std::move(did_activate_render_views)); for (const auto& rvh : render_view_hosts) { - base::TimeTicks navigation_start_to_send; + auto params = blink::mojom::PrerenderPageActivationParams::New(); + // Only send navigation_start to the RenderViewHost for the main frame to // avoid sending the info cross-origin. Only this RenderViewHost needs the // info, as we expect the other RenderViewHosts are made for cross-origin @@ -188,16 +190,16 @@ // not yet committed. These RenderViews still need to know about activation // so their documents are created in the non-prerendered state once their // navigation is committed. - if (main_document_->GetRenderViewHost() == &*rvh) - navigation_start_to_send = *activation_start_time_for_prerendering_; + if (main_document_->GetRenderViewHost() == &*rvh) { + params->activation_start = *activation_start_time_for_prerendering_; + params->view_transition_state = std::move(view_transition_state); + } - auto params = blink::mojom::PrerenderPageActivationParams::New(); params->was_user_activated = main_document_->frame_tree_node() ->has_received_user_gesture_before_nav() ? blink::mojom::WasActivatedOption::kYes : blink::mojom::WasActivatedOption::kNo; - params->activation_start = navigation_start_to_send; rvh->ActivatePrerenderedPage(std::move(params), barrier); }
diff --git a/content/browser/renderer_host/page_impl.h b/content/browser/renderer_host/page_impl.h index dd06963..c74269d 100644 --- a/content/browser/renderer_host/page_impl.h +++ b/content/browser/renderer_host/page_impl.h
@@ -141,7 +141,8 @@ // documents from prerendered to activated. Tells the corresponding // RenderFrameHostImpls that the renderer will be activating their documents. void ActivateForPrerendering( - StoredPage::RenderViewHostImplSafeRefSet& render_view_hosts_to_activate); + StoredPage::RenderViewHostImplSafeRefSet& render_view_hosts_to_activate, + absl::optional<blink::ViewTransitionState> view_transition_state); // Prerender2: // Dispatches load events that were deferred to be dispatched after
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc index 7108cb11..1be900f 100644 --- a/content/browser/renderer_host/render_frame_host_impl.cc +++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -4057,9 +4057,20 @@ return frame_tree_node_->GetFencedFrameNonce(); } +bool RenderFrameHostImpl::IsMainFrameThirdPartyStoragePartitioningEnabled() { + RuntimeFeatureStateDocumentData* rfs_document_data_for_storage_key = + RuntimeFeatureStateDocumentData::GetForCurrentDocument(GetMainFrame()); + + DCHECK(rfs_document_data_for_storage_key); + + return rfs_document_data_for_storage_key->runtime_feature_read_context() + .IsThirdPartyStoragePartitioningEnabled(); +} + blink::StorageKey RenderFrameHostImpl::CalculateStorageKey( const url::Origin& new_rfh_origin, - const base::UnguessableToken* nonce) { + const base::UnguessableToken* nonce, + bool is_third_party_storage_partitioning_allowed) { if (nonce) { // If the nonce isn't null, we can use the simpler form of the constructor. return blink::StorageKey::CreateWithNonce(new_rfh_origin, *nonce); @@ -4120,7 +4131,8 @@ } return blink::StorageKey::Create(new_rfh_origin, top_level_site, - ancestor_chain_bit); + ancestor_chain_bit, + is_third_party_storage_partitioning_allowed); } void RenderFrameHostImpl::SetOriginDependentStateOfNewFrame( @@ -4150,11 +4162,11 @@ if (creator_frame) { // If we're given a parent/opener frame, copy the // RuntimeFeatureStateReadContext. - RuntimeFeatureStateDocumentData* document_data = + RuntimeFeatureStateDocumentData* rfs_document_data_from_creator = RuntimeFeatureStateDocumentData::GetForCurrentDocument(creator_frame); - DCHECK(document_data); + DCHECK(rfs_document_data_from_creator); RuntimeFeatureStateDocumentData::CreateForCurrentDocument( - this, document_data->runtime_feature_read_context()); + this, rfs_document_data_from_creator->runtime_feature_read_context()); } else { // Otherwise create a RuntimeFeatureStateContext. We need to construct a // RuntimeFeatureStateContext because its constructor initializes default @@ -4163,8 +4175,11 @@ this, blink::RuntimeFeatureStateContext()); } + // For the StorageKey, we want the main frame's + // RuntimeFeatureStateReadContext. SetStorageKey(CalculateStorageKey( - new_frame_origin, base::OptionalToPtr(isolation_info_.nonce()))); + new_frame_origin, base::OptionalToPtr(isolation_info_.nonce()), + IsMainFrameThirdPartyStoragePartitioningEnabled())); // Apply private network request policy according to our new origin. if (GetContentClient()->browser()->ShouldAllowInsecurePrivateNetworkRequests( @@ -8256,6 +8271,17 @@ return; } + // Container-initiated navigations must come from the same process as the + // parent. + if (begin_params->is_container_initiated) { + if (!GetParent() || + (initiator_process_id != GetParent()->GetProcess()->GetID())) { + mojo::ReportBadMessage( + "container initiated navigation from non-parent process"); + return; + } + } + // If the request is bearing Private State Tokens parameters: // - it must not be a main-frame navigation, and // - for certain Private State Tokens operations, the frame's parent needs the @@ -9746,6 +9772,48 @@ navigation_request->DidEncounterError()); } +void RenderFrameHostImpl::AddResourceTimingEntryForFailedSubframeNavigation( + FrameTreeNode* child_frame, + base::TimeTicks start_time, + base::TimeTicks redirect_time, + const GURL& initial_url, + const GURL& final_url, + network::mojom::URLResponseHeadPtr response_head, + bool allow_response_details, + const network::URLLoaderCompletionStatus& completion_status) { + uint32_t status_code = 0; + std::string mime_type; + std::string normalized_server_timing; + + response_head->headers->GetNormalizedHeader("Server-Timing", + &normalized_server_timing); + + if (allow_response_details) { + status_code = response_head->headers->response_code(); + mime_type = response_head->mime_type; + } + + // To avoid cross-origin leaks, make sure to only to pass here data that + // is OK when TAO-gated (as in, timing information only). + + absl::optional<blink::FrameToken> child_token_in_parent = + child_frame->GetRenderFrameHostManager() + .GetFrameTokenForSiteInstanceGroup(GetSiteInstance()->group()); + + if (!child_token_in_parent) { + return; + } + + GetAssociatedLocalFrame()->AddResourceTimingEntryForFailedSubframeNavigation( + child_token_in_parent.value(), initial_url, start_time, redirect_time, + response_head->request_start, response_head->response_start, status_code, + mime_type, response_head->load_timing, response_head->connection_info, + response_head->alpn_negotiated_protocol, + base::Contains(url::GetSecureSchemes(), + url::Origin::Create(final_url).scheme()), + response_head->is_validated, normalized_server_timing, completion_status); +} + void RenderFrameHostImpl::HandleRendererDebugURL(const GURL& url) { DCHECK(blink::IsRendererDebugURL(url)); @@ -12400,7 +12468,8 @@ url::Origin origin = GetLastCommittedOrigin(); blink::StorageKey storage_key_to_commit = CalculateStorageKey( - origin, base::OptionalToPtr(provisional_storage_key.nonce())); + origin, base::OptionalToPtr(provisional_storage_key.nonce()), + IsMainFrameThirdPartyStoragePartitioningEnabled()); SetStorageKey(storage_key_to_commit); coep_reporter_ = navigation_request->TakeCoepReporter();
diff --git a/content/browser/renderer_host/render_frame_host_impl.h b/content/browser/renderer_host/render_frame_host_impl.h index 36d5326..d31f4b5 100644 --- a/content/browser/renderer_host/render_frame_host_impl.h +++ b/content/browser/renderer_host/render_frame_host_impl.h
@@ -185,6 +185,7 @@ namespace blink { class AssociatedInterfaceRegistry; class DocumentPolicy; +class RuntimeFeatureStateReadContext; struct FramePolicy; struct TransferableMessage; struct UntrustworthyContextMenuParams; @@ -1435,6 +1436,16 @@ const absl::optional<std::string>& error_page_content, const blink::DocumentToken& document_token); + void AddResourceTimingEntryForFailedSubframeNavigation( + FrameTreeNode* child_frame, + base::TimeTicks start_time, + base::TimeTicks redirect_time, + const GURL& initial_url, + const GURL& final_url, + network::mojom::URLResponseHeadPtr response_head, + bool allow_response_details, + const network::URLLoaderCompletionStatus& completion_status); + // Sends a renderer-debug URL to the renderer process for handling. void HandleRendererDebugURL(const GURL& url); @@ -2654,12 +2665,19 @@ // opaque origin instead). void SetOriginDependentStateOfNewFrame(RenderFrameHostImpl* creator_frame); + // Returns the value of `this`'s main frame's + // RuntimeFeatureStateReadContext::IsThirdPartyStoragePartitioningEnabled() + bool IsMainFrameThirdPartyStoragePartitioningEnabled(); + // Calculates the storage key for this RenderFrameHostImpl using the passed - // `new_rfh_origin`, and `nonce` and calculating the storage key's - // top_level_site` and `ancestor_bit` parameters. This takes into account - // possible host permissions of the top_level RenderFrameHostImpl. - blink::StorageKey CalculateStorageKey(const url::Origin& new_rfh_origin, - const base::UnguessableToken* nonce); + // `new_rfh_origin`, and `nonce`, and + // `is_third_party_storage_partitioning_allowed` and deriving the storage + // key's top_level_site` and `ancestor_bit` parameters. This takes into + // account possible host permissions of the top_level RenderFrameHostImpl. + blink::StorageKey CalculateStorageKey( + const url::Origin& new_rfh_origin, + const base::UnguessableToken* nonce, + bool is_third_party_storage_partitioning_allowed); // Returns the BrowsingContextState associated with this RenderFrameHostImpl. // See class comments in BrowsingContextState for a more detailed description.
diff --git a/content/browser/renderer_host/render_frame_host_impl_unittest.cc b/content/browser/renderer_host/render_frame_host_impl_unittest.cc index 3f2fcca..9c8a9563 100644 --- a/content/browser/renderer_host/render_frame_host_impl_unittest.cc +++ b/content/browser/renderer_host/render_frame_host_impl_unittest.cc
@@ -28,6 +28,8 @@ #include "services/network/public/mojom/cors_origin_pattern.mojom.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/runtime_feature_state/runtime_feature_state_context.h" +#include "third_party/blink/public/common/runtime_feature_state/runtime_feature_state_read_context.h" #include "third_party/blink/public/common/storage_key/storage_key.h" #include "third_party/blink/public/mojom/favicon/favicon_url.mojom.h" #include "third_party/blink/public/mojom/webauthn/authenticator.mojom.h" @@ -539,6 +541,9 @@ } TEST_F(RenderFrameHostImplTest, CalculateStorageKey) { + bool partitioning_allowed = + blink::StorageKey::IsThirdPartyStoragePartitioningEnabled(); + // Register extension scheme for testing. url::ScopedSchemeRegistryForTests scoped_registry; url::AddStandardScheme("chrome-extension", url::SCHEME_WITH_HOST); @@ -577,7 +582,8 @@ EXPECT_EQ(expected_grandchild_no_permissions_storage_key, grandchild_frame->CalculateStorageKey( - grandchild_frame->GetLastCommittedOrigin(), nullptr)); + grandchild_frame->GetLastCommittedOrigin(), nullptr, + partitioning_allowed)); // Give extension host permissions to `grandchild_frame`. Since // `grandchild_frame` is not the root non-extension frame @@ -597,7 +603,8 @@ EXPECT_EQ(expected_grandchild_no_permissions_storage_key, grandchild_frame->CalculateStorageKey( - grandchild_frame->GetLastCommittedOrigin(), nullptr)); + grandchild_frame->GetLastCommittedOrigin(), nullptr, + partitioning_allowed)); // Now give extension host permissions to `child_frame`. Since the root // extension rfh has host permissions to`child_frame` calling @@ -622,9 +629,10 @@ child_frame->GetLastCommittedOrigin(), net::SchemefulSite(child_frame->GetLastCommittedOrigin()), blink::mojom::AncestorChainBit::kSameSite); - EXPECT_EQ(expected_child_with_permissions_storage_key, - child_frame->CalculateStorageKey( - child_frame->GetLastCommittedOrigin(), nullptr)); + EXPECT_EQ( + expected_child_with_permissions_storage_key, + child_frame->CalculateStorageKey(child_frame->GetLastCommittedOrigin(), + nullptr, partitioning_allowed)); blink::StorageKey expected_grandchild_with_permissions_storage_key = blink::StorageKey::Create( @@ -633,11 +641,15 @@ blink::mojom::AncestorChainBit::kCrossSite); EXPECT_EQ(expected_grandchild_with_permissions_storage_key, grandchild_frame->CalculateStorageKey( - grandchild_frame->GetLastCommittedOrigin(), nullptr)); + grandchild_frame->GetLastCommittedOrigin(), nullptr, + partitioning_allowed)); } TEST_F(RenderFrameHostImplTest, CalculateStorageKeyWhenPassedOriginIsNotCurrentFrame) { + bool partitioning_allowed = + blink::StorageKey::IsThirdPartyStoragePartitioningEnabled(); + // Register extension scheme for testing. url::ScopedSchemeRegistryForTests scoped_registry; url::AddStandardScheme("chrome-extension", url::SCHEME_WITH_HOST); @@ -677,9 +689,10 @@ child_frame->GetLastCommittedOrigin(), net::SchemefulSite(child_frame->GetLastCommittedOrigin()), blink::mojom::AncestorChainBit::kSameSite); - EXPECT_EQ(expected_child_with_permissions_storage_key, - child_frame->CalculateStorageKey( - child_frame->GetLastCommittedOrigin(), nullptr)); + EXPECT_EQ( + expected_child_with_permissions_storage_key, + child_frame->CalculateStorageKey(child_frame->GetLastCommittedOrigin(), + nullptr, partitioning_allowed)); // CalculateStorageKey is called with an origin that the top level document // does not have host permissions to. A cross-site storage key is expected and @@ -693,7 +706,266 @@ blink::mojom::AncestorChainBit::kCrossSite); EXPECT_EQ(expected_storage_key_no_permissions, child_frame->CalculateStorageKey( - url::Origin::Create(no_host_permissions_url), nullptr)); + url::Origin::Create(no_host_permissions_url), nullptr, + partitioning_allowed)); +} + +// Test that the correct StorageKey is calculated when a RFH takes its document +// properties from a navigation. +// TODO(https://crbug.com/888079): Once we are able to compute the origin to +// commit in the browser, `navigation_request->commit_params().storage_key` +// will contain the correct origin and it won't be necessary to override it +// with `param.origin` anymore. Meaning this test may be removed because we +// already check that the NavigationRequest calculates the correct key. +TEST_F(RenderFrameHostImplTest, + CalculateStorageKeyTakeNewDocumentPropertiesFromNavigation) { + base::test::ScopedFeatureList scoped_feature_list; + // Because the StorageKey's (and Storage Partitioning's) usage of + // RuntimeFeatureState is only meant to disable partitioning (i.e.: + // first-party only), we need the make sure the net::features is always + // enabled. + scoped_feature_list.InitAndEnableFeature( + net::features::kThirdPartyStoragePartitioning); + + // This lamdba performs the navigation and disables Storage Partitioning for + // the navigation if `disable_sp` is true. It returns the new + // TestRenderFrameHost* to the navigated frame. + auto NavigateFrame = [](NavigationSimulator* navigation, + bool disable_sp = false) -> TestRenderFrameHost* { + navigation->Start(); + + if (disable_sp) { + NavigationRequest* request = + NavigationRequest::From(navigation->GetNavigationHandle()); + request->GetMutableRuntimeFeatureStateContext() + .SetThirdPartyStoragePartitioningEnabled(false); + } + + navigation->Commit(); + return static_cast<TestRenderFrameHost*>( + navigation->GetFinalRenderFrameHost()); + }; + + // Throughout the test we'll be creating a frame tree with a main frame, a + // child frame, and a grandchild frame. + GURL main_url("https://main.com"); + GURL b_url("https://b.com"); + GURL c_url("https://c.com"); + + url::Origin main_origin = url::Origin::Create(main_url); + url::Origin b_origin = url::Origin::Create(b_url); + url::Origin c_origin = url::Origin::Create(c_url); + + // Begin by testing with Storage Partitioning enabled. + + auto main_navigation = + NavigationSimulatorImpl::CreateBrowserInitiated(main_url, contents()); + + // By definition the main frame's StorageKey will always be first party + blink::StorageKey main_frame_key = + blink::StorageKey::CreateFirstParty(main_origin); + + NavigateFrame(main_navigation.get()); + + EXPECT_EQ(main_frame_key, main_test_rfh()->storage_key()); + + TestRenderFrameHost* child_frame = static_cast<TestRenderFrameHost*>( + RenderFrameHostTester::For(main_rfh())->AppendChild("child")); + + auto child_navigation = + NavigationSimulatorImpl::CreateRendererInitiated(b_url, child_frame); + + // The child and grandchild should both be third-party keys. + blink::StorageKey child_frame_key = + blink::StorageKey::Create(b_origin, net::SchemefulSite(main_origin), + blink::mojom::AncestorChainBit::kCrossSite); + + child_frame = NavigateFrame(child_navigation.get()); + + EXPECT_EQ(child_frame_key, child_frame->storage_key()); + + TestRenderFrameHost* grandchild_frame = + child_frame->AppendChild("grandchild"); + + auto grandchild_navigation = + NavigationSimulatorImpl::CreateRendererInitiated(c_url, grandchild_frame); + + blink::StorageKey grandchild_frame_key = + blink::StorageKey::Create(c_origin, net::SchemefulSite(main_origin), + blink::mojom::AncestorChainBit::kCrossSite); + grandchild_frame = NavigateFrame(grandchild_navigation.get()); + + EXPECT_EQ(grandchild_frame_key, grandchild_frame->storage_key()); + + // Only the RuntimeFeatureStateContext in the main frame's matters. So + // disabling Storage Partitioning in the child_frame shouldn't affect the + // child's or the grandchild's StorageKey. + child_navigation = + NavigationSimulatorImpl::CreateRendererInitiated(b_url, child_frame); + + child_frame = NavigateFrame(child_navigation.get(), + /*disable_sp=*/true); + EXPECT_EQ(child_frame_key, child_frame->storage_key()); + + grandchild_frame = child_frame->AppendChild("grandchild"); + + grandchild_navigation = + NavigationSimulatorImpl::CreateRendererInitiated(c_url, grandchild_frame); + + grandchild_frame = NavigateFrame(grandchild_navigation.get()); + + EXPECT_EQ(grandchild_frame_key, grandchild_frame->storage_key()); + + // Disabling Storage Partitioning on the main frame should cause the child's + // and grandchild's StorageKey to be first-party. + main_navigation = + NavigationSimulatorImpl::CreateBrowserInitiated(main_url, contents()); + + NavigateFrame(main_navigation.get(), + /*disable_sp=*/true); + + child_frame = static_cast<TestRenderFrameHost*>( + RenderFrameHostTester::For(main_rfh())->AppendChild("child")); + + child_navigation = + NavigationSimulatorImpl::CreateRendererInitiated(b_url, child_frame); + + // The child and grandchild should both be first-party keys. + blink::StorageKey child_frame_key_1p = + blink::StorageKey::CreateFirstParty(b_origin); + + child_frame = NavigateFrame(child_navigation.get()); + + EXPECT_EQ(child_frame_key_1p, child_frame->storage_key()); + + grandchild_frame = child_frame->AppendChild("grandchild"); + + blink::StorageKey grandchild_frame_key_1p = + blink::StorageKey::CreateFirstParty(c_origin); + + grandchild_navigation = + NavigationSimulatorImpl::CreateRendererInitiated(c_url, grandchild_frame); + + grandchild_frame = NavigateFrame(grandchild_navigation.get()); + + EXPECT_EQ(grandchild_frame_key_1p, grandchild_frame->storage_key()); +} + +// Test that CalculateStorageKey creates a first-party or third-party key +// depending on state of Storage Partitioning the main frame's +// RuntimeFeatureStateReadContext for a new unnavigated frame. +TEST_F(RenderFrameHostImplTest, CalculateStorageKeyOfUnnavigatedFrame) { + base::test::ScopedFeatureList scoped_feature_list; + // Because Storage partitioning's usage of RuntimeFeatureState is only meant + // to disable (i.e.: 1p only) partitioning, we need the make sure the feature + // is on first. + scoped_feature_list.InitAndEnableFeature( + net::features::kThirdPartyStoragePartitioning); + + // This test will create a main frame that has Storage Partitioning disabled + // via its RuntimeFeatureStateReadContext. It will have a navigated child + // frame's whose RFSRC will be the default (i.e.: Storage Partitioning + // enabled) and that child will then spawn an unnavigated grandchild whose + // StorageKey should still depend upon the main frame's RFSRC. + + GURL url = GURL("https://a.com"); + GURL child_url = GURL("https://b.com"); + + // Start by giving the main frame a SP disabled + // RuntimeFeatureStateReadContext. + auto navigation = + NavigationSimulator::CreateRendererInitiated(url, main_rfh()); + navigation->Start(); + + NavigationRequest* request = + NavigationRequest::From(navigation->GetNavigationHandle()); + + request->GetMutableRuntimeFeatureStateContext() + .SetThirdPartyStoragePartitioningEnabled(false); + + navigation->Commit(); + + EXPECT_FALSE( + RuntimeFeatureStateDocumentData::GetForCurrentDocument(main_rfh()) + ->runtime_feature_read_context() + .IsThirdPartyStoragePartitioningEnabled()); + + // Create a child frame and navigate to `child_url`. + auto* child_frame = main_test_rfh()->AppendChild("child"); + auto child_navigation = + NavigationSimulator::CreateRendererInitiated(child_url, child_frame); + child_navigation->Commit(); + child_frame = static_cast<TestRenderFrameHost*>( + child_navigation->GetFinalRenderFrameHost()); + + // Create a grand child and check it's StorageKey. + auto* grandchild_frame = child_frame->AppendChild("grandchild"); + + // Since Storage Partitioning is disabled, the key should be first party. + blink::StorageKey grandchild_frame_key_1p = + blink::StorageKey::CreateFirstParty(url::Origin::Create(child_url)); + EXPECT_EQ(grandchild_frame_key_1p, grandchild_frame->storage_key()); + + // Now perform the same test, except the main frame also gets a default + // RuntimeFeatureStateReadContext. (I.e.: Storage Partitioning enabled). + NavigationSimulator::NavigateAndCommitFromDocument(url, main_rfh()); + + child_frame = main_test_rfh()->AppendChild("child"); + child_navigation = + NavigationSimulator::CreateRendererInitiated(child_url, child_frame); + child_navigation->Commit(); + child_frame = static_cast<TestRenderFrameHost*>( + child_navigation->GetFinalRenderFrameHost()); + + grandchild_frame = child_frame->AppendChild("grandchild"); + + blink::StorageKey grandchild_frame_key = + blink::StorageKey::Create(url::Origin::Create(child_url), + net::SchemefulSite(url::Origin::Create(url)), + blink::mojom::AncestorChainBit::kCrossSite); + EXPECT_EQ(grandchild_frame_key, grandchild_frame->storage_key()); +} + +TEST_F(RenderFrameHostImplTest, + NewFrameInheritsRuntimeFeatureStateReadContext) { + GURL url = GURL("https://a.com"); + GURL child_url = GURL("https://b.com"); + + // Start by giving the main frame a non-default + // RuntimeFeatureStateReadContext. + + auto navigation = + NavigationSimulator::CreateRendererInitiated(url, main_rfh()); + navigation->Start(); + + NavigationRequest* request = + NavigationRequest::From(navigation->GetNavigationHandle()); + + request->GetMutableRuntimeFeatureStateContext().SetTestFeatureEnabled(true); + + navigation->Commit(); + + EXPECT_TRUE(RuntimeFeatureStateDocumentData::GetForCurrentDocument(main_rfh()) + ->runtime_feature_read_context() + .IsTestFeatureEnabled()); + + // Now add a child and check its RFSRC. + auto* child_frame = main_test_rfh()->AppendChild("child"); + EXPECT_TRUE( + RuntimeFeatureStateDocumentData::GetForCurrentDocument(child_frame) + ->runtime_feature_read_context() + .IsTestFeatureEnabled()); + + // Navigating the child away should change the RFSRC. + auto child_navigation = + NavigationSimulator::CreateRendererInitiated(child_url, child_frame); + child_navigation->Commit(); + child_frame = static_cast<TestRenderFrameHost*>( + child_navigation->GetFinalRenderFrameHost()); + EXPECT_FALSE( + RuntimeFeatureStateDocumentData::GetForCurrentDocument(child_frame) + ->runtime_feature_read_context() + .IsTestFeatureEnabled()); } #if BUILDFLAG(IS_ANDROID)
diff --git a/content/browser/renderer_host/render_frame_host_manager.cc b/content/browser/renderer_host/render_frame_host_manager.cc index ddc0a834..465a009 100644 --- a/content/browser/renderer_host/render_frame_host_manager.cc +++ b/content/browser/renderer_host/render_frame_host_manager.cc
@@ -3906,10 +3906,10 @@ for (const auto& rvh : render_view_hosts_to_restore) { blink::mojom::PageRestoreParamsPtr page_restore_params = pending_stored_page->page_restore_params().Clone(); - // We only send view_transition_state to the main RenderViewHost, so - // clear it for any other RenderViewHosts. - if (&*rvh != current_frame_host()->GetRenderViewHost()) { - page_restore_params->view_transition_state.reset(); + // We only send view_transition_state to the main RenderViewHost. + if (&*rvh == current_frame_host()->GetRenderViewHost()) { + page_restore_params->view_transition_state = + pending_stored_page->TakeViewTransitionState(); } rvh->LeaveBackForwardCache(std::move(page_restore_params)); } @@ -3917,7 +3917,8 @@ DCHECK_EQ(prev_state, RenderFrameHostImpl::LifecycleStateImpl::kPrerendering); current_frame_host()->GetPage().ActivateForPrerendering( - render_view_hosts_to_restore); + render_view_hosts_to_restore, + pending_stored_page->TakeViewTransitionState()); } }
diff --git a/content/browser/renderer_host/render_frame_proxy_host.cc b/content/browser/renderer_host/render_frame_proxy_host.cc index b9ddf05..824e7cc 100644 --- a/content/browser/renderer_host/render_frame_proxy_host.cc +++ b/content/browser/renderer_host/render_frame_proxy_host.cc
@@ -703,7 +703,10 @@ params->extra_headers, std::move(blob_url_loader_factory), std::move(params->source_location), params->user_gesture, params->is_form_submission, params->impression, - params->initiator_activation_and_ad_status, navigation_start_time); + params->initiator_activation_and_ad_status, navigation_start_time, + /*is_embedder_initiated_fenced_frame_navigation=*/false, + /*is_unfenced_top_navigation=*/false, + /*force_new_browsing_instance=*/false, params->is_container_initiated); } void RenderFrameProxyHost::UpdateViewportIntersection(
diff --git a/content/browser/renderer_host/stored_page.cc b/content/browser/renderer_host/stored_page.cc index 8a4b95e..af94bed2 100644 --- a/content/browser/renderer_host/stored_page.cc +++ b/content/browser/renderer_host/stored_page.cc
@@ -99,4 +99,15 @@ return std::move(render_view_hosts_); } +void StoredPage::SetViewTransitionState( + absl::optional<blink::ViewTransitionState> view_transition_state) { + DCHECK(!view_transition_state_); + view_transition_state_ = std::move(view_transition_state); +} + +absl::optional<blink::ViewTransitionState> +StoredPage::TakeViewTransitionState() { + return std::exchange(view_transition_state_, {}); +} + } // namespace content
diff --git a/content/browser/renderer_host/stored_page.h b/content/browser/renderer_host/stored_page.h index a1a8bba..1a704286 100644 --- a/content/browser/renderer_host/stored_page.h +++ b/content/browser/renderer_host/stored_page.h
@@ -93,6 +93,10 @@ RenderFrameProxyHostMap TakeProxyHosts(); RenderViewHostImplSafeRefSet TakeRenderViewHosts(); + void SetViewTransitionState( + absl::optional<blink::ViewTransitionState> view_transition_state); + absl::optional<blink::ViewTransitionState> TakeViewTransitionState(); + private: void ClearAllObservers(); @@ -124,6 +128,10 @@ blink::mojom::PageRestoreParamsPtr page_restore_params_; raw_ptr<Delegate> delegate_ = nullptr; + + // View transition state to use when the page is activated, either via BFCache + // activation or prerender activation. + absl::optional<blink::ViewTransitionState> view_transition_state_; }; } // namespace content
diff --git a/content/browser/security_exploit_browsertest.cc b/content/browser/security_exploit_browsertest.cc index e8d9a9c4..15e819d1 100644 --- a/content/browser/security_exploit_browsertest.cc +++ b/content/browser/security_exploit_browsertest.cc
@@ -1538,7 +1538,8 @@ base::TimeTicks() /* renderer_before_unload_end */, absl::nullopt /* web_bundle_token */, blink::mojom::NavigationInitiatorActivationAndAdStatus:: - kDidNotStartWithTransientActivation); + kDidNotStartWithTransientActivation, + false /* is_container_initiated */); // Receiving the invalid IPC message should lead to renderer process // termination.
diff --git a/content/browser/service_worker/fake_service_worker.cc b/content/browser/service_worker/fake_service_worker.cc index 4f93752..dbc079f 100644 --- a/content/browser/service_worker/fake_service_worker.cc +++ b/content/browser/service_worker/fake_service_worker.cc
@@ -237,11 +237,11 @@ } void FakeServiceWorker::AddKeepAlive() { - NOTIMPLEMENTED(); + idle_delay_.reset(); } void FakeServiceWorker::ClearKeepAlive() { - NOTIMPLEMENTED(); + idle_delay_ = base::Seconds(30); } void FakeServiceWorker::AddMessageToConsole(
diff --git a/content/browser/service_worker/service_worker_main_resource_loader_interceptor.cc b/content/browser/service_worker/service_worker_main_resource_loader_interceptor.cc index 58dce62..f70c1b4 100644 --- a/content/browser/service_worker/service_worker_main_resource_loader_interceptor.cc +++ b/content/browser/service_worker/service_worker_main_resource_loader_interceptor.cc
@@ -12,6 +12,7 @@ #include "base/types/optional_util.h" #include "build/chromeos_buildflags.h" #include "content/browser/renderer_host/frame_tree_node.h" +#include "content/browser/renderer_host/navigation_request.h" #include "content/browser/renderer_host/navigation_request_info.h" #include "content/browser/service_worker/service_worker_container_host.h" #include "content/browser/service_worker/service_worker_context_core.h" @@ -230,6 +231,11 @@ storage_key = GetStorageKeyFromWorkerHost(new_origin); } if (!storage_key.has_value()) { + // If we're in this case then we couldn't get the StorageKey from the RFH, + // which means we also can't get the storage partitioning status from + // RuntimeFeatureState(Read)Context. Using + // CreateFromOriginAndIsolationInfo() will create a key based on + // net::features::kThirdPartyStoragePartitioning state. storage_key = blink::StorageKey::CreateFromOriginAndIsolationInfo( new_origin, isolation_info_); } @@ -362,7 +368,20 @@ RenderFrameHostImpl* frame_host = frame_tree_node->current_frame_host(); if (!frame_host) return absl::nullopt; - return frame_host->CalculateStorageKey(origin, nonce); + + // Determine if we should allow partitioned StorageKeys. + // + // If this is a main frame navigation then the value of + // third_party_storage_partitioning_enabled is irrelevant because main frames + // are always first-party by definition. If this is a subframe navigation + // then the main frame will have the correct value. + bool third_party_storage_partitioning_enabled = false; + if (!frame_host->is_main_frame()) { + third_party_storage_partitioning_enabled = + frame_host->IsMainFrameThirdPartyStoragePartitioningEnabled(); + } + return frame_host->CalculateStorageKey( + origin, nonce, third_party_storage_partitioning_enabled); } absl::optional<blink::StorageKey>
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc index 54ad5cd..2e88866 100644 --- a/content/browser/service_worker/service_worker_version.cc +++ b/content/browser/service_worker/service_worker_version.cc
@@ -2231,8 +2231,9 @@ return; } - // Requests have not finished before their expiration. - bool stop_for_timeout = false; + // Are there requests that have not finished before their expiration. + bool has_kill_on_timeout = false; + bool has_continue_on_timeout = false; // In case, `request_timeouts_` can be modified in the callbacks initiated // in `MaybeTimeoutRequest`, we keep its contents locally during the // following while loop. @@ -2245,8 +2246,14 @@ break; } if (MaybeTimeoutRequest(info)) { - stop_for_timeout = - stop_for_timeout || info.timeout_behavior == KILL_ON_TIMEOUT; + switch (info.timeout_behavior) { + case KILL_ON_TIMEOUT: + has_kill_on_timeout = true; + break; + case CONTINUE_ON_TIMEOUT: + has_continue_on_timeout = true; + break; + } } timeout_iter = request_timeouts.erase(timeout_iter); } @@ -2256,14 +2263,24 @@ // TODO(crbug.com/1363504): remove the following DCHECK when the cause // identified. DCHECK_EQ(request_timeouts_.size(), inflight_requests_.size()); - if (stop_for_timeout && running_status() != EmbeddedWorkerStatus::STOPPING) + + if (has_kill_on_timeout && + running_status() != EmbeddedWorkerStatus::STOPPING) { embedded_worker_->Stop(); + } // For the timeouts below, there are no callbacks to timeout so there is // nothing more to do if the worker is already stopping. if (running_status() == EmbeddedWorkerStatus::STOPPING) return; + // If an request is expired and there is no other requests, we ask event + // queue to check if idle timeout should be scheduled. Event queue may + // schedule idle timeout if there is no events at the time. + if (has_continue_on_timeout && !HasWorkInBrowser()) { + endpoint()->ClearKeepAlive(); + } + // Check ping status. ping_controller_.CheckPingStatus(); }
diff --git a/content/browser/service_worker/service_worker_version_unittest.cc b/content/browser/service_worker/service_worker_version_unittest.cc index ada9251b..15dbdac 100644 --- a/content/browser/service_worker/service_worker_version_unittest.cc +++ b/content/browser/service_worker/service_worker_version_unittest.cc
@@ -959,6 +959,8 @@ TEST_F(ServiceWorkerVersionTest, RequestNowTimeout) { absl::optional<blink::ServiceWorkerStatusCode> status; base::RunLoop run_loop; + auto* service_worker = + helper_->AddNewPendingServiceWorker<FakeServiceWorker>(helper_.get()); version_->SetStatus(ServiceWorkerVersion::ACTIVATED); ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk, StartServiceWorker(version_.get())); @@ -975,6 +977,11 @@ run_loop.Run(); EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorTimeout, status.value()); + service_worker->FlushForTesting(); + // Should try to set idle timeout if the last request has expired and is + // CONTINUE_ON_TIMEOUT. + EXPECT_TRUE(service_worker->idle_delay().has_value()); + EXPECT_FALSE(version_->FinishRequest(request_id, /*was_handled=*/true)); // CONTINUE_ON_TIMEOUT timeouts don't stop the service worker.
diff --git a/content/browser/shared_storage/shared_storage_browsertest.cc b/content/browser/shared_storage/shared_storage_browsertest.cc index db96c1f..0127fec 100644 --- a/content/browser/shared_storage/shared_storage_browsertest.cc +++ b/content/browser/shared_storage/shared_storage_browsertest.cc
@@ -2962,7 +2962,6 @@ }, }, target)); - ; } private:
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc index 3769320..f9ae18dd 100644 --- a/content/browser/storage_partition_impl.cc +++ b/content/browser/storage_partition_impl.cc
@@ -3151,7 +3151,21 @@ RenderFrameHostImpl* frame_host = node->current_frame_host(); if (!frame_host) return absl::nullopt; - return frame_host->CalculateStorageKey(origin, nonce); + + // Determine if we should allow partitioned StorageKeys. + // + // If this is a main frame navigation then the value of + // third_party_storage_partitioning_enabled is irrelevant because main frames + // are always first-party by definition. If this is a subframe navigation + // then the main frame will have the correct value. + bool third_party_storage_partitioning_enabled = false; + if (!frame_host->is_main_frame()) { + third_party_storage_partitioning_enabled = + frame_host->IsMainFrameThirdPartyStoragePartitioningEnabled(); + } + + return frame_host->CalculateStorageKey( + origin, nonce, third_party_storage_partitioning_enabled); } StoragePartitionImpl::URLLoaderNetworkContext::URLLoaderNetworkContext(
diff --git a/content/browser/tracing/tracing_controller_browsertest.cc b/content/browser/tracing/tracing_controller_browsertest.cc index fb0535a..20dc2c6 100644 --- a/content/browser/tracing/tracing_controller_browsertest.cc +++ b/content/browser/tracing/tracing_controller_browsertest.cc
@@ -48,24 +48,22 @@ namespace { -bool KeyEquals(const base::Value* value, +bool KeyEquals(const base::Value::Dict& dict, const char* key_name, const char* expected) { - const base::Value* content = - value->FindKeyOfType(key_name, base::Value::Type::STRING); + const std::string* content = dict.FindString(key_name); if (!content) return false; - return content->GetString() == expected; + return *content == expected; } -bool KeyNotEquals(const base::Value* value, +bool KeyNotEquals(const base::Value::Dict& dict, const char* key_name, const char* expected) { - const base::Value* content = - value->FindKeyOfType(key_name, base::Value::Type::STRING); + const std::string* content = dict.FindString(key_name); if (!content) return false; - return content->GetString() != expected; + return *content != expected; } } // namespace @@ -431,20 +429,20 @@ // Check that a number of important keys exist in the metadata dictionary. absl::optional<base::Value> trace_json = base::JSONReader::Read(last_data()); ASSERT_TRUE(trace_json); - const base::Value* metadata_json = - trace_json->FindKeyOfType("metadata", base::Value::Type::DICT); + const base::Value::Dict* metadata_json = + trace_json->GetDict().FindDict("metadata"); ASSERT_TRUE(metadata_json); - EXPECT_TRUE(KeyNotEquals(metadata_json, "cpu-brand", "__stripped__")); - EXPECT_TRUE(KeyNotEquals(metadata_json, "network-type", "__stripped__")); - EXPECT_TRUE(KeyNotEquals(metadata_json, "os-name", "__stripped__")); - EXPECT_TRUE(KeyNotEquals(metadata_json, "user-agent", "__stripped__")); + EXPECT_TRUE(KeyNotEquals(*metadata_json, "cpu-brand", "__stripped__")); + EXPECT_TRUE(KeyNotEquals(*metadata_json, "network-type", "__stripped__")); + EXPECT_TRUE(KeyNotEquals(*metadata_json, "os-name", "__stripped__")); + EXPECT_TRUE(KeyNotEquals(*metadata_json, "user-agent", "__stripped__")); #if BUILDFLAG(IS_CHROMEOS_ASH) - EXPECT_TRUE(KeyNotEquals(metadata_json, "hardware-class", "__stripped__")); + EXPECT_TRUE(KeyNotEquals(*metadata_json, "hardware-class", "__stripped__")); #endif // The following field is not whitelisted and is supposed to be stripped. - EXPECT_TRUE(KeyEquals(metadata_json, "v8-version", "__stripped__")); + EXPECT_TRUE(KeyEquals(*metadata_json, "v8-version", "__stripped__")); } IN_PROC_BROWSER_TEST_F(TracingControllerTest,
diff --git a/content/browser/webauth/authenticator_common_impl.cc b/content/browser/webauth/authenticator_common_impl.cc index 2c35fb2..27a89db 100644 --- a/content/browser/webauth/authenticator_common_impl.cc +++ b/content/browser/webauth/authenticator_common_impl.cc
@@ -1350,8 +1350,8 @@ #if BUILDFLAG(IS_WIN) GetWebAuthenticationDelegate()->OperationSucceeded( - GetBrowserContext(), authenticator->GetType() == - device::FidoAuthenticator::Type::kWinNative); + GetBrowserContext(), + authenticator->GetType() == device::AuthenticatorType::kWinNative); #endif absl::optional<device::FidoTransportProtocol> transport = @@ -1580,7 +1580,7 @@ #if BUILDFLAG(IS_WIN) GetWebAuthenticationDelegate()->OperationSucceeded( GetBrowserContext(), - authenticator->GetType() == device::FidoAuthenticator::Type::kWinNative); + authenticator->GetType() == device::AuthenticatorType::kWinNative); #endif // Show an account picker for discoverable credential requests (empty allow
diff --git a/content/common/frame.mojom b/content/common/frame.mojom index d2f7102..4fbba74 100644 --- a/content/common/frame.mojom +++ b/content/common/frame.mojom
@@ -17,6 +17,7 @@ import "skia/public/mojom/skcolor.mojom"; import "services/network/public/mojom/content_security_policy.mojom"; import "services/network/public/mojom/url_loader.mojom"; +import "services/network/public/mojom/url_loader_completion_status.mojom"; import "services/network/public/mojom/url_loader_factory.mojom"; import "services/network/public/mojom/url_request.mojom"; import "services/network/public/mojom/url_response_head.mojom";
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index 668c7a0..68654d5 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -1079,7 +1079,7 @@ // https://crbug.com/1356224 . BASE_FEATURE(kSecurePaymentConfirmationRemoveRpField, "SecurePaymentConfirmationRemoveRpField", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); // Make sendBeacon throw for a Blob with a non simple type. BASE_FEATURE(kSendBeaconThrowForBlobWithNonSimpleType,
diff --git a/content/public/test/fake_local_frame.cc b/content/public/test/fake_local_frame.cc index f8191976..f648ddf 100644 --- a/content/public/test/fake_local_frame.cc +++ b/content/public/test/fake_local_frame.cc
@@ -9,7 +9,6 @@ #include "third_party/blink/public/mojom/devtools/inspector_issue.mojom.h" #include "third_party/blink/public/mojom/frame/media_player_action.mojom.h" #include "third_party/blink/public/mojom/push_messaging/push_messaging.mojom.h" -#include "third_party/blink/public/mojom/timing/resource_timing.mojom.h" #if BUILDFLAG(IS_MAC) #include "ui/base/mojom/attributed_string.mojom.h" @@ -79,15 +78,6 @@ const std::vector<blink::mojom::WebFeature>&) {} void FakeLocalFrame::RenderFallbackContent() {} - -void FakeLocalFrame::AddResourceTimingEntryFromNonNavigatedFrame( - blink::mojom::ResourceTimingInfoPtr timing, - blink::FrameOwnerElementType parent_frame_element_type) {} - -void FakeLocalFrame::RenderFallbackContentWithResourceTiming( - blink::mojom::ResourceTimingInfoPtr, - const std::string& server_timing_value) {} - void FakeLocalFrame::BeforeUnload(bool is_reload, BeforeUnloadCallback callback) { base::TimeTicks now = base::TimeTicks::Now(); @@ -204,6 +194,23 @@ void FakeLocalFrame::SnapshotDocumentForViewTransition( SnapshotDocumentForViewTransitionCallback callback) {} +void FakeLocalFrame::AddResourceTimingEntryForFailedSubframeNavigation( + const ::blink::FrameToken& subframe_token, + const GURL& initial_url, + ::base::TimeTicks start_time, + ::base::TimeTicks redirect_time, + ::base::TimeTicks request_start, + ::base::TimeTicks response_start, + uint32_t response_code, + const std::string& mime_type, + const ::net::LoadTimingInfo& load_timing_info, + ::net::HttpResponseInfo::ConnectionInfo connection_info, + const std::string& alpn_negotiated_protocol, + bool is_secure_transport, + bool is_validated, + const std::string& normalized_server_timing, + const ::network::URLLoaderCompletionStatus& completion_status) {} + void FakeLocalFrame::BindFrameHostReceiver( mojo::ScopedInterfaceEndpointHandle handle) { receiver_.Bind(mojo::PendingAssociatedReceiver<blink::mojom::LocalFrame>(
diff --git a/content/public/test/fake_local_frame.h b/content/public/test/fake_local_frame.h index e732e63..8930e12 100644 --- a/content/public/test/fake_local_frame.h +++ b/content/public/test/fake_local_frame.h
@@ -8,6 +8,8 @@ #include "build/build_config.h" #include "mojo/public/cpp/bindings/associated_receiver_set.h" #include "mojo/public/cpp/bindings/pending_associated_receiver.h" +#include "net/http/http_response_info.h" +#include "services/network/public/mojom/load_timing_info.mojom.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" #include "third_party/blink/public/common/messaging/transferable_message.h" @@ -65,12 +67,6 @@ void ReportBlinkFeatureUsage( const std::vector<blink::mojom::WebFeature>&) override; void RenderFallbackContent() override; - void AddResourceTimingEntryFromNonNavigatedFrame( - blink::mojom::ResourceTimingInfoPtr timing, - blink::FrameOwnerElementType parent_frame_element_type) override; - void RenderFallbackContentWithResourceTiming( - blink::mojom::ResourceTimingInfoPtr, - const std::string& server_timing_value) override; void BeforeUnload(bool is_reload, BeforeUnloadCallback callback) override; void MediaPlayerActionAt(const gfx::Point& location, blink::mojom::MediaPlayerActionPtr action) override; @@ -150,6 +146,22 @@ blink::mojom::TraverseCancelledReason reason) override; void SnapshotDocumentForViewTransition( SnapshotDocumentForViewTransitionCallback callback) override; + void AddResourceTimingEntryForFailedSubframeNavigation( + const ::blink::FrameToken& subframe_token, + const GURL& initial_url, + base::TimeTicks start_time, + base::TimeTicks redirect_time, + base::TimeTicks request_start, + base::TimeTicks response_start, + uint32_t response_code, + const std::string& mime_type, + const net::LoadTimingInfo& load_timing_info, + net::HttpResponseInfo::ConnectionInfo connection_info, + const std::string& alpn_negotiated_protocol, + bool is_secure_transport, + bool is_validated, + const std::string& normalized_server_timing, + const ::network::URLLoaderCompletionStatus& completion_status) override; private: void BindFrameHostReceiver(mojo::ScopedInterfaceEndpointHandle handle);
diff --git a/content/public/test/fake_remote_frame.cc b/content/public/test/fake_remote_frame.cc index 9492218..04d8a077 100644 --- a/content/public/test/fake_remote_frame.cc +++ b/content/public/test/fake_remote_frame.cc
@@ -63,10 +63,6 @@ void FakeRemoteFrame::RenderFallbackContent() {} -void FakeRemoteFrame::RenderFallbackContentWithResourceTiming( - blink::mojom::ResourceTimingInfoPtr, - const std::string& server_timing_value) {} - void FakeRemoteFrame::AddResourceTimingFromChild( blink::mojom::ResourceTimingInfoPtr timing) {}
diff --git a/content/public/test/fake_remote_frame.h b/content/public/test/fake_remote_frame.h index e8174cd2..1521517b 100644 --- a/content/public/test/fake_remote_frame.h +++ b/content/public/test/fake_remote_frame.h
@@ -64,9 +64,6 @@ const base::UnguessableToken& embedding_token) override; void SetPageFocus(bool is_focused) override; void RenderFallbackContent() override; - void RenderFallbackContentWithResourceTiming( - blink::mojom::ResourceTimingInfoPtr, - const std::string& server_timing_value) override; void AddResourceTimingFromChild( blink::mojom::ResourceTimingInfoPtr timing) override;
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index 0569890..24fced83 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -944,6 +944,8 @@ browser_navigation_timings.fetch_start; renderer_navigation_timings.input_start = input_start; + renderer_navigation_timings.parent_resource_timing_access = + browser_navigation_timings.parent_resource_timing_access; return renderer_navigation_timings; } @@ -5757,7 +5759,7 @@ : nullptr, info->impression, renderer_before_unload_start, renderer_before_unload_end, web_bundle_token_params, - initiator_activation_and_ad_status); + initiator_activation_and_ad_status, info->is_container_initiated); mojo::PendingAssociatedRemote<mojom::NavigationClient> navigation_client_remote;
diff --git a/content/services/auction_worklet/public/mojom/bidder_worklet.mojom b/content/services/auction_worklet/public/mojom/bidder_worklet.mojom index 99689183..35131f3 100644 --- a/content/services/auction_worklet/public/mojom/bidder_worklet.mojom +++ b/content/services/auction_worklet/public/mojom/bidder_worklet.mojom
@@ -292,9 +292,11 @@ interface BidderWorklet { // Loads the same-origin realtime bidding signals URL (if necessary), and // after the rest of the arguments for it have been provided via - // `bid_finalizer`, invokes the worklet's generateBid() method, returning the - // generated bid and associated data. Waits for the worklet script to be - // loaded first, if needed. + // a FinishGenerateBid() call on `bid_finalizer`, invokes the worklet's + // generateBid() method, returning the generated bid and associated data. + // Waits for the worklet script to be loaded first, if needed. + // FinishGenerateBid() *must* always be called, even if no parameters are + // provided as promises. // // Arguments: // `bidder_worklet_non_shared_params` values that can vary in the
diff --git a/content/test/content_unittests_bundle_data.filelist b/content/test/content_unittests_bundle_data.filelist index 1d651e73..6943b774 100644 --- a/content/test/content_unittests_bundle_data.filelist +++ b/content/test/content_unittests_bundle_data.filelist
@@ -65,6 +65,7 @@ //content/test/data/attribution_reporting/interop/dedup_key.json //content/test/data/attribution_reporting/interop/default_config.json //content/test/data/attribution_reporting/interop/destination_limit.json +//content/test/data/attribution_reporting/interop/event_level_report_time.json //content/test/data/attribution_reporting/interop/event_level_storage_limit.json //content/test/data/attribution_reporting/interop/event_level_trigger_filter_data.json //content/test/data/attribution_reporting/interop/event_level_trigger_priority.json
diff --git a/content/test/data/attribution_reporting/interop/event_level_report_time.json b/content/test/data/attribution_reporting/interop/event_level_report_time.json new file mode 100644 index 0000000..0fa5658 --- /dev/null +++ b/content/test/data/attribution_reporting/interop/event_level_report_time.json
@@ -0,0 +1,277 @@ +{ + "description": "Different report time windows for event-level reports", + "input": { + "sources": [ + { + "timestamp": "1643235573000", + "registration_request": { + "source_origin": "https://source.test", + "attribution_src_url": "https://reporter.test/register-source", + "source_type": "navigation" + }, + "responses": [{ + "url": "https://reporter.test/register-source", + "response": { + "Attribution-Reporting-Register-Source": { + "destination": "https://destination.test", + "source_event_id": "123", + "event_report_window": "96400" + } + } + }] + }, + { + "timestamp": "1643235574000", + "registration_request": { + "source_origin": "https://source.test", + "attribution_src_url": "https://reporter2.test/register-source", + "source_type": "navigation" + }, + "responses": [{ + "url": "https://reporter2.test/register-source", + "response": { + "Attribution-Reporting-Register-Source": { + "destination": "https://destination.test", + "source_event_id": "456", + "event_report_window": "182800" + } + } + }] + }, + { + "timestamp": "1643235575000", + "registration_request": { + "source_origin": "https://source.test", + "attribution_src_url": "https://reporter3.test/register-source", + "source_type": "navigation" + }, + "responses": [{ + "url": "https://reporter3.test/register-source", + "response": { + "Attribution-Reporting-Register-Source": { + "destination": "https://destination.test", + "source_event_id": "789", + "expiry": "864000" + } + } + }] + }, + { + "timestamp": "1643235576000", + "registration_request": { + "source_origin": "https://source.test", + "attribution_src_url": "https://reporter.test/register-source", + "source_type": "event" + }, + "responses": [{ + "url": "https://reporter.test/register-source", + "response": { + "Attribution-Reporting-Register-Source": { + "destination": "https://destination2.test", + "source_event_id": "666", + "event_report_window": "182800" + } + } + }] + } + ], + "triggers": [ + // Event source should report at event report window. + { + "timestamp": "1643235577000", + "registration_request": { + "attribution_src_url": "https://reporter.test/register-trigger", + "destination_origin": "https://destination2.test" + }, + "responses": [{ + "url": "https://reporter.test/register-trigger", + "response": { + "Attribution-Reporting-Register-Trigger": { + "event_trigger_data": [ + { + "trigger_data": "7" + } + ] + } + } + }] + }, + // Should report at event report window. + { + "timestamp": "1643331873000", + "registration_request": { + "attribution_src_url": "https://reporter.test/register-trigger", + "destination_origin": "https://destination.test" + }, + "responses": [{ + "url": "https://reporter.test/register-trigger", + "response": { + "Attribution-Reporting-Register-Trigger": { + "event_trigger_data": [ + { + "trigger_data": "1" + } + ] + } + } + }] + }, + // Should report at 2 days window. + { + "timestamp": "1643408374000", + "registration_request": { + "attribution_src_url": "https://reporter2.test/register-trigger", + "destination_origin": "https://destination.test" + }, + "responses": [{ + "url": "https://reporter2.test/register-trigger", + "response": { + "Attribution-Reporting-Register-Trigger": { + "event_trigger_data": [ + { + "trigger_data": "2" + } + ] + } + } + }] + }, + // Should report at event report window. + { + "timestamp": "1643408374001", + "registration_request": { + "attribution_src_url": "https://reporter2.test/register-trigger", + "destination_origin": "https://destination.test" + }, + "responses": [{ + "url": "https://reporter2.test/register-trigger", + "response": { + "Attribution-Reporting-Register-Trigger": { + "event_trigger_data": [ + { + "trigger_data": "3" + } + ] + } + } + }] + }, + // Should report at 7 days window. + { + "timestamp": "1643840375000", + "registration_request": { + "attribution_src_url": "https://reporter3.test/register-trigger", + "destination_origin": "https://destination.test" + }, + "responses": [{ + "url": "https://reporter3.test/register-trigger", + "response": { + "Attribution-Reporting-Register-Trigger": { + "event_trigger_data": [ + { + "trigger_data": "4" + } + ] + } + } + }] + }, + // Should report at expiry time window. + { + "timestamp": "1643840375001", + "registration_request": { + "attribution_src_url": "https://reporter3.test/register-trigger", + "destination_origin": "https://destination.test" + }, + "responses": [{ + "url": "https://reporter3.test/register-trigger", + "response": { + "Attribution-Reporting-Register-Trigger": { + "event_trigger_data": [ + { + "trigger_data": "5" + } + ] + } + } + }] + } + ] + }, + "output": { + "event_level_results": [ + { + "payload": { + "attribution_destination": "https://destination.test", + "randomized_trigger_rate": 0.0024, + "scheduled_report_time": "1643335573", + "source_event_id": "123", + "source_type": "navigation", + "trigger_data": "1" + }, + "report_url": "https://reporter.test/.well-known/attribution-reporting/report-event-attribution", + "report_time": "1643335573000" + }, + { + "payload": { + "attribution_destination": "https://destination.test", + "randomized_trigger_rate": 0.0024, + "scheduled_report_time": "1643411974", + "source_event_id": "456", + "source_type": "navigation", + "trigger_data": "2" + }, + "report_url": "https://reporter2.test/.well-known/attribution-reporting/report-event-attribution", + "report_time": "1643411974000" + }, + { + "payload": { + "attribution_destination": "https://destination.test", + "randomized_trigger_rate": 0.0024, + "scheduled_report_time": "1643421974", + "source_event_id": "456", + "source_type": "navigation", + "trigger_data": "3" + }, + "report_url": "https://reporter2.test/.well-known/attribution-reporting/report-event-attribution", + "report_time": "1643421974000" + }, + { + "payload": { + "attribution_destination": "https://destination2.test", + "randomized_trigger_rate": 0.0000025, + "scheduled_report_time": "1643421976", + "source_event_id": "666", + "source_type": "event", + "trigger_data": "1" + }, + "report_time": "1643421976000", + "report_url": "https://reporter.test/.well-known/attribution-reporting/report-event-attribution" + }, + { + "payload": { + "attribution_destination": "https://destination.test", + "randomized_trigger_rate": 0.0024, + "scheduled_report_time": "1643843975", + "source_event_id": "789", + "source_type": "navigation", + "trigger_data": "4" + }, + "report_url": "https://reporter3.test/.well-known/attribution-reporting/report-event-attribution", + "report_time": "1643843975000" + }, + { + "payload": { + "attribution_destination": "https://destination.test", + "randomized_trigger_rate": 0.0024, + "scheduled_report_time": "1644103175", + "source_event_id": "789", + "source_type": "navigation", + "trigger_data": "5" + }, + "report_time": "1644103175000", + "report_url": "https://reporter3.test/.well-known/attribution-reporting/report-event-attribution" + } + ] + } +}
diff --git a/content/test/data/interest_group/component_auction_component_decision_argument_validator.js b/content/test/data/interest_group/component_auction_component_decision_argument_validator.js index 9c7c7fe..ff91a14 100644 --- a/content/test/data/interest_group/component_auction_component_decision_argument_validator.js +++ b/content/test/data/interest_group/component_auction_component_decision_argument_validator.js
@@ -87,7 +87,7 @@ JSON.stringify(auctionConfig.perBuyerTimeouts); } - if (auctionConfig.perBuyerCumulativeTimeouts[buyerOrigin] !== 201) { + if (auctionConfig.perBuyerCumulativeTimeouts[buyerOrigin] !== 20100) { throw 'Wrong perBuyerCumulativeTimeouts ' + JSON.stringify(auctionConfig.perBuyerCumulativeTimeouts); }
diff --git a/content/test/data/interest_group/component_auction_top_level_decision_argument_validator.js b/content/test/data/interest_group/component_auction_top_level_decision_argument_validator.js index 0dc46876..0b6bd90e 100644 --- a/content/test/data/interest_group/component_auction_top_level_decision_argument_validator.js +++ b/content/test/data/interest_group/component_auction_top_level_decision_argument_validator.js
@@ -90,8 +90,8 @@ const perBuyerCumulativeTimeoutsJson = JSON.stringify(auctionConfig.perBuyerCumulativeTimeouts); if (!perBuyerCumulativeTimeoutsJson.includes('a.test') || - !perBuyerCumulativeTimeoutsJson.includes('111') || - auctionConfig.perBuyerCumulativeTimeouts['*'] != 151) { + !perBuyerCumulativeTimeoutsJson.includes('11100') || + auctionConfig.perBuyerCumulativeTimeouts['*'] != 15100) { throw 'Wrong perBuyerCumulativeTimeouts ' + perBuyerCumulativeTimeoutsJson; }
diff --git a/content/test/data/interest_group/decision_argument_validator.js b/content/test/data/interest_group/decision_argument_validator.js index 72e405a..a3486813 100644 --- a/content/test/data/interest_group/decision_argument_validator.js +++ b/content/test/data/interest_group/decision_argument_validator.js
@@ -96,9 +96,9 @@ JSON.stringify(auctionConfig.perBuyerTimeouts); } - if (auctionConfig.perBuyerCumulativeTimeouts[buyerAOrigin] !== 130 || - auctionConfig.perBuyerCumulativeTimeouts[buyerBOrigin] !== 140 || - auctionConfig.perBuyerCumulativeTimeouts['*'] !== 160) { + if (auctionConfig.perBuyerCumulativeTimeouts[buyerAOrigin] !== 13000 || + auctionConfig.perBuyerCumulativeTimeouts[buyerBOrigin] !== 14000 || + auctionConfig.perBuyerCumulativeTimeouts['*'] !== 16000) { throw 'Wrong perBuyerCumulativeTimeouts ' + JSON.stringify(auctionConfig.perBuyerCumulativeTimeouts); }
diff --git a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt index e156c12..55e289e 100644 --- a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
@@ -384,8 +384,11 @@ crbug.com/1382332 [ display-server-wayland intel-0x9bc5 linux no-clang-coverage release renderer-skia-gl ] Pixel_MediaRecorderFromVideoElement [ RetryOnFailure ] # Flakes on Pixel 4, Pixel 6, Nexus 5X, and Samsung A13 due to video stream being offset vertically by 1 pixel. -crbug.com/1410332 [ android ] Pixel_VideoStreamFromWebGLAlphaCanvas [ RetryOnFailure ] +# finder:group-start crbug.com/1410332 +crbug.com/1410332 [ android ] Pixel_VideoStreamFrom2DAlphaCanvas [ RetryOnFailure ] crbug.com/1410332 [ android ] Pixel_VideoStreamFrom2DAlphaCanvas_DisableOOPRaster [ RetryOnFailure ] +crbug.com/1410332 [ android ] Pixel_VideoStreamFromWebGLAlphaCanvas [ RetryOnFailure ] +# finder:group-end # Fails on Linux AMD RX 5500 XT with RADV 20.0.8 crbug.com/1418987 [ linux amd-0x7340 angle-vulkan ] Pixel_OffscreenCanvasAccelerated2DWorker [ Failure ]
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt index a63f61c2..f52d079 100644 --- a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
@@ -624,17 +624,20 @@ crbug.com/angleproject/3686 [ android angle-opengles ] deqp/functional/gles3/multisample/fbo_max_samples.html [ Failure ] # finder:group-start crbug.com/1382796 failures happen in many tests, so can be classified as stale for one specific test -crbug.com/1382796 [ android android-pixel-4 angle-opengles passthrough ] conformance/canvas/rapid-resizing.html [ RetryOnFailure ] -crbug.com/1382796 [ android android-pixel-4 angle-opengles passthrough ] conformance/context/context-release-with-workers.html [ RetryOnFailure ] -crbug.com/1382796 [ android android-pixel-4 angle-opengles passthrough ] conformance/textures/misc/texture-corner-case-videos.html [ RetryOnFailure ] -crbug.com/1382796 [ android android-pixel-4 angle-opengles passthrough ] conformance2/sync/sync-webgl-specific.html [ RetryOnFailure ] -crbug.com/1382796 [ android android-pixel-4 angle-opengles passthrough ] deqp/data/gles3/shaders/declarations.html [ RetryOnFailure ] -crbug.com/1382796 [ android android-pixel-4 angle-opengles passthrough ] deqp/functional/gles3/primitiverestart/00.html [ RetryOnFailure ] -crbug.com/1382796 [ android android-pixel-4 angle-opengles passthrough ] deqp/functional/gles3/textureshadow/* [ RetryOnFailure ] +# finder:disable-narrowing +crbug.com/1382796 [ android android-pixel-4 ] conformance/canvas/rapid-resizing.html [ RetryOnFailure ] +crbug.com/1382796 [ android android-pixel-4 ] conformance/context/context-release-with-workers.html [ RetryOnFailure ] +crbug.com/1382796 [ android android-pixel-4 ] conformance/textures/misc/texture-corner-case-videos.html [ RetryOnFailure ] +crbug.com/1382796 [ android android-pixel-4 ] conformance2/sync/sync-webgl-specific.html [ RetryOnFailure ] +crbug.com/1382796 [ android android-pixel-4 ] deqp/data/gles3/shaders/declarations.html [ RetryOnFailure ] +crbug.com/1382796 [ android android-pixel-4 ] deqp/functional/gles3/primitiverestart/00.html [ RetryOnFailure ] +crbug.com/1382796 [ android android-pixel-4 ] deqp/functional/gles3/shadermatrix/transpose.html [ RetryOnFailure ] +crbug.com/1382796 [ android android-pixel-4 ] deqp/functional/gles3/textureshadow/* [ RetryOnFailure ] crbug.com/1382796 [ android android-pixel-4 ] conformance/textures/image_bitmap_from_video/* [ RetryOnFailure ] -crbug.com/1382796 [ android android-pixel-4 angle-opengles passthrough ] conformance/textures/video/* [ RetryOnFailure ] +crbug.com/1382796 [ android android-pixel-4 ] conformance/textures/video/* [ RetryOnFailure ] crbug.com/1382796 [ android android-pixel-4 ] conformance2/textures/image_bitmap_from_video/* [ RetryOnFailure ] -crbug.com/1382796 [ android android-pixel-4 angle-opengles passthrough ] conformance2/textures/video/* [ RetryOnFailure ] +crbug.com/1382796 [ android android-pixel-4 ] conformance2/textures/video/* [ RetryOnFailure ] +# finder:enable-narrowing # finder:group-end crbug.com/1419019 [ android android-pixel-4 no-passthrough ] conformance2/transform_feedback/too-small-buffers.html [ RetryOnFailure ]
diff --git a/content/test/navigation_simulator_impl.cc b/content/test/navigation_simulator_impl.cc index d7bf5ca..d4e0576 100644 --- a/content/test/navigation_simulator_impl.cc +++ b/content/test/navigation_simulator_impl.cc
@@ -1323,7 +1323,8 @@ base::TimeTicks() /* renderer_before_unload_end */, absl::nullopt /* web_bundle_token */, blink::mojom::NavigationInitiatorActivationAndAdStatus:: - kDidNotStartWithTransientActivation); + kDidNotStartWithTransientActivation, + false /* is_container_initiated */); auto common_params = blink::CreateCommonNavigationParams(); common_params->navigation_start = base::TimeTicks::Now(); common_params->input_start = navigation_input_start_;
diff --git a/content/test/test_render_frame_host.cc b/content/test/test_render_frame_host.cc index 0491d69..3cdfea02 100644 --- a/content/test/test_render_frame_host.cc +++ b/content/test/test_render_frame_host.cc
@@ -419,7 +419,8 @@ base::TimeTicks() /* renderer_before_unload_end */, absl::nullopt /* web_bundle_token */, blink::mojom::NavigationInitiatorActivationAndAdStatus:: - kDidNotStartWithTransientActivation); + kDidNotStartWithTransientActivation, + false /* is_container_initiated */); auto common_params = blink::CreateCommonNavigationParams(); common_params->url = url; common_params->initiator_origin = GetLastCommittedOrigin();
diff --git a/device/fido/cros/authenticator.cc b/device/fido/cros/authenticator.cc index 80b9bb3..1fcb6e5d 100644 --- a/device/fido/cros/authenticator.cc +++ b/device/fido/cros/authenticator.cc
@@ -36,8 +36,8 @@ ChromeOSAuthenticator::~ChromeOSAuthenticator() {} -FidoAuthenticator::Type ChromeOSAuthenticator::GetType() const { - return Type::kChromeOS; +AuthenticatorType ChromeOSAuthenticator::GetType() const { + return AuthenticatorType::kChromeOS; } std::string ChromeOSAuthenticator::GetId() const {
diff --git a/device/fido/cros/authenticator.h b/device/fido/cros/authenticator.h index 7a0689e92..4562a04 100644 --- a/device/fido/cros/authenticator.h +++ b/device/fido/cros/authenticator.h
@@ -81,7 +81,7 @@ const CtapGetAssertionOptions& options, GetPlatformCredentialInfoForRequestCallback callback) override; void Cancel() override; - Type GetType() const override; + AuthenticatorType GetType() const override; std::string GetId() const override; const AuthenticatorSupportedOptions& Options() const override;
diff --git a/device/fido/fido_authenticator.cc b/device/fido/fido_authenticator.cc index da4e66b..3f19050 100644 --- a/device/fido/fido_authenticator.cc +++ b/device/fido/fido_authenticator.cc
@@ -186,8 +186,8 @@ absl::nullopt); } -FidoAuthenticator::Type FidoAuthenticator::GetType() const { - return Type::kOther; +AuthenticatorType FidoAuthenticator::GetType() const { + return AuthenticatorType::kOther; } std::string FidoAuthenticator::GetDisplayName() const {
diff --git a/device/fido/fido_authenticator.h b/device/fido/fido_authenticator.h index 426f8370..efb4c0e 100644 --- a/device/fido/fido_authenticator.h +++ b/device/fido/fido_authenticator.h
@@ -23,6 +23,7 @@ #include "device/fido/fido_constants.h" #include "device/fido/fido_request_handler_base.h" #include "device/fido/fido_transport_protocol.h" +#include "device/fido/fido_types.h" #include "device/fido/large_blob.h" #include "device/fido/make_credential_request_handler.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -282,14 +283,8 @@ virtual void Reset(ResetCallback callback); virtual void Cancel() = 0; - enum class Type { - kWinNative, // i.e. webauthn.dll - kTouchID, // the Chrome-native Touch ID integration on macOS - kChromeOS, // the platform authenticator on Chrome OS - kOther, - }; // GetType returns the type of the authenticator. - virtual Type GetType() const; + virtual AuthenticatorType GetType() const; // GetId returns a unique string representing this device. This string should // be distinct from all other devices concurrently discovered.
diff --git a/device/fido/fido_request_handler_base.cc b/device/fido/fido_request_handler_base.cc index 78302aa6..3434598 100644 --- a/device/fido/fido_request_handler_base.cc +++ b/device/fido/fido_request_handler_base.cc
@@ -374,7 +374,7 @@ } #if BUILDFLAG(IS_WIN) - if (authenticator->GetType() == FidoAuthenticator::Type::kWinNative) { + if (authenticator->GetType() == AuthenticatorType::kWinNative) { DCHECK(transport_availability_info_.has_win_native_api_authenticator); transport_availability_info_.win_native_api_authenticator_id = authenticator->GetId();
diff --git a/device/fido/fido_types.h b/device/fido/fido_types.h index 0987c5e..ddcd2ee 100644 --- a/device/fido/fido_types.h +++ b/device/fido/fido_types.h
@@ -90,6 +90,15 @@ kExtension, }; +// AuthenticatorType enumerates the different types of authenticators that this +// code handles. +enum class AuthenticatorType { + kWinNative, // i.e. webauthn.dll + kTouchID, // the Chrome-native Touch ID integration on macOS + kChromeOS, // the platform authenticator on Chrome OS + kOther, +}; + } // namespace device #endif // DEVICE_FIDO_FIDO_TYPES_H_
diff --git a/device/fido/get_assertion_handler_unittest.cc b/device/fido/get_assertion_handler_unittest.cc index 0ddc8df..c337ace5 100644 --- a/device/fido/get_assertion_handler_unittest.cc +++ b/device/fido/get_assertion_handler_unittest.cc
@@ -929,7 +929,7 @@ EXPECT_EQ(handler->AuthenticatorsForTesting().size(), 1u); EXPECT_EQ(handler->AuthenticatorsForTesting().begin()->second->GetType() == - FidoAuthenticator::Type::kWinNative, + AuthenticatorType::kWinNative, enable_api); } }
diff --git a/device/fido/get_assertion_request_handler.cc b/device/fido/get_assertion_request_handler.cc index fd1d11c..989bd5a 100644 --- a/device/fido/get_assertion_request_handler.cc +++ b/device/fido/get_assertion_request_handler.cc
@@ -647,7 +647,7 @@ } #if BUILDFLAG(IS_WIN) - if (authenticator->GetType() == FidoAuthenticator::Type::kWinNative) { + if (authenticator->GetType() == AuthenticatorType::kWinNative) { state_ = State::kFinished; CancelActiveAuthenticators(authenticator->GetId()); if (status != CtapDeviceResponseCode::kSuccess) {
diff --git a/device/fido/mac/authenticator.h b/device/fido/mac/authenticator.h index 23cabb8..b1c56d79 100644 --- a/device/fido/mac/authenticator.h +++ b/device/fido/mac/authenticator.h
@@ -61,7 +61,7 @@ const CtapGetAssertionOptions& options, GetPlatformCredentialInfoForRequestCallback callback) override; void Cancel() override; - Type GetType() const override; + AuthenticatorType GetType() const override; std::string GetId() const override; const AuthenticatorSupportedOptions& Options() const override; absl::optional<FidoTransportProtocol> AuthenticatorTransport() const override;
diff --git a/device/fido/mac/authenticator.mm b/device/fido/mac/authenticator.mm index 48cf70b..98ba1695 100644 --- a/device/fido/mac/authenticator.mm +++ b/device/fido/mac/authenticator.mm
@@ -129,8 +129,8 @@ operation_.reset(); } -FidoAuthenticator::Type TouchIdAuthenticator::GetType() const { - return Type::kTouchID; +AuthenticatorType TouchIdAuthenticator::GetType() const { + return AuthenticatorType::kTouchID; } std::string TouchIdAuthenticator::GetId() const {
diff --git a/device/fido/make_credential_request_handler.cc b/device/fido/make_credential_request_handler.cc index e66e575..48a2c1f 100644 --- a/device/fido/make_credential_request_handler.cc +++ b/device/fido/make_credential_request_handler.cc
@@ -748,7 +748,7 @@ } #if BUILDFLAG(IS_WIN) - if (authenticator->GetType() == FidoAuthenticator::Type::kWinNative) { + if (authenticator->GetType() == AuthenticatorType::kWinNative) { state_ = State::kFinished; if (status != CtapDeviceResponseCode::kSuccess) { std::move(completion_callback_) @@ -983,7 +983,7 @@ request->resident_key_required = #if BUILDFLAG(IS_WIN) // Windows does not yet support rk=preferred. - authenticator->GetType() != FidoAuthenticator::Type::kWinNative && + authenticator->GetType() != AuthenticatorType::kWinNative && #endif auth_options.supports_resident_key && !authenticator->DiscoverableCredentialStorageFull() &&
diff --git a/device/fido/win/authenticator.cc b/device/fido/win/authenticator.cc index b9a255d9..874d71e 100644 --- a/device/fido/win/authenticator.cc +++ b/device/fido/win/authenticator.cc
@@ -363,8 +363,8 @@ win_api_->CancelCurrentOperation(&cancellation_id_); } -FidoAuthenticator::Type WinWebAuthnApiAuthenticator::GetType() const { - return Type::kWinNative; +AuthenticatorType WinWebAuthnApiAuthenticator::GetType() const { + return AuthenticatorType::kWinNative; } std::string WinWebAuthnApiAuthenticator::GetId() const {
diff --git a/device/fido/win/authenticator.h b/device/fido/win/authenticator.h index 297c8b4..e4f9f11 100644 --- a/device/fido/win/authenticator.h +++ b/device/fido/win/authenticator.h
@@ -90,7 +90,7 @@ GetPlatformCredentialInfoForRequestCallback callback) override; void GetTouch(base::OnceClosure callback) override; void Cancel() override; - Type GetType() const override; + AuthenticatorType GetType() const override; std::string GetId() const override; const AuthenticatorSupportedOptions& Options() const override; absl::optional<FidoTransportProtocol> AuthenticatorTransport() const override;
diff --git a/extensions/browser/api/declarative_net_request/file_backed_ruleset_source.cc b/extensions/browser/api/declarative_net_request/file_backed_ruleset_source.cc index b7ac107..05334a5 100644 --- a/extensions/browser/api/declarative_net_request/file_backed_ruleset_source.cc +++ b/extensions/browser/api/declarative_net_request/file_backed_ruleset_source.cc
@@ -132,9 +132,8 @@ std::string rule_location; // If possible use the rule ID in the install warning. - if (auto* id_val = - rules_list[i].FindKeyOfType(kIDKey, base::Value::Type::INTEGER)) { - rule_location = base::StringPrintf("id %d", id_val->GetInt()); + if (auto id = rules_list[i].GetDict().FindInt(kIDKey)) { + rule_location = base::StringPrintf("id %d", *id); } else { // Use one-based indices. rule_location = base::StringPrintf("index %zu", i + 1);
diff --git a/extensions/browser/api/lock_screen_data/lock_screen_item_storage.cc b/extensions/browser/api/lock_screen_data/lock_screen_item_storage.cc index 3b97fbd..28afe8c 100644 --- a/extensions/browser/api/lock_screen_data/lock_screen_item_storage.cc +++ b/extensions/browser/api/lock_screen_data/lock_screen_item_storage.cc
@@ -620,9 +620,9 @@ if (it.second.is_int() && (include_empty || it.second.GetInt() > 0)) { result.insert(it.first); } else if (it.second.is_dict()) { - const base::Value* count = it.second.FindKeyOfType( - kExtensionItemCountPrefKey, base::Value::Type::INTEGER); - if (include_empty || (count && count->GetInt() > 0)) { + absl::optional<int> count = + it.second.GetDict().FindInt(kExtensionItemCountPrefKey); + if (include_empty || (count && *count > 0)) { result.insert(it.first); } }
diff --git a/extensions/common/manifest_handlers/action_handlers_handler.cc b/extensions/common/manifest_handlers/action_handlers_handler.cc index 03dd7bb..85f6222 100644 --- a/extensions/common/manifest_handlers/action_handlers_handler.cc +++ b/extensions/common/manifest_handlers/action_handlers_handler.cc
@@ -54,18 +54,18 @@ std::string value; bool enabled_on_lock_screen = false; if (wrapped_value.is_dict()) { - const base::Value* action_value = wrapped_value.FindKeyOfType( - keys::kActionHandlerActionKey, base::Value::Type::STRING); - if (!action_value) { + const base::Value::Dict& wrapped_dict = wrapped_value.GetDict(); + const std::string* action = + wrapped_dict.FindString(keys::kActionHandlerActionKey); + if (!action) { *error = errors::kInvalidActionHandlerDictionary; return false; } - value = action_value->GetString(); - const base::Value* lock_screen_value = wrapped_value.FindKeyOfType( - keys::kActionHandlerEnabledOnLockScreenKey, - base::Value::Type::BOOLEAN); - if (lock_screen_value) { - enabled_on_lock_screen = lock_screen_value->GetBool(); + value = *action; + absl::optional<bool> enabled = + wrapped_dict.FindBool(keys::kActionHandlerEnabledOnLockScreenKey); + if (enabled) { + enabled_on_lock_screen = *enabled; } } else if (wrapped_value.is_string()) { value = wrapped_value.GetString();
diff --git a/extensions/common/manifest_handlers/nacl_modules_handler.cc b/extensions/common/manifest_handlers/nacl_modules_handler.cc index 1eb30487..ff4e754 100644 --- a/extensions/common/manifest_handlers/nacl_modules_handler.cc +++ b/extensions/common/manifest_handlers/nacl_modules_handler.cc
@@ -54,23 +54,22 @@ const base::Value::List& list = list_value->GetList(); for (size_t i = 0; i < list.size(); ++i) { - if (!list[i].is_dict()) { + const base::Value::Dict* dict = list[i].GetIfDict(); + if (!dict) { *error = errors::kInvalidNaClModules; return false; } // Get nacl_modules[i].path. - const base::Value* path_str = list[i].FindKeyOfType( - keys::kNaClModulesPath, base::Value::Type::STRING); - if (path_str == nullptr) { + const std::string* path = dict->FindString(keys::kNaClModulesPath); + if (path == nullptr) { *error = ErrorUtils::FormatErrorMessageUTF16( errors::kInvalidNaClModulesPath, base::NumberToString(i)); return false; } // Get nacl_modules[i].mime_type. - const base::Value* mime_type = list[i].FindKeyOfType( - keys::kNaClModulesMIMEType, base::Value::Type::STRING); + const std::string* mime_type = dict->FindString(keys::kNaClModulesMIMEType); if (mime_type == nullptr) { *error = ErrorUtils::FormatErrorMessageUTF16( errors::kInvalidNaClModulesMIMEType, base::NumberToString(i)); @@ -79,8 +78,8 @@ nacl_module_data->nacl_modules_.push_back(NaClModuleInfo()); nacl_module_data->nacl_modules_.back().url = - extension->GetResourceURL(path_str->GetString()); - nacl_module_data->nacl_modules_.back().mime_type = mime_type->GetString(); + extension->GetResourceURL(*path); + nacl_module_data->nacl_modules_.back().mime_type = *mime_type; } extension->SetManifestData(keys::kNaClModules, std::move(nacl_module_data));
diff --git a/extensions/renderer/bindings/api_signature.cc b/extensions/renderer/bindings/api_signature.cc index f89a3819..1cc05ad 100644 --- a/extensions/renderer/bindings/api_signature.cc +++ b/extensions/renderer/bindings/api_signature.cc
@@ -33,39 +33,39 @@ }; std::vector<std::unique_ptr<ArgumentSpec>> ValueListToArgumentSpecs( - const base::Value& specification_list, + const base::Value::List& specification_list, bool uses_returns_async) { - std::vector<std::unique_ptr<ArgumentSpec>> signature; - auto size = specification_list.GetList().size(); + std::vector<std::unique_ptr<ArgumentSpec>> signatures; + auto size = specification_list.size(); // If the API specification uses the returns_async format we will be pushing a // callback onto the end of the argument spec list during the call to the ctor // later, so we make room for it now when we reserve the size. if (uses_returns_async) size++; - signature.reserve(size); - for (const auto& value : specification_list.GetList()) { - CHECK(value.is_dict()); - signature.push_back(std::make_unique<ArgumentSpec>(value)); + signatures.reserve(size); + for (const auto& signature : specification_list) { + CHECK(signature.is_dict()); + signatures.push_back(std::make_unique<ArgumentSpec>(signature)); } - return signature; + return signatures; } std::unique_ptr<APISignature::ReturnsAsync> BuildReturnsAsyncFromValues( - const base::Value& returns_async_spec, + const base::Value::Dict& returns_async_spec, bool api_supports_promises) { auto returns_async = std::make_unique<APISignature::ReturnsAsync>(); if (api_supports_promises) returns_async->promise_support = binding::APIPromiseSupport::kSupported; - const base::Value* callback_optional = - returns_async_spec.FindKeyOfType("optional", base::Value::Type::BOOLEAN); - returns_async->optional = callback_optional && callback_optional->GetBool(); + absl::optional<bool> callback_optional = + returns_async_spec.FindBool("optional"); + returns_async->optional = callback_optional.value_or(false); // If response validation is enabled, parse the callback signature. Otherwise, // there's no reason to, so don't bother. if (binding::IsResponseValidationEnabled()) { - const base::Value* callback_params = - returns_async_spec.FindKeyOfType("parameters", base::Value::Type::LIST); + const base::Value::List* callback_params = + returns_async_spec.FindList("parameters"); if (callback_params) { returns_async->signature = ValueListToArgumentSpecs(*callback_params, false); @@ -558,7 +558,8 @@ const std::string& api_name, bool is_event_signature) { bool uses_returns_async = returns_async != nullptr; - auto argument_specs = ValueListToArgumentSpecs(spec_list, uses_returns_async); + auto argument_specs = + ValueListToArgumentSpecs(spec_list.GetList(), uses_returns_async); // Asynchronous returns for an API are either defined in the returns_async // part of the specification or as a trailing function argument. @@ -580,8 +581,8 @@ std::unique_ptr<APISignature::ReturnsAsync> returns_async_struct; if (returns_async_spec) { bool api_supports_promises = returns_async != nullptr; - returns_async_struct = - BuildReturnsAsyncFromValues(*returns_async_spec, api_supports_promises); + returns_async_struct = BuildReturnsAsyncFromValues( + returns_async_spec->GetDict(), api_supports_promises); } return std::make_unique<APISignature>(std::move(argument_specs),
diff --git a/extensions/test/test_extension_dir.cc b/extensions/test/test_extension_dir.cc index 0168c804..705d3eb 100644 --- a/extensions/test/test_extension_dir.cc +++ b/extensions/test/test_extension_dir.cc
@@ -34,9 +34,7 @@ void TestExtensionDir::WriteFile(const base::FilePath::StringType& filename, base::StringPiece contents) { base::ScopedAllowBlockingForTesting allow_blocking; - EXPECT_EQ(base::checked_cast<int>(contents.size()), - base::WriteFile(dir_.GetPath().Append(filename), contents.data(), - contents.size())); + EXPECT_TRUE(base::WriteFile(dir_.GetPath().Append(filename), contents)); } void TestExtensionDir::CopyFileTo(
diff --git a/fuchsia_web/webengine/renderer/web_engine_audio_renderer.cc b/fuchsia_web/webengine/renderer/web_engine_audio_renderer.cc index d4fb641..828d1f09 100644 --- a/fuchsia_web/webengine/renderer/web_engine_audio_renderer.cc +++ b/fuchsia_web/webengine/renderer/web_engine_audio_renderer.cc
@@ -274,7 +274,7 @@ if (GetPlaybackState() == PlaybackState::kStartPending) StartAudioConsumer(); - ScheduleReadDemuxerStream(); + ScheduleBufferTimers(); } media::TimeSource* WebEngineAudioRenderer::GetTimeSource() { @@ -294,7 +294,7 @@ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); renderer_started_ = true; - ScheduleReadDemuxerStream(); + ScheduleBufferTimers(); } void WebEngineAudioRenderer::SetVolume(float volume) { @@ -414,7 +414,7 @@ } FlushInternal(); - ScheduleReadDemuxerStream(); + ScheduleBufferTimers(); } base::TimeDelta WebEngineAudioRenderer::CurrentMediaTime() { @@ -429,29 +429,27 @@ const std::vector<base::TimeDelta>& media_timestamps, std::vector<base::TimeTicks>* wall_clock_times) { wall_clock_times->reserve(media_timestamps.size()); - auto now = base::TimeTicks::Now(); base::AutoLock lock(timeline_lock_); const bool is_time_moving = IsTimeMoving(); if (media_timestamps.empty()) { - wall_clock_times->push_back(is_time_moving ? now : reference_time_); + wall_clock_times->push_back(is_time_moving ? base::TimeTicks::Now() + : reference_time_); return is_time_moving; } - base::TimeTicks wall_clock_base = is_time_moving ? reference_time_ : now; + base::TimeTicks wall_clock_base = + is_time_moving ? reference_time_ : base::TimeTicks::Now(); for (base::TimeDelta timestamp : media_timestamps) { - base::TimeTicks wall_clock_time; - auto relative_pos = timestamp - media_pos_; if (is_time_moving) { // See https://fuchsia.dev/reference/fidl/fuchsia.media#formulas . relative_pos = relative_pos * reference_delta_ / media_delta_; } - wall_clock_time = wall_clock_base + relative_pos; - wall_clock_times->push_back(wall_clock_time); + wall_clock_times->push_back(wall_clock_base + relative_pos); } return is_time_moving; @@ -475,6 +473,7 @@ stream_sink_.Unbind(); sysmem_buffer_stream_.reset(); read_timer_.Stop(); + out_of_buffer_timer_.Stop(); renderer_started_ = false; if (is_demuxer_read_pending_) { @@ -504,7 +503,7 @@ return; } - bool reschedule_read_timer = false; + bool reschedule_timers = false; if (status.has_presentation_timeline()) { if (GetPlaybackState() != PlaybackState::kStopped) { @@ -519,7 +518,7 @@ reference_delta_ = status.presentation_timeline().reference_delta; media_delta_ = status.presentation_timeline().subject_delta; - reschedule_read_timer = true; + reschedule_timers = true; } } @@ -529,7 +528,7 @@ DCHECK(!new_min_lead_time.is_zero()); if (new_min_lead_time != min_lead_time_) { min_lead_time_ = new_min_lead_time; - reschedule_read_timer = true; + reschedule_timers = true; } } if (status.has_max_lead_time()) { @@ -538,51 +537,82 @@ DCHECK(!new_max_lead_time.is_zero()); if (new_max_lead_time != max_lead_time_) { max_lead_time_ = new_max_lead_time; - reschedule_read_timer = true; + reschedule_timers = true; } } - if (reschedule_read_timer) { - read_timer_.Stop(); - ScheduleReadDemuxerStream(); + if (reschedule_timers) { + ScheduleBufferTimers(); } RequestAudioConsumerStatus(); } -void WebEngineAudioRenderer::ScheduleReadDemuxerStream() { +void WebEngineAudioRenderer::ScheduleBufferTimers() { + std::vector<base::TimeDelta> media_timestamps; + if (!last_packet_timestamp_.is_min()) { + media_timestamps.push_back(last_packet_timestamp_); + } + std::vector<base::TimeTicks> wall_clock_times; + bool is_time_moving = GetWallClockTimes(media_timestamps, &wall_clock_times); + + ScheduleReadDemuxerStream(is_time_moving, wall_clock_times[0]); + ScheduleOutOfBufferTimer(is_time_moving, wall_clock_times[0]); +} + +void WebEngineAudioRenderer::ScheduleReadDemuxerStream( + bool is_time_moving, + base::TimeTicks end_of_buffer_time) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - if (!renderer_started_ || !demuxer_stream_ || read_timer_.IsRunning() || - is_demuxer_read_pending_ || is_at_end_of_stream_) { + read_timer_.Stop(); + + if (!renderer_started_ || !demuxer_stream_ || is_demuxer_read_pending_ || + is_at_end_of_stream_) { return; } - base::TimeDelta next_read_delay; - if (!last_packet_timestamp_.is_min()) { - std::vector<base::TimeTicks> wall_clock_times; - bool is_time_moving = - GetWallClockTimes({last_packet_timestamp_}, &wall_clock_times); - base::TimeDelta relative_buffer_pos = - wall_clock_times[0] - base::TimeTicks::Now(); + base::TimeTicks next_read_time; + // If playback is not active then there is no need to buffer more. + if (!is_time_moving) { // Check if we have buffered more than |max_lead_time_|. - if (relative_buffer_pos >= max_lead_time_) { - // If playback is not active then there is no need to buffer more. - if (!is_time_moving) - return; - - // If the buffer is larger than |max_lead_time_|, then the next read - // should be delayed. - next_read_delay = relative_buffer_pos - max_lead_time_; + if (end_of_buffer_time >= base::TimeTicks::Now() + max_lead_time_) { + return; } } - read_timer_.Start(FROM_HERE, next_read_delay, + // Schedule the next read at the time when the buffer size will be below + // `max_lead_time_` (may be in the past). + next_read_time = end_of_buffer_time - max_lead_time_; + + read_timer_.Start(FROM_HERE, next_read_time, base::BindOnce(&WebEngineAudioRenderer::ReadDemuxerStream, base::Unretained(this))); } +void WebEngineAudioRenderer::ScheduleOutOfBufferTimer( + bool is_time_moving, + base::TimeTicks end_of_buffer_time) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + + out_of_buffer_timer_.Stop(); + + if (buffer_state_ == media::BUFFERING_HAVE_NOTHING || !is_time_moving || + is_at_end_of_stream_) { + return; + } + + // Time when the `stream_sink_` will run out of buffer. + base::TimeTicks out_of_buffer_time = end_of_buffer_time - min_lead_time_; + + out_of_buffer_timer_.Start( + FROM_HERE, out_of_buffer_time, + base::BindOnce(&WebEngineAudioRenderer::SetBufferState, + base::Unretained(this), media::BUFFERING_HAVE_NOTHING), + base::subtle::DelayPolicy::kFlexibleNoSooner); +} + void WebEngineAudioRenderer::ReadDemuxerStream() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(demuxer_stream_); @@ -606,7 +636,7 @@ if (drop_next_demuxer_read_result_) { drop_next_demuxer_read_result_ = false; - ScheduleReadDemuxerStream(); + ScheduleBufferTimers(); return; } @@ -621,7 +651,7 @@ // Continue reading the stream. Decryptor won't finish output buffer // initialization until it starts receiving data on the input. - ScheduleReadDemuxerStream(); + ScheduleBufferTimers(); client_->OnAudioConfigChange(demuxer_stream_->audio_decoder_config()); } else { @@ -659,7 +689,7 @@ sysmem_buffer_stream_->EnqueueBuffer(std::move(buffer)); - ScheduleReadDemuxerStream(); + ScheduleBufferTimers(); } void WebEngineAudioRenderer::SendInputPacket( @@ -697,11 +727,14 @@ GetWallClockTimes({packet->timestamp()}, &wall_clock_times); base::TimeDelta relative_buffer_pos = wall_clock_times[0] - base::TimeTicks::Now(); - if (relative_buffer_pos >= min_lead_time_) + if (relative_buffer_pos >= min_lead_time_) { SetBufferState(media::BUFFERING_HAVE_ENOUGH); - } - ScheduleReadDemuxerStream(); + // Reschedule timers to ensure that the state is changed back to + // `BUFFERING_HAVE_NOTHING` when necessary. + ScheduleBufferTimers(); + } + } } void WebEngineAudioRenderer::SetBufferState( @@ -723,6 +756,7 @@ SetBufferState(media::BUFFERING_HAVE_NOTHING); last_packet_timestamp_ = base::TimeDelta::Min(); read_timer_.Stop(); + out_of_buffer_timer_.Stop(); is_at_end_of_stream_ = false; if (is_demuxer_read_pending_) { @@ -787,8 +821,6 @@ // The packet will be sent after StreamSink is connected. delayed_packets_.push_back(std::move(packet)); } - - ScheduleReadDemuxerStream(); } void WebEngineAudioRenderer::OnSysmemBufferStreamEndOfStream() {
diff --git a/fuchsia_web/webengine/renderer/web_engine_audio_renderer.h b/fuchsia_web/webengine/renderer/web_engine_audio_renderer.h index 3f3f74a..3c0dc47 100644 --- a/fuchsia_web/webengine/renderer/web_engine_audio_renderer.h +++ b/fuchsia_web/webengine/renderer/web_engine_audio_renderer.h
@@ -116,13 +116,23 @@ void RequestAudioConsumerStatus(); void OnAudioConsumerStatusChanged(fuchsia::media::AudioConsumerStatus status); + // Calls `ScheduleReadDemuxerStream()` and `ScheduleOutOfBufferTimer()` to + // schedule the corresponding timers. + void ScheduleBufferTimers(); + // Helpers to pump data from |demuxer_stream_| to |stream_sink_|. - void ScheduleReadDemuxerStream(); + void ScheduleReadDemuxerStream(bool is_time_moving, + base::TimeTicks end_of_buffer_time); void ReadDemuxerStream(); void OnDemuxerStreamReadDone( media::DemuxerStream::Status status, media::DemuxerStream::DecoderBufferVector buffers); + // Schedules `out_of_buffer_timer_` timer, which transitions the renderer to + // the `BUFFERING_HAVE_NOTHING` state. + void ScheduleOutOfBufferTimer(bool is_time_moving, + base::TimeTicks end_of_buffer_time); + // Sends the specified packet to |stream_sink_|. void SendInputPacket(media::StreamProcessorHelper::IoPacket packet); @@ -190,7 +200,8 @@ media::BufferingState buffer_state_ = media::BUFFERING_HAVE_NOTHING; base::TimeDelta last_packet_timestamp_ = base::TimeDelta::Min(); - base::OneShotTimer read_timer_; + base::DeadlineTimer read_timer_; + base::DeadlineTimer out_of_buffer_timer_; media::SysmemAllocatorClient sysmem_allocator_{"WebEngineAudioRenderer"}; std::unique_ptr<media::SysmemCollectionClient> input_buffer_collection_;
diff --git a/fuchsia_web/webengine/renderer/web_engine_audio_renderer_test.cc b/fuchsia_web/webengine/renderer/web_engine_audio_renderer_test.cc index 6ea45f99..017513ea 100644 --- a/fuchsia_web/webengine/renderer/web_engine_audio_renderer_test.cc +++ b/fuchsia_web/webengine/renderer/web_engine_audio_renderer_test.cc
@@ -15,6 +15,7 @@ #include "base/test/bind.h" #include "base/test/task_environment.h" #include "base/time/time.h" +#include "media/base/buffering_state.h" #include "media/base/cdm_context.h" #include "media/base/decoder_buffer.h" #include "media/base/renderer_client.h" @@ -1152,3 +1153,29 @@ EXPECT_GT(stream_sink_->received_packets()->size(), 0U); EXPECT_FALSE(stream_sink_->received_end_of_stream()); } + +TEST_P(WebEngineAudioRendererTest, Buffering) { + ASSERT_NO_FATAL_FAILURE(CreateAndInitializeRenderer()); + + constexpr base::TimeDelta kStartPos = base::TimeDelta(); + ASSERT_NO_FATAL_FAILURE(StartPlayback(kStartPos)); + + constexpr base::TimeDelta kTimeBeforeBuffering = base::Milliseconds(500); + FillDemuxerStream(kTimeBeforeBuffering); + + // Buffering state should be set to BUFFERING_HAVE_ENOUGH while the renderer + // still has data to play. + task_environment_.FastForwardBy(kTimeBeforeBuffering - kMinLeadTime - + kPacketDuration); + EXPECT_EQ(client_.buffering_state(), media::BUFFERING_HAVE_ENOUGH); + + // Buffering state should be updated once the renderer runs out of data it can + // read from the demuxer. + task_environment_.FastForwardBy(kPacketDuration); + EXPECT_EQ(client_.buffering_state(), media::BUFFERING_HAVE_NOTHING); + + // Buffering state should be updated once more data is read from the demuxer. + FillDemuxerStream(kTimeBeforeBuffering + kMinLeadTime); + task_environment_.RunUntilIdle(); + EXPECT_EQ(client_.buffering_state(), media::BUFFERING_HAVE_ENOUGH); +}
diff --git a/fuchsia_web/webengine/test/context_provider_for_test.cc b/fuchsia_web/webengine/test/context_provider_for_test.cc index cb3216e4..da2eb11b 100644 --- a/fuchsia_web/webengine/test/context_provider_for_test.cc +++ b/fuchsia_web/webengine/test/context_provider_for_test.cc
@@ -75,15 +75,23 @@ } // namespace -ContextProviderForTest::ContextProviderForTest( - const base::CommandLine& command_line) - : realm_root_(BuildRealm(command_line)) { +// static +ContextProviderForTest ContextProviderForTest::Create( + const base::CommandLine& command_line) { + auto realm_root = BuildRealm(command_line); ::fuchsia::web::ContextProviderPtr context_provider; zx_status_t status = - realm_root_.component().Connect(context_provider_.NewRequest()); + realm_root.component().Connect(context_provider.NewRequest()); ZX_CHECK(status == ZX_OK, status) << "Connect to ContextProvider"; + return ContextProviderForTest(std::move(realm_root), + std::move(context_provider)); } +ContextProviderForTest::ContextProviderForTest( + ContextProviderForTest&&) noexcept = default; +ContextProviderForTest& ContextProviderForTest::operator=( + ContextProviderForTest&&) noexcept = default; + ContextProviderForTest::~ContextProviderForTest() { // We're about to shut down the realm; unbind to unhook the error handler. context_provider_.Unbind(); @@ -93,10 +101,23 @@ run_loop.Run(); } -ContextProviderForDebugTest::ContextProviderForDebugTest( - const base::CommandLine& command_line) - : context_provider_(command_line) {} +ContextProviderForTest::ContextProviderForTest( + ::component_testing::RealmRoot realm_root, + ::fuchsia::web::ContextProviderPtr context_provider) + : realm_root_(std::move(realm_root)), + context_provider_(std::move(context_provider)) {} +// static +ContextProviderForDebugTest ContextProviderForDebugTest::Create( + const base::CommandLine& command_line) { + return ContextProviderForDebugTest( + ContextProviderForTest::Create(command_line)); +} + +ContextProviderForDebugTest::ContextProviderForDebugTest( + ContextProviderForDebugTest&&) noexcept = default; +ContextProviderForDebugTest& ContextProviderForDebugTest::operator=( + ContextProviderForDebugTest&&) noexcept = default; ContextProviderForDebugTest::~ContextProviderForDebugTest() = default; void ContextProviderForDebugTest::ConnectToDebug( @@ -105,3 +126,7 @@ std::move(debug_request)); ZX_CHECK(status == ZX_OK, status) << "Connect to Debug"; } + +ContextProviderForDebugTest::ContextProviderForDebugTest( + ContextProviderForTest context_provider) + : context_provider_(std::move(context_provider)) {}
diff --git a/fuchsia_web/webengine/test/context_provider_for_test.h b/fuchsia_web/webengine/test/context_provider_for_test.h index e6fbd862..eefb909 100644 --- a/fuchsia_web/webengine/test/context_provider_for_test.h +++ b/fuchsia_web/webengine/test/context_provider_for_test.h
@@ -16,11 +16,10 @@ // system log. class ContextProviderForTest { public: - explicit ContextProviderForTest(const base::CommandLine& command_line); + static ContextProviderForTest Create(const base::CommandLine& command_line); - ContextProviderForTest(const ContextProviderForTest&) = delete; - ContextProviderForTest& operator=(const ContextProviderForTest&) = delete; - + ContextProviderForTest(ContextProviderForTest&&) noexcept; + ContextProviderForTest& operator=(ContextProviderForTest&&) noexcept; ~ContextProviderForTest(); ::fuchsia::web::ContextProviderPtr& ptr() { return context_provider_; } @@ -28,6 +27,9 @@ ::component_testing::RealmRoot& realm_root() { return realm_root_; } private: + ContextProviderForTest(::component_testing::RealmRoot realm_root, + ::fuchsia::web::ContextProviderPtr context_provider); + ::component_testing::RealmRoot realm_root_; ::fuchsia::web::ContextProviderPtr context_provider_; }; @@ -36,8 +38,12 @@ // WebEngine's fuchsia::web::Debug interface. class ContextProviderForDebugTest { public: - explicit ContextProviderForDebugTest(const base::CommandLine& command_line); + static ContextProviderForDebugTest Create( + const base::CommandLine& command_line); + ContextProviderForDebugTest(ContextProviderForDebugTest&&) noexcept; + ContextProviderForDebugTest& operator=( + ContextProviderForDebugTest&&) noexcept; ~ContextProviderForDebugTest(); ::fuchsia::web::ContextProviderPtr& ptr() { return context_provider_.ptr(); } @@ -47,6 +53,8 @@ ::fidl::InterfaceRequest<::fuchsia::web::Debug> debug_request); private: + explicit ContextProviderForDebugTest(ContextProviderForTest context_provider); + ContextProviderForTest context_provider_; };
diff --git a/fuchsia_web/webengine/web_engine_debug_integration_test.cc b/fuchsia_web/webengine/web_engine_debug_integration_test.cc index bd1cce6..fcdc6c0 100644 --- a/fuchsia_web/webengine/web_engine_debug_integration_test.cc +++ b/fuchsia_web/webengine/web_engine_debug_integration_test.cc
@@ -26,7 +26,10 @@ class WebEngineDebugIntegrationTest : public testing::Test { public: - WebEngineDebugIntegrationTest() { + WebEngineDebugIntegrationTest() + : web_context_provider_(ContextProviderForDebugTest::Create( + base::CommandLine(base::CommandLine::NO_PROGRAM))), + dev_tools_listener_binding_(&dev_tools_listener_) { web_context_provider_.ptr().set_error_handler( [](zx_status_t status) { FAIL() << zx_status_get_string(status); }); } @@ -53,11 +56,9 @@ base::test::SingleThreadTaskEnvironment task_environment_{ base::test::SingleThreadTaskEnvironment::MainThreadType::IO}; - ContextProviderForDebugTest web_context_provider_{ - base::CommandLine(base::CommandLine::NO_PROGRAM)}; + ContextProviderForDebugTest web_context_provider_; TestDebugListener dev_tools_listener_; - fidl::Binding<fuchsia::web::DevToolsListener> dev_tools_listener_binding_{ - &dev_tools_listener_}; + fidl::Binding<fuchsia::web::DevToolsListener> dev_tools_listener_binding_; fuchsia::web::DebugSyncPtr debug_; base::OnceClosure on_url_fetch_complete_ack_;
diff --git a/fuchsia_web/webengine/web_engine_integration_logging_test.cc b/fuchsia_web/webengine/web_engine_integration_logging_test.cc index 2a413073..1886b17 100644 --- a/fuchsia_web/webengine/web_engine_integration_logging_test.cc +++ b/fuchsia_web/webengine/web_engine_integration_logging_test.cc
@@ -54,7 +54,8 @@ } void StartWebEngine(base::CommandLine command_line) override { - context_provider_.emplace(command_line); + context_provider_.emplace( + ContextProviderForTest::Create(std::move(command_line))); context_provider_->ptr().set_error_handler( [](zx_status_t status) { FAIL() << zx_status_get_string(status); }); }
diff --git a/fuchsia_web/webengine/web_engine_integration_test.cc b/fuchsia_web/webengine/web_engine_integration_test.cc index 00047022..27e6201 100644 --- a/fuchsia_web/webengine/web_engine_integration_test.cc +++ b/fuchsia_web/webengine/web_engine_integration_test.cc
@@ -60,7 +60,8 @@ } void StartWebEngine(base::CommandLine command_line) override { - context_provider_.emplace(command_line); + context_provider_.emplace( + ContextProviderForTest::Create(std::move(command_line))); context_provider_->ptr().set_error_handler( [](zx_status_t status) { FAIL() << zx_status_get_string(status); }); }
diff --git a/infra/config/PRESUBMIT.py b/infra/config/PRESUBMIT.py index 1dcd017f..85f3c35 100644 --- a/infra/config/PRESUBMIT.py +++ b/infra/config/PRESUBMIT.py
@@ -110,7 +110,7 @@ def CheckOutagesConfigOnCommit(input_api, output_api): outages_pyl = input_api.os_path.join( input_api.PresubmitLocalPath(), 'generated/outages.pyl') - with open(outages_pyl) as f: + with open(outages_pyl, encoding='utf-8') as f: outages_config = input_api.ast.literal_eval(f.read()) if not outages_config:
diff --git a/infra/config/generated/builders/ci/android-fieldtrial-rel/properties.json b/infra/config/generated/builders/ci/android-fieldtrial-rel/properties.json index 34441d24..8eb4bd4 100644 --- a/infra/config/generated/builders/ci/android-fieldtrial-rel/properties.json +++ b/infra/config/generated/builders/ci/android-fieldtrial-rel/properties.json
@@ -50,11 +50,6 @@ ] } }, - "$build/goma": { - "enable_ats": true, - "rpc_extra_params": "?prod", - "server_host": "goma.chromium.org" - }, "$build/reclient": { "instance": "rbe-chromium-trusted", "jobs": 250,
diff --git a/infra/config/generated/builders/ci/win-fieldtrial-rel/properties.json b/infra/config/generated/builders/ci/win-fieldtrial-rel/properties.json index 533fb471..973c8a9 100644 --- a/infra/config/generated/builders/ci/win-fieldtrial-rel/properties.json +++ b/infra/config/generated/builders/ci/win-fieldtrial-rel/properties.json
@@ -44,11 +44,6 @@ ] } }, - "$build/goma": { - "enable_ats": true, - "rpc_extra_params": "?prod", - "server_host": "goma.chromium.org" - }, "$build/reclient": { "instance": "rbe-chromium-trusted", "jobs": 80,
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg index cd545ca3..23d1bf7 100644 --- a/infra/config/generated/luci/cr-buildbucket.cfg +++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -2244,7 +2244,7 @@ dimensions: "builderless:1" dimensions: "cores:8" dimensions: "cpu:x86-64" - dimensions: "free_space:standard" + dimensions: "free_space:high" dimensions: "os:Ubuntu-18.04" dimensions: "pool:luci.chromium.ci" dimensions: "ssd:0" @@ -3467,12 +3467,6 @@ } properties: '{' - ' "$build/goma": {' - ' "enable_ats": true,' - ' "jobs": 250,' - ' "rpc_extra_params": "?prod",' - ' "server_host": "goma.chromium.org"' - ' },' ' "$build/reclient": {' ' "bootstrap_env": {' ' "RBE_deps_cache_mode": "reproxy",' @@ -3557,12 +3551,6 @@ } properties: '{' - ' "$build/goma": {' - ' "enable_ats": true,' - ' "jobs": 250,' - ' "rpc_extra_params": "?prod",' - ' "server_host": "goma.chromium.org"' - ' },' ' "$build/reclient": {' ' "bootstrap_env": {' ' "RBE_deps_cache_mode": "reproxy",' @@ -3647,12 +3635,6 @@ } properties: '{' - ' "$build/goma": {' - ' "enable_ats": true,' - ' "jobs": 300,' - ' "rpc_extra_params": "?prod",' - ' "server_host": "goma.chromium.org"' - ' },' ' "$build/reclient": {' ' "bootstrap_env": {' ' "RBE_deps_cache_mode": "reproxy",' @@ -3737,12 +3719,6 @@ } properties: '{' - ' "$build/goma": {' - ' "enable_ats": true,' - ' "jobs": 250,' - ' "rpc_extra_params": "?prod",' - ' "server_host": "goma.chromium.org"' - ' },' ' "$build/reclient": {' ' "bootstrap_env": {' ' "RBE_deps_cache_mode": "reproxy",' @@ -3826,12 +3802,6 @@ } properties: '{' - ' "$build/goma": {' - ' "enable_ats": true,' - ' "jobs": 150,' - ' "rpc_extra_params": "?prod",' - ' "server_host": "goma.chromium.org"' - ' },' ' "$build/reclient": {' ' "bootstrap_env": {' ' "RBE_deps_cache_mode": "reproxy",' @@ -3914,11 +3884,6 @@ } properties: '{' - ' "$build/goma": {' - ' "jobs": 250,' - ' "rpc_extra_params": "?prod",' - ' "server_host": "goma.chromium.org"' - ' },' ' "$build/reclient": {' ' "bootstrap_env": {' ' "GLOG_vmodule": "bridge*=2",' @@ -4003,11 +3968,6 @@ } properties: '{' - ' "$build/goma": {' - ' "jobs": 150,' - ' "rpc_extra_params": "?prod",' - ' "server_host": "goma.chromium.org"' - ' },' ' "$build/reclient": {' ' "bootstrap_env": {' ' "GLOG_vmodule": "bridge*=2",' @@ -4092,11 +4052,6 @@ } properties: '{' - ' "$build/goma": {' - ' "jobs": 250,' - ' "rpc_extra_params": "?prod",' - ' "server_host": "goma.chromium.org"' - ' },' ' "$build/reclient": {' ' "bootstrap_env": {' ' "GLOG_vmodule": "bridge*=2",' @@ -4180,11 +4135,6 @@ } properties: '{' - ' "$build/goma": {' - ' "jobs": 250,' - ' "rpc_extra_params": "?prod",' - ' "server_host": "goma.chromium.org"' - ' },' ' "$build/reclient": {' ' "bootstrap_env": {' ' "GLOG_vmodule": "bridge*=2",' @@ -4270,12 +4220,6 @@ } properties: '{' - ' "$build/goma": {' - ' "enable_ats": true,' - ' "jobs": 250,' - ' "rpc_extra_params": "?prod",' - ' "server_host": "goma.chromium.org"' - ' },' ' "$build/reclient": {' ' "bootstrap_env": {' ' "RBE_deps_cache_mode": "reproxy",' @@ -4359,12 +4303,6 @@ } properties: '{' - ' "$build/goma": {' - ' "enable_ats": true,' - ' "jobs": 300,' - ' "rpc_extra_params": "?prod",' - ' "server_host": "goma.chromium.org"' - ' },' ' "$build/reclient": {' ' "bootstrap_env": {' ' "RBE_deps_cache_mode": "reproxy",' @@ -4449,12 +4387,6 @@ } properties: '{' - ' "$build/goma": {' - ' "enable_ats": true,' - ' "jobs": 80,' - ' "rpc_extra_params": "?prod",' - ' "server_host": "goma.chromium.org"' - ' },' ' "$build/reclient": {' ' "bootstrap_env": {' ' "RBE_deps_cache_mode": "reproxy",' @@ -4538,12 +4470,6 @@ } properties: '{' - ' "$build/goma": {' - ' "enable_ats": true,' - ' "jobs": 250,' - ' "rpc_extra_params": "?prod",' - ' "server_host": "goma.chromium.org"' - ' },' ' "$build/reclient": {' ' "bootstrap_env": {' ' "RBE_deps_cache_mode": "reproxy",' @@ -4627,12 +4553,6 @@ } properties: '{' - ' "$build/goma": {' - ' "enable_ats": false,' - ' "jobs": 300,' - ' "rpc_extra_params": "?prod",' - ' "server_host": "goma.chromium.org"' - ' },' ' "$build/reclient": {' ' "bootstrap_env": {' ' "RBE_deps_cache_mode": "reproxy",' @@ -4715,11 +4635,6 @@ } properties: '{' - ' "$build/goma": {' - ' "jobs": 250,' - ' "rpc_extra_params": "?prod",' - ' "server_host": "goma.chromium.org"' - ' },' ' "$build/reclient": {' ' "bootstrap_env": {' ' "RBE_deps_cache_mode": "reproxy",' @@ -4808,11 +4723,6 @@ } properties: '{' - ' "$build/goma": {' - ' "jobs": 150,' - ' "rpc_extra_params": "?prod",' - ' "server_host": "goma.chromium.org"' - ' },' ' "$build/reclient": {' ' "bootstrap_env": {' ' "RBE_deps_cache_mode": "reproxy",' @@ -28678,11 +28588,6 @@ ' ]' ' }' ' },' - ' "$build/goma": {' - ' "enable_ats": true,' - ' "rpc_extra_params": "?prod",' - ' "server_host": "goma.chromium.org"' - ' },' ' "$build/reclient": {' ' "instance": "rbe-chromium-untrusted",' ' "jobs": 300,' @@ -28802,11 +28707,6 @@ ' "$build/code_coverage": {' ' "use_clang_coverage": true' ' },' - ' "$build/goma": {' - ' "enable_ats": true,' - ' "rpc_extra_params": "?prod",' - ' "server_host": "goma.chromium.org"' - ' },' ' "$build/reclient": {' ' "instance": "rbe-chromium-untrusted",' ' "jobs": 300,' @@ -28926,11 +28826,6 @@ ' "$build/code_coverage": {' ' "use_clang_coverage": true' ' },' - ' "$build/goma": {' - ' "enable_ats": true,' - ' "rpc_extra_params": "?prod",' - ' "server_host": "goma.chromium.org"' - ' },' ' "$build/reclient": {' ' "instance": "rbe-chromium-untrusted",' ' "jobs": 300,'
diff --git a/infra/config/subprojects/chromium/ci/chromium.android.star b/infra/config/subprojects/chromium/ci/chromium.android.star index b8d1318..df3572d 100644 --- a/infra/config/subprojects/chromium/ci/chromium.android.star +++ b/infra/config/subprojects/chromium/ci/chromium.android.star
@@ -335,6 +335,7 @@ name = "Android x64 Builder All Targets (dbg)", branch_selector = branches.selector.ANDROID_BRANCHES, builder_spec = builder_config.copy_from("ci/Android x64 Builder (dbg)"), + free_space = builders.free_space.high, console_view_entry = consoles.console_view_entry( category = "builder|x86", short_name = "64-all",
diff --git a/infra/config/subprojects/chromium/ci/chromium.fyi.star b/infra/config/subprojects/chromium/ci/chromium.fyi.star index 8b958b6..90dc2bf0 100644 --- a/infra/config/subprojects/chromium/ci/chromium.fyi.star +++ b/infra/config/subprojects/chromium/ci/chromium.fyi.star
@@ -5,7 +5,7 @@ load("//lib/branches.star", "branches") load("//lib/builder_config.star", "builder_config") -load("//lib/builders.star", "builders", "cpu", "goma", "os", "reclient", "xcode") +load("//lib/builders.star", "builders", "cpu", "os", "reclient", "xcode") load("//lib/ci.star", "ci") load("//lib/consoles.star", "consoles") load("//lib/structs.star", "structs") @@ -522,7 +522,6 @@ console_view_entry = consoles.console_view_entry( category = "android", ), - goma_backend = goma.backend.RBE_PROD, ) fyi_ios_builder( @@ -1119,8 +1118,6 @@ short_name = "cmp", ), execution_timeout = 15 * time.hour, - goma_backend = goma.backend.RBE_PROD, - goma_jobs = 250, reclient_bootstrap_env = { "RBE_ip_reset_min_delay": "-1s", "RBE_experimental_goma_deps_cache": "true", @@ -1145,8 +1142,6 @@ short_name = "cmp", ), execution_timeout = 15 * time.hour, - goma_backend = goma.backend.RBE_PROD, - goma_jobs = 250, reclient_bootstrap_env = { "RBE_ip_reset_min_delay": "-1s", "RBE_experimental_goma_deps_cache": "true", @@ -1164,8 +1159,6 @@ short_name = "cmp", ), execution_timeout = 6 * time.hour, - goma_backend = goma.backend.RBE_PROD, - goma_jobs = 250, reclient_bootstrap_env = { "RBE_ip_reset_min_delay": "-1s", "RBE_experimental_goma_deps_cache": "true", @@ -1184,8 +1177,6 @@ short_name = "cmp", ), execution_timeout = 10 * time.hour, - goma_backend = goma.backend.RBE_PROD, - goma_jobs = 250, reclient_bootstrap_env = { "RBE_ip_reset_min_delay": "-1s", "GLOG_vmodule": "bridge*=2", @@ -1206,8 +1197,6 @@ short_name = "cmp", ), execution_timeout = 10 * time.hour, - goma_backend = goma.backend.RBE_PROD, - goma_jobs = 250, reclient_bootstrap_env = { "RBE_ip_reset_min_delay": "-1s", "GLOG_vmodule": "bridge*=2", @@ -1229,8 +1218,6 @@ short_name = "cmp", ), execution_timeout = 10 * time.hour, - goma_backend = goma.backend.RBE_PROD, - goma_jobs = 250, reclient_bootstrap_env = { "RBE_ip_reset_min_delay": "-1s", "GLOG_vmodule": "bridge*=2", @@ -1252,8 +1239,6 @@ category = "win", short_name = "re", ), - goma_backend = goma.backend.RBE_PROD, - goma_jobs = 80, reclient_bootstrap_env = { "RBE_ip_reset_min_delay": "-1s", "RBE_experimental_goma_deps_cache": "true", @@ -1275,8 +1260,6 @@ short_name = "re", ), execution_timeout = 6 * time.hour, - goma_backend = goma.backend.RBE_PROD, - goma_jobs = 250, reclient_bootstrap_env = { "RBE_ip_reset_min_delay": "-1s", "RBE_experimental_goma_deps_cache": "true", @@ -1295,8 +1278,6 @@ short_name = "cmp", ), execution_timeout = 10 * time.hour, - goma_backend = goma.backend.RBE_PROD, - goma_jobs = 250, reclient_bootstrap_env = { "RBE_ip_reset_min_delay": "-1s", "RBE_experimental_goma_deps_cache": "true", @@ -1315,8 +1296,6 @@ short_name = "cmp", ), execution_timeout = 10 * time.hour, - goma_backend = goma.backend.RBE_PROD, - goma_jobs = 250, reclient_bootstrap_env = { "RBE_ip_reset_min_delay": "-1s", "RBE_experimental_goma_deps_cache": "true", @@ -1342,8 +1321,6 @@ short_name = "cmp", ), execution_timeout = 15 * time.hour, - goma_backend = goma.backend.RBE_PROD, - goma_jobs = goma.jobs.J300, reclient_bootstrap_env = { "RBE_ip_reset_min_delay": "-1s", "RBE_experimental_goma_deps_cache": "true", @@ -1369,8 +1346,6 @@ short_name = "cmp", ), execution_timeout = 6 * time.hour, - goma_backend = goma.backend.RBE_PROD, - goma_jobs = 150, reclient_bootstrap_env = { "RBE_ip_reset_min_delay": "-1s", "RBE_experimental_goma_deps_cache": "true", @@ -1396,8 +1371,6 @@ short_name = "cmp", ), execution_timeout = 10 * time.hour, - goma_backend = goma.backend.RBE_PROD, - goma_jobs = 150, reclient_bootstrap_env = { "GLOG_vmodule": "bridge*=2", "RBE_ip_reset_min_delay": "-1s", @@ -1425,9 +1398,7 @@ short_name = "re", ), execution_timeout = 6 * time.hour, - goma_backend = goma.backend.RBE_PROD, goma_enable_ats = False, - goma_jobs = 300, reclient_bootstrap_env = { "RBE_ip_reset_min_delay": "-1s", "RBE_experimental_goma_deps_cache": "true", @@ -1454,8 +1425,6 @@ short_name = "cmp", ), execution_timeout = 10 * time.hour, - goma_backend = goma.backend.RBE_PROD, - goma_jobs = 300, reclient_bootstrap_env = { "RBE_ip_reset_min_delay": "-1s", "RBE_experimental_goma_deps_cache": "true", @@ -1481,8 +1450,6 @@ short_name = "cmp", ), execution_timeout = 10 * time.hour, - goma_backend = goma.backend.RBE_PROD, - goma_jobs = 150, reclient_bootstrap_env = { "RBE_ip_reset_min_delay": "-1s", "RBE_experimental_goma_deps_cache": "true", @@ -1535,7 +1502,6 @@ short_name = "and", ), execution_timeout = 10 * time.hour, - goma_backend = goma.backend.RBE_PROD, reclient_instance = reclient.instance.DEFAULT_UNTRUSTED, reclient_jobs = reclient.jobs.HIGH_JOBS_FOR_CQ, service_account = "chromium-build-perf-ci-builder@chops-service-accounts.iam.gserviceaccount.com", @@ -1572,7 +1538,6 @@ short_name = "lnx", ), execution_timeout = 6 * time.hour, - goma_backend = goma.backend.RBE_PROD, reclient_instance = reclient.instance.DEFAULT_UNTRUSTED, reclient_jobs = reclient.jobs.HIGH_JOBS_FOR_CQ, service_account = "chromium-build-perf-ci-builder@chops-service-accounts.iam.gserviceaccount.com", @@ -1610,7 +1575,6 @@ short_name = "win", ), execution_timeout = 6 * time.hour, - goma_backend = goma.backend.RBE_PROD, reclient_instance = reclient.instance.DEFAULT_UNTRUSTED, reclient_jobs = reclient.jobs.HIGH_JOBS_FOR_CQ, service_account = "chromium-build-perf-ci-builder@chops-service-accounts.iam.gserviceaccount.com", @@ -2471,7 +2435,6 @@ category = "win11", ), experimental = True, - goma_backend = None, reclient_instance = reclient.instance.DEFAULT_TRUSTED, reclient_jobs = reclient.jobs.DEFAULT, ) @@ -2519,7 +2482,6 @@ console_view_entry = consoles.console_view_entry( category = "win", ), - goma_backend = goma.backend.RBE_PROD, reclient_jobs = reclient.jobs.LOW_JOBS_FOR_CI, )
diff --git a/ios/chrome/app/post_restore_app_agent_unittest.mm b/ios/chrome/app/post_restore_app_agent_unittest.mm index a9d3fb03..736c49e4 100644 --- a/ios/chrome/app/post_restore_app_agent_unittest.mm +++ b/ios/chrome/app/post_restore_app_agent_unittest.mm
@@ -95,11 +95,6 @@ StorePreRestoreIdentity(local_state_.Get(), accountInfo); } - void EnableFeatureVariationFullscreen() { - scoped_feature_list_.InitAndEnableFeature( - post_restore_signin::features::kIOSNewPostRestoreExperience); - } - void EnableFeatureVariationAlert() { scoped_feature_list_.InitWithFeaturesAndParameters( {base::test::FeatureRefAndParams( @@ -124,18 +119,7 @@ MockAppStateChange(InitStageFinal); ClearPreRestoreIdentity(local_state_.Get()); - EnableFeatureVariationFullscreen(); - MockAppStateChange(InitStageFinal); -} - -TEST_F(PostRestoreAppAgentTest, registerPromoFullscreen) { - EXPECT_CALL(*promos_manager_.get(), - RegisterPromoForSingleDisplay( - promos_manager::Promo::PostRestoreSignInFullscreen)) - .Times(1); - - EnableFeatureVariationFullscreen(); - SetFakePreRestoreAccountInfo(); + EnableFeatureVariationAlert(); MockAppStateChange(InitStageFinal); } @@ -151,7 +135,7 @@ } TEST_F(PostRestoreAppAgentTest, registerPromoDisablesReauthPrompt) { - EnableFeatureVariationFullscreen(); + EnableFeatureVariationAlert(); SetFakePreRestoreAccountInfo(); auth_service_->SetReauthPromptForSignInAndSync(); EXPECT_TRUE(auth_service_->ShouldReauthPromptForSignInAndSync()); @@ -159,43 +143,18 @@ EXPECT_FALSE(auth_service_->ShouldReauthPromptForSignInAndSync()); } -TEST_F(PostRestoreAppAgentTest, deregisterPromoFullscreen) { - EXPECT_CALL(*promos_manager_.get(), DeregisterPromo(_)).Times(1); - EXPECT_CALL( - *promos_manager_.get(), - DeregisterPromo(promos_manager::Promo::PostRestoreSignInFullscreen)) - .Times(1); - - EnableFeatureVariationAlert(); - SetFakePreRestoreAccountInfo(); - ClearPreRestoreIdentity(local_state_.Get()); - MockAppStateChange(InitStageFinal); -} - TEST_F(PostRestoreAppAgentTest, deregisterPromoAlert) { EXPECT_CALL(*promos_manager_.get(), DeregisterPromo(_)).Times(1); EXPECT_CALL(*promos_manager_.get(), DeregisterPromo(promos_manager::Promo::PostRestoreSignInAlert)) .Times(1); - EnableFeatureVariationFullscreen(); + EnableFeatureVariationAlert(); SetFakePreRestoreAccountInfo(); ClearPreRestoreIdentity(local_state_.Get()); MockAppStateChange(InitStageFinal); } -TEST_F(PostRestoreAppAgentTest, featureVariationSwitchToFullscreen) { - EXPECT_CALL(*promos_manager_.get(), - RegisterPromoForSingleDisplay( - promos_manager::Promo::PostRestoreSignInFullscreen)) - .Times(1); - - EnableFeatureVariationFullscreen(); - SetFakePreRestoreAccountInfo(); - - MockAppStateChange(InitStageFinal); -} - TEST_F(PostRestoreAppAgentTest, featureVariationSwitchToAlert) { EXPECT_CALL(*promos_manager_.get(), RegisterPromoForSingleDisplay(
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd index 357ae42..53ccdabf 100644 --- a/ios/chrome/app/strings/ios_strings.grd +++ b/ios/chrome/app/strings/ios_strings.grd
@@ -2331,7 +2331,7 @@ <message name="IDS_IOS_TOOLS_MENU_CELL_NEW_FEATURE_BADGE" desc="Title and accessibility label of the badge displayed on a tools menu item when it represents a new feature [Length: 20em]" meaning="A badge with this title is displayed informing the user that this feature that is new to them."> New </message> - <message name="IDS_IOS_NEW_LABEL_FEATURE_BADGE" desc="Character representing the word new displayed inside the badge to represent a new features [iOS only]"> + <message name="IDS_IOS_NEW_LABEL_FEATURE_BADGE" desc="Character representing the word new displayed inside the badge to represent a new features [CHAR_LIMIT=1][iOS only]" meaning="A badge with a character representing the word new is displayed to inform users that a feature a new. [CHAR_LIMIT=1][iOS only]"> N </message> <message name="IDS_IOS_TOOLS_MENU_DOWNLOADS" desc="The iOS menu item for opening the downloads folder [iOS only]" meaning="[Length: unlimited]">
diff --git a/ios/chrome/browser/autofill/form_structure_browsertest.mm b/ios/chrome/browser/autofill/form_structure_browsertest.mm index 1f58c73..2daf0a9 100644 --- a/ios/chrome/browser/autofill/form_structure_browsertest.mm +++ b/ios/chrome/browser/autofill/form_structure_browsertest.mm
@@ -220,10 +220,13 @@ // TODO(crbug.com/1355264): Remove once launched. features::kAutofillLabelAffixRemoval}, // Disabled - // TODO(crbug.com/1311937): Remove once launched. - // This feature is part of the AutofillRefinedPhoneNumberTypes rollout. As - // it is not supported on iOS yet, it is disabled. - {features::kAutofillConsiderPhoneNumberSeparatorsValidLabels}); + {// TODO(crbug.com/1311937): Remove once launched. + // This feature is part of the AutofillRefinedPhoneNumberTypes rollout. + // As it is not supported on iOS yet, it is disabled. + features::kAutofillConsiderPhoneNumberSeparatorsValidLabels, + // TODO(crbug.com/1317961): Remove once launched. This feature is + // disabled since it is not supported on iOS. + features::kAutofillAlwaysParsePlaceholders}); } void FormStructureBrowserTest::SetUp() {
diff --git a/ios/chrome/browser/flags/BUILD.gn b/ios/chrome/browser/flags/BUILD.gn index de57220..808b7fda 100644 --- a/ios/chrome/browser/flags/BUILD.gn +++ b/ios/chrome/browser/flags/BUILD.gn
@@ -18,6 +18,7 @@ "//base", "//components/autofill/core/common", "//components/autofill/ios/browser", + "//components/bookmarks/common", "//components/breadcrumbs/core:feature_flags", "//components/commerce/core:feature_list", "//components/dom_distiller/core",
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm index 06b5cc8..fa03cda0 100644 --- a/ios/chrome/browser/flags/about_flags.mm +++ b/ios/chrome/browser/flags/about_flags.mm
@@ -25,6 +25,7 @@ #import "components/autofill/core/common/autofill_payments_features.h" #import "components/autofill/core/common/autofill_switches.h" #import "components/autofill/ios/browser/autofill_switches.h" +#import "components/bookmarks/common/bookmark_features.h" #import "components/breadcrumbs/core/features.h" #import "components/commerce/core/commerce_feature_list.h" #import "components/commerce/core/flag_descriptions.h" @@ -1392,6 +1393,15 @@ flag_descriptions::kIndicateAccountStorageErrorInAccountCellDescription, flags_ui::kOsIos, FEATURE_VALUE_TYPE(kIndicateAccountStorageErrorInAccountCell)}, + {"enable-bookmarks-account-storage", + flag_descriptions::kEnableBookmarksAccountStorageName, + flag_descriptions::kEnableBookmarksAccountStorageDescription, + flags_ui::kOsIos, + FEATURE_VALUE_TYPE(bookmarks::kEnableBookmarksAccountStorage)}, + {"web-feed-feedback-reroute", + flag_descriptions::kWebFeedFeedbackRerouteName, + flag_descriptions::kWebFeedFeedbackRerouteDescription, flags_ui::kOsIos, + FEATURE_VALUE_TYPE(kWebFeedFeedbackReroute)}, }; bool SkipConditionalFeatureEntry(const flags_ui::FeatureEntry& entry) {
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc index aaa7f89..d09e4c8a 100644 --- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc +++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
@@ -274,6 +274,11 @@ const char kEnableAutofillAddressSavePromptDescription[] = "Enable the Autofill address save prompts."; +const char kEnableBookmarksAccountStorageName[] = + "Enable Bookmarks Account Storage"; +const char kEnableBookmarksAccountStorageDescription[] = + "Enable bookmarks account storage and related UI features."; + const char kEnableCBDSignOutName[] = "Enable Clear Browsing Data Sign-out"; const char kEnableCBDSignOutDescription[] = "Offer signed-in user to sign-out from Clear Browsing Data settings."; @@ -971,6 +976,12 @@ const char kWalletServiceUseSandboxDescription[] = "Uses the sandbox service for Google Payments API calls."; +const char kWebFeedFeedbackRerouteName[] = + "Send discover feed feedback to a updated destination"; +const char kWebFeedFeedbackRerouteDescription[] = + "Directs discover feed feedback to a new target for better handling of the" + "feedback reports."; + const char kWebPageDefaultZoomFromDynamicTypeName[] = "Use dynamic type size for default text zoom level"; const char kWebPageDefaultZoomFromDynamicTypeDescription[] =
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h index fd1894c..64efe23 100644 --- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h +++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
@@ -206,6 +206,11 @@ extern const char kDetectMainThreadFreezeName[]; extern const char kDetectMainThreadFreezeDescription[]; +// Title and description for the flag to enable the bookmarks account storage +// and related UI features. +extern const char kEnableBookmarksAccountStorageName[]; +extern const char kEnableBookmarksAccountStorageDescription[]; + // Title and description for the flag to enable checking feed visibility on // attention log start. extern const char kEnableCheckVisibilityOnAttentionLogStartName[]; @@ -851,6 +856,11 @@ extern const char kWalletServiceUseSandboxName[]; extern const char kWalletServiceUseSandboxDescription[]; +// Title and description for the flag to control whether to send discover +// feedback to a new product destination +extern const char kWebFeedFeedbackRerouteName[]; +extern const char kWebFeedFeedbackRerouteDescription[]; + // Title and description for the flag to tie the default text zoom level to // the dynamic type setting. extern const char kWebPageDefaultZoomFromDynamicTypeName[];
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm index 8ab8118..c3a3e797 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm
@@ -204,7 +204,7 @@ #pragma mark - ContentSuggestionsViewControllerAudience -- (void)viewDidDisappear { +- (void)viewWillDisappear { // Start no longer showing self.contentSuggestionsMediator.showingStartSurface = NO; DiscoverFeedServiceFactory::GetForBrowserState(
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm index 1676f64f..28733e6 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm
@@ -351,10 +351,10 @@ } } -- (void)viewDidDisappear:(BOOL)animated { - [super viewDidDisappear:animated]; +- (void)viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; if (ShouldShowReturnToMostRecentTabForStartSurface()) { - [self.audience viewDidDisappear]; + [self.audience viewWillDisappear]; } }
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller_audience.h b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller_audience.h index 1464d685..8931ff5 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller_audience.h +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller_audience.h
@@ -8,8 +8,8 @@ // Audience for the ContentSuggestions, getting informations from it. @protocol ContentSuggestionsViewControllerAudience -// Notifies the audience of the UIKit viewDidDisappear: callback. -- (void)viewDidDisappear; +// Notifies the audience of the UIKit viewWillDisappear: callback. +- (void)viewWillDisappear; // Notifies the audience that the Return to Recent Tab tile has been added. - (void)returnToRecentTabWasAdded;
diff --git a/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm b/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm index eaa4102..ab3b414c 100644 --- a/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm +++ b/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm
@@ -536,6 +536,54 @@ } } +// Tests that the pull to refresh (iphone) or the refresh button (ipad) lands +// the user on the top of the NTP even with a previously saved scroll position. +- (void)testReload { + // Scroll to have a position to restored. + [[EarlGrey selectElementWithMatcher:chrome_test_util::NTPCollectionView()] + performAction:grey_swipeFastInDirection(kGREYDirectionUp)]; + + // Save the position before navigating. + UICollectionView* collectionView = [NewTabPageAppInterface collectionView]; + CGFloat previousPosition = collectionView.contentOffset.y; + + // Navigate and come back. + self.testServer->RegisterRequestHandler( + base::BindRepeating(&StandardResponse)); + GREYAssertTrue(self.testServer->Start(), @"Test server failed to start."); + const GURL pageURL = self.testServer->GetURL(kPageURL); + + [ChromeEarlGrey loadURL:pageURL]; + [ChromeEarlGrey waitForWebStateContainingText:kPageLoadedString]; + [ChromeEarlGrey goBack]; + + // Check that the new position is the same. + GREYAssertEqual(previousPosition, collectionView.contentOffset.y, + @"NTP is not at the same position."); + + if ([ChromeEarlGrey isIPadIdiom]) { + // Have to scroll up to the top since tapping on reload button does not + // automatically scroll to the top when feed is off or if feed returns no + // contents (e.g. upstream bots). TODO(crbug.com/1406940): Look into why the + // Feed only scrolls up when there is content. + [[EarlGrey selectElementWithMatcher:chrome_test_util::NTPCollectionView()] + performAction:grey_scrollToContentEdge(kGREYContentEdgeTop)]; + // Tap on reload button. + [[EarlGrey selectElementWithMatcher:chrome_test_util::ReloadButton()] + performAction:grey_tap()]; + } else { + // Get back to the top of the page and then pull down to trigger Pull To + // Refresh + [[EarlGrey selectElementWithMatcher:chrome_test_util::NTPCollectionView()] + performAction:grey_scrollToContentEdge(kGREYContentEdgeTop)]; + [[EarlGrey selectElementWithMatcher:chrome_test_util::NTPCollectionView()] + performAction:grey_swipeSlowInDirection(kGREYDirectionDown)]; + } + [ChromeEarlGreyUI waitForAppToIdle]; + [self + testNTPInitialPositionAndContent:[NewTabPageAppInterface collectionView]]; +} + // Tests that the position of the collection view is restored when navigating // back to the NTP. - (void)testPositionRestored {
diff --git a/ios/chrome/browser/ui/first_run/BUILD.gn b/ios/chrome/browser/ui/first_run/BUILD.gn index 7b94e2b0..76eb62a8 100644 --- a/ios/chrome/browser/ui/first_run/BUILD.gn +++ b/ios/chrome/browser/ui/first_run/BUILD.gn
@@ -83,7 +83,7 @@ "//ios/chrome/browser/ui/first_run/default_browser", "//ios/chrome/browser/ui/first_run/signin", "//ios/chrome/browser/ui/first_run/tangible_sync", - "//ios/chrome/browser/ui/first_run/welcome", + "//ios/chrome/browser/ui/first_run/tos", "//ios/chrome/browser/ui/screen:screen_provider", "//ios/chrome/browser/ui/screen:screen_type", "//ios/chrome/browser/ui/settings/resources:enterprise_icon",
diff --git a/ios/chrome/browser/ui/first_run/resources/welcome_screen_banner.imageset/Contents.json b/ios/chrome/browser/ui/first_run/resources/welcome_screen_banner.imageset/Contents.json deleted file mode 100644 index bb15c9bd..0000000 --- a/ios/chrome/browser/ui/first_run/resources/welcome_screen_banner.imageset/Contents.json +++ /dev/null
@@ -1,40 +0,0 @@ -{ - "images" : [ - { - "filename" : "welcome_screen_banner_light@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "filename" : "welcome_screen_banner_dark@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "welcome_screen_banner_light@3x.png", - "idiom" : "universal", - "scale" : "3x" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "filename" : "welcome_screen_banner_dark@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} \ No newline at end of file
diff --git a/ios/chrome/browser/ui/first_run/resources/welcome_screen_banner.imageset/welcome_screen_banner_dark@2x.png b/ios/chrome/browser/ui/first_run/resources/welcome_screen_banner.imageset/welcome_screen_banner_dark@2x.png deleted file mode 100644 index 1d18224..0000000 --- a/ios/chrome/browser/ui/first_run/resources/welcome_screen_banner.imageset/welcome_screen_banner_dark@2x.png +++ /dev/null Binary files differ
diff --git a/ios/chrome/browser/ui/first_run/resources/welcome_screen_banner.imageset/welcome_screen_banner_dark@3x.png b/ios/chrome/browser/ui/first_run/resources/welcome_screen_banner.imageset/welcome_screen_banner_dark@3x.png deleted file mode 100644 index 46d7045..0000000 --- a/ios/chrome/browser/ui/first_run/resources/welcome_screen_banner.imageset/welcome_screen_banner_dark@3x.png +++ /dev/null Binary files differ
diff --git a/ios/chrome/browser/ui/first_run/resources/welcome_screen_banner.imageset/welcome_screen_banner_light@2x.png b/ios/chrome/browser/ui/first_run/resources/welcome_screen_banner.imageset/welcome_screen_banner_light@2x.png deleted file mode 100644 index f33edf85..0000000 --- a/ios/chrome/browser/ui/first_run/resources/welcome_screen_banner.imageset/welcome_screen_banner_light@2x.png +++ /dev/null Binary files differ
diff --git a/ios/chrome/browser/ui/first_run/resources/welcome_screen_banner.imageset/welcome_screen_banner_light@3x.png b/ios/chrome/browser/ui/first_run/resources/welcome_screen_banner.imageset/welcome_screen_banner_light@3x.png deleted file mode 100644 index 76319c9..0000000 --- a/ios/chrome/browser/ui/first_run/resources/welcome_screen_banner.imageset/welcome_screen_banner_light@3x.png +++ /dev/null Binary files differ
diff --git a/ios/chrome/browser/ui/first_run/signin/BUILD.gn b/ios/chrome/browser/ui/first_run/signin/BUILD.gn index fcd2cbc..4de89fd8 100644 --- a/ios/chrome/browser/ui/first_run/signin/BUILD.gn +++ b/ios/chrome/browser/ui/first_run/signin/BUILD.gn
@@ -32,8 +32,8 @@ "//ios/chrome/browser/ui/first_run:constants", "//ios/chrome/browser/ui/first_run:screen_delegate", "//ios/chrome/browser/ui/first_run:utils", + "//ios/chrome/browser/ui/first_run/tos", "//ios/chrome/browser/ui/first_run/uma", - "//ios/chrome/browser/ui/first_run/welcome", ] }
diff --git a/ios/chrome/browser/ui/first_run/signin/signin_screen_coordinator.mm b/ios/chrome/browser/ui/first_run/signin/signin_screen_coordinator.mm index e83b816..8ef0410 100644 --- a/ios/chrome/browser/ui/first_run/signin/signin_screen_coordinator.mm +++ b/ios/chrome/browser/ui/first_run/signin/signin_screen_coordinator.mm
@@ -29,8 +29,8 @@ #import "ios/chrome/browser/ui/first_run/signin/signin_screen_consumer.h" #import "ios/chrome/browser/ui/first_run/signin/signin_screen_mediator.h" #import "ios/chrome/browser/ui/first_run/signin/signin_screen_view_controller.h" +#import "ios/chrome/browser/ui/first_run/tos/tos_coordinator.h" #import "ios/chrome/browser/ui/first_run/uma/uma_coordinator.h" -#import "ios/chrome/browser/ui/first_run/welcome/tos_coordinator.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support."
diff --git a/ios/chrome/browser/ui/first_run/welcome/BUILD.gn b/ios/chrome/browser/ui/first_run/tos/BUILD.gn similarity index 62% rename from ios/chrome/browser/ui/first_run/welcome/BUILD.gn rename to ios/chrome/browser/ui/first_run/tos/BUILD.gn index 8015dfae..f3c5125d 100644 --- a/ios/chrome/browser/ui/first_run/welcome/BUILD.gn +++ b/ios/chrome/browser/ui/first_run/tos/BUILD.gn
@@ -2,28 +2,22 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -source_set("welcome") { +source_set("tos") { configs += [ "//build/config/compiler:enable_arc" ] sources = [ "tos_coordinator.h", "tos_coordinator.mm", ] deps = [ - ":welcome_ui", + ":tos_ui", "//base", - "//components/metrics", "//components/strings", "//ios/chrome/app/strings", "//ios/chrome/browser/browser_state", - "//ios/chrome/browser/first_run", "//ios/chrome/browser/main:public", "//ios/chrome/browser/ui/alert_coordinator", "//ios/chrome/browser/ui/commands", - "//ios/chrome/browser/ui/commands", "//ios/chrome/browser/ui/coordinators:chrome_coordinators", - "//ios/chrome/browser/ui/first_run:field_trial", - "//ios/chrome/browser/ui/first_run:screen_delegate", - "//ios/chrome/browser/ui/first_run:utils", "//ios/chrome/browser/ui/first_run/uma", "//ios/chrome/browser/ui/util:terms_util", "//ios/web/common:web_view_creation_util", @@ -32,7 +26,7 @@ frameworks = [ "UIKit.framework" ] } -source_set("welcome_ui") { +source_set("tos_ui") { configs += [ "//build/config/compiler:enable_arc" ] sources = [ "tos_view_controller.h", @@ -40,24 +34,12 @@ ] deps = [ "//base", - "//components/metrics", - "//components/prefs", - "//components/web_resource", "//ios/chrome/app/strings", - "//ios/chrome/browser/application_context", - "//ios/chrome/browser/policy:policy_util", "//ios/chrome/browser/ui/commands", - "//ios/chrome/browser/ui/first_run:constants", - "//ios/chrome/browser/ui/first_run:field_trial", - "//ios/chrome/browser/ui/first_run:utils", - "//ios/chrome/browser/ui/first_run/uma", - "//ios/chrome/browser/ui/util", "//ios/chrome/common:string_util", "//ios/chrome/common/ui/colors", - "//ios/chrome/common/ui/promo_style", "//ios/chrome/common/ui/util", "//ui/base", - "//url", ] frameworks = [ "UIKit.framework" ] } @@ -67,7 +49,7 @@ testonly = true sources = [ "tos_unittest.mm" ] deps = [ - ":welcome", + ":tos", "//testing/gtest", "//third_party/ocmock", ]
diff --git a/ios/chrome/browser/ui/first_run/welcome/tos_coordinator.h b/ios/chrome/browser/ui/first_run/tos/tos_coordinator.h similarity index 61% rename from ios/chrome/browser/ui/first_run/welcome/tos_coordinator.h rename to ios/chrome/browser/ui/first_run/tos/tos_coordinator.h index 4e7ae5f3..df4bde70 100644 --- a/ios/chrome/browser/ui/first_run/welcome/tos_coordinator.h +++ b/ios/chrome/browser/ui/first_run/tos/tos_coordinator.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_CHROME_BROWSER_UI_FIRST_RUN_WELCOME_TOS_COORDINATOR_H_ -#define IOS_CHROME_BROWSER_UI_FIRST_RUN_WELCOME_TOS_COORDINATOR_H_ +#ifndef IOS_CHROME_BROWSER_UI_FIRST_RUN_TOS_TOS_COORDINATOR_H_ +#define IOS_CHROME_BROWSER_UI_FIRST_RUN_TOS_TOS_COORDINATOR_H_ #import "ios/chrome/browser/ui/coordinators/chrome_coordinator.h" @@ -12,4 +12,4 @@ @end -#endif // IOS_CHROME_BROWSER_UI_FIRST_RUN_WELCOME_TOS_COORDINATOR_H_ +#endif // IOS_CHROME_BROWSER_UI_FIRST_RUN_TOS_TOS_COORDINATOR_H_
diff --git a/ios/chrome/browser/ui/first_run/welcome/tos_coordinator.mm b/ios/chrome/browser/ui/first_run/tos/tos_coordinator.mm similarity index 97% rename from ios/chrome/browser/ui/first_run/welcome/tos_coordinator.mm rename to ios/chrome/browser/ui/first_run/tos/tos_coordinator.mm index 08a7b34a..26e833b2 100644 --- a/ios/chrome/browser/ui/first_run/welcome/tos_coordinator.mm +++ b/ios/chrome/browser/ui/first_run/tos/tos_coordinator.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/chrome/browser/ui/first_run/welcome/tos_coordinator.h" +#import "ios/chrome/browser/ui/first_run/tos/tos_coordinator.h" #import <WebKit/WebKit.h> @@ -14,7 +14,7 @@ #import "ios/chrome/browser/ui/alert_coordinator/alert_coordinator.h" #import "ios/chrome/browser/ui/commands/command_dispatcher.h" #import "ios/chrome/browser/ui/commands/tos_commands.h" -#import "ios/chrome/browser/ui/first_run/welcome/tos_view_controller.h" +#import "ios/chrome/browser/ui/first_run/tos/tos_view_controller.h" #import "ios/chrome/browser/ui/util/terms_util.h" #import "ios/chrome/grit/ios_strings.h" #import "ios/web/common/web_view_creation_util.h"
diff --git a/ios/chrome/browser/ui/first_run/welcome/tos_unittest.mm b/ios/chrome/browser/ui/first_run/tos/tos_unittest.mm similarity index 96% rename from ios/chrome/browser/ui/first_run/welcome/tos_unittest.mm rename to ios/chrome/browser/ui/first_run/tos/tos_unittest.mm index 58e3608..f83e8c6 100644 --- a/ios/chrome/browser/ui/first_run/welcome/tos_unittest.mm +++ b/ios/chrome/browser/ui/first_run/tos/tos_unittest.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/chrome/browser/ui/first_run/welcome/tos_coordinator.h" +#import "ios/chrome/browser/ui/first_run/tos/tos_coordinator.h" #import <WebKit/WebKit.h> #import <gtest/gtest.h>
diff --git a/ios/chrome/browser/ui/first_run/welcome/tos_view_controller.h b/ios/chrome/browser/ui/first_run/tos/tos_view_controller.h similarity index 72% rename from ios/chrome/browser/ui/first_run/welcome/tos_view_controller.h rename to ios/chrome/browser/ui/first_run/tos/tos_view_controller.h index e6b0671d..608ca80f 100644 --- a/ios/chrome/browser/ui/first_run/welcome/tos_view_controller.h +++ b/ios/chrome/browser/ui/first_run/tos/tos_view_controller.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_CHROME_BROWSER_UI_FIRST_RUN_WELCOME_TOS_VIEW_CONTROLLER_H_ -#define IOS_CHROME_BROWSER_UI_FIRST_RUN_WELCOME_TOS_VIEW_CONTROLLER_H_ +#ifndef IOS_CHROME_BROWSER_UI_FIRST_RUN_TOS_TOS_VIEW_CONTROLLER_H_ +#define IOS_CHROME_BROWSER_UI_FIRST_RUN_TOS_TOS_VIEW_CONTROLLER_H_ #import <UIKit/UIKit.h> @@ -23,4 +23,4 @@ @end -#endif // IOS_CHROME_BROWSER_UI_FIRST_RUN_WELCOME_TOS_VIEW_CONTROLLER_H_ +#endif // IOS_CHROME_BROWSER_UI_FIRST_RUN_TOS_TOS_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/first_run/welcome/tos_view_controller.mm b/ios/chrome/browser/ui/first_run/tos/tos_view_controller.mm similarity index 96% rename from ios/chrome/browser/ui/first_run/welcome/tos_view_controller.mm rename to ios/chrome/browser/ui/first_run/tos/tos_view_controller.mm index 2099fed..729370c2 100644 --- a/ios/chrome/browser/ui/first_run/welcome/tos_view_controller.mm +++ b/ios/chrome/browser/ui/first_run/tos/tos_view_controller.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/chrome/browser/ui/first_run/welcome/tos_view_controller.h" +#import "ios/chrome/browser/ui/first_run/tos/tos_view_controller.h" #import <WebKit/WebKit.h>
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.mm b/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.mm index faf6fba..fc5b64bac 100644 --- a/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.mm +++ b/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.mm
@@ -453,6 +453,10 @@ if (self.browser->GetBrowserState()->IsOffTheRecord()) { return; } + // Call this before RefreshFeed() to ensure some NTP state configs are reset + // before callbacks in repsonse to a feed refresh are called, ensuring the NTP + // returns to a state at the top of the surface upon refresh. + [self.NTPViewController resetStateUponReload]; self.discoverFeedService->RefreshFeed(/*feed_visible=*/true); [self reloadContentSuggestions]; }
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_feature.h b/ios/chrome/browser/ui/ntp/new_tab_page_feature.h index 0eca0d7..d365a857 100644 --- a/ios/chrome/browser/ui/ntp/new_tab_page_feature.h +++ b/ios/chrome/browser/ui/ntp/new_tab_page_feature.h
@@ -53,6 +53,9 @@ // Feature flag to enable synthentic capabilities. BASE_DECLARE_FEATURE(kEnableFeedSyntheticCapabilities); +// Feature flag to enable sending discover feedback to an updated target +BASE_DECLARE_FEATURE(kWebFeedFeedbackReroute); + #pragma mark - Feature parameters // A parameter to indicate whether Reconstructed Templates is enabled for static @@ -150,4 +153,7 @@ // from the server, or returns the default value. int FollowingFeedHeaderHeight(); +// YES if discover feedback is going to be sent to the updated target +bool IsWebFeedFeedbackRerouteEnabled(); + #endif // IOS_CHROME_BROWSER_UI_NTP_NEW_TAB_PAGE_FEATURE_H_
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_feature.mm b/ios/chrome/browser/ui/ntp/new_tab_page_feature.mm index e6d81af..2082d449 100644 --- a/ios/chrome/browser/ui/ntp/new_tab_page_feature.mm +++ b/ios/chrome/browser/ui/ntp/new_tab_page_feature.mm
@@ -63,6 +63,10 @@ "EnableFeedSyntheticCapabilities", base::FEATURE_DISABLED_BY_DEFAULT); +BASE_FEATURE(kWebFeedFeedbackReroute, + "WebFeedFeedbackReroute", + base::FEATURE_ENABLED_BY_DEFAULT); + #pragma mark - Feature parameters const char kDiscoverFeedSRSReconstructedTemplatesEnabled[] = @@ -175,3 +179,7 @@ kOverrideFeedHeaderHeight, defaultWebChannelsHeaderHeight); } + +bool IsWebFeedFeedbackRerouteEnabled() { + return base::FeatureList::IsEnabled(kWebFeedFeedbackReroute); +}
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_view_controller.h b/ios/chrome/browser/ui/ntp/new_tab_page_view_controller.h index c0fe8d3f..71ea13fa 100644 --- a/ios/chrome/browser/ui/ntp/new_tab_page_view_controller.h +++ b/ios/chrome/browser/ui/ntp/new_tab_page_view_controller.h
@@ -114,6 +114,9 @@ // Resets hierarchy of views and view controllers. - (void)resetViewHierarchy; +// Resets any relevant NTP states due for a content reload. +- (void)resetStateUponReload; + // Sets the NTP collection view's scroll position to `contentOffset`, unless it // is beyond the top of the feed. In that case, sets the scroll position to the // top of the feed.
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_view_controller.mm b/ios/chrome/browser/ui/ntp/new_tab_page_view_controller.mm index 2077bec1..4c93c64 100644 --- a/ios/chrome/browser/ui/ntp/new_tab_page_view_controller.mm +++ b/ios/chrome/browser/ui/ntp/new_tab_page_view_controller.mm
@@ -237,6 +237,10 @@ // can open a new tab while an NTP is currently visible. `-viewWillAppear:` is // called before the offset can be saved, so `-setContentOffsetToTop` will // reset any scrolled position. + // It is NOT safe to reset `hasSavedOffsetFromPreviousScrollState` to NO here + // because -updateHeightAboveFeedAndScrollToTopIfNeeded calls from async + // updates to the Content Suggestions (i.e. MVT, Doodle) can happen after + // this. if (!self.feedVisible) { if (self.hasSavedOffsetFromPreviousScrollState) { [self setContentOffset:self.savedScrollOffset]; @@ -505,6 +509,10 @@ [self.viewControllersAboveFeed removeAllObjects]; } +- (void)resetStateUponReload { + self.hasSavedOffsetFromPreviousScrollState = NO; +} + - (void)setContentOffsetToTopOfFeed:(CGFloat)contentOffset { if (contentOffset < [self offsetWhenScrolledIntoFeed]) { [self setContentOffset:contentOffset]; @@ -546,6 +554,10 @@ // Updating insets can influence contentOffset, so update saved scroll state // after it. This handles what the starting offset be with the feed enabled, // `-viewWillAppear:` handles when the feed is not enabled. + // It is NOT safe to reset `hasSavedOffsetFromPreviousScrollState` to NO here + // because -updateHeightAboveFeedAndScrollToTopIfNeeded calls from async + // updates to the Content Suggestions (i.e. MVT, Doodle) can happen after + // this. if (self.hasSavedOffsetFromPreviousScrollState) { [self setContentOffset:self.savedScrollOffset]; } @@ -582,12 +594,12 @@ if ([self.ntpContentDelegate isContentHeaderSticky]) { [self setInitialFeedHeaderConstraints]; } - // Reset here since none of the view lifecycle callbacks are called reliably - // to be able to be used (it seems) (i.e. switching between NTPs where there - // is saved scroll state in the destination tab). If the content offset is - // being set to the top, it is safe to assume this can be set to NO. Being - // called before setSavedContentOffset: is no problem since then it will be - // subsequently overriden to YES. + // Reset here since none of the view lifecycle callbacks (e.g. + // viewDidDisappear) can be reliably used (it seems) (i.e. switching between + // NTPs where there is saved scroll state in the destination tab). If the + // content offset is being set to the top, it is safe to assume this can be + // set to NO. Being called before setSavedContentOffset: is no problem since + // then it will be subsequently overriden to YES. self.hasSavedOffsetFromPreviousScrollState = NO; } @@ -693,6 +705,9 @@ } - (void)scrollViewWillBeginDragging:(UIScrollView*)scrollView { + // User has interacted with the surface, so it is safe to assume that a saved + // scroll position can now be overriden. + self.hasSavedOffsetFromPreviousScrollState = NO; [self.overscrollActionsController scrollViewWillBeginDragging:scrollView]; [self.panGestureHandler scrollViewWillBeginDragging:scrollView]; self.scrollStartPosition = scrollView.contentOffset.y; @@ -742,6 +757,13 @@ // Prevent scrolling back to pre-focus state, making sure we don't have // two scrolling animations running at the same time. self.collectionShiftingOffset = 0; + // Reset here since none of the view lifecycle callbacks are called reliably + // to be able to be used (it seems) (i.e. switching between NTPs where there + // is saved scroll state in the destination tab). If the content offset is + // being set to the top, it is safe to assume this can be set to NO. Being + // called before setSavedContentOffset: is no problem since then it will be + // subsequently overriden to YES. + self.hasSavedOffsetFromPreviousScrollState = NO; // Unfocus omnibox without scrolling back. [self unfocusOmnibox]; return YES;
diff --git a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_destination_view.swift b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_destination_view.swift index f012759..a6174f4 100644 --- a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_destination_view.swift +++ b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_destination_view.swift
@@ -145,7 +145,7 @@ .frame(width: Dimensions.newLabelBadgeWidth, height: Dimensions.newLabelBadgeWidth) .offset(x: newBadgeOffsetX, y: newBadgeOffsetY) .overlay { - if let newLabelString = L10NUtils.string( + if let newLabelString = L10NUtils.stringWithFixup( forMessageId: IDS_IOS_NEW_LABEL_FEATURE_BADGE) { Text(newLabelString)
diff --git a/ios/chrome/browser/ui/post_restore_signin/features.cc b/ios/chrome/browser/ui/post_restore_signin/features.cc index 8a1a1eb..d20df0d 100644 --- a/ios/chrome/browser/ui/post_restore_signin/features.cc +++ b/ios/chrome/browser/ui/post_restore_signin/features.cc
@@ -12,17 +12,14 @@ BASE_FEATURE(kIOSNewPostRestoreExperience, "IOSNewPostRestoreExperience", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); const char kIOSNewPostRestoreExperienceParam[] = "ios-new-post-restore-experience"; PostRestoreSignInType CurrentPostRestoreSignInType() { - if (base::FeatureList::IsEnabled(kIOSNewPostRestoreExperience)) - return base::GetFieldTrialParamByFeatureAsBool( - kIOSNewPostRestoreExperience, kIOSNewPostRestoreExperienceParam, - false) - ? PostRestoreSignInType::kAlert - : PostRestoreSignInType::kFullscreen; + if (base::FeatureList::IsEnabled(kIOSNewPostRestoreExperience)) { + return PostRestoreSignInType::kAlert; + } return PostRestoreSignInType::kDisabled; }
diff --git a/ios/chrome/browser/ui/post_restore_signin/post_restore_signin_provider_unittest.mm b/ios/chrome/browser/ui/post_restore_signin/post_restore_signin_provider_unittest.mm index 7844072..905db27 100644 --- a/ios/chrome/browser/ui/post_restore_signin/post_restore_signin_provider_unittest.mm +++ b/ios/chrome/browser/ui/post_restore_signin/post_restore_signin_provider_unittest.mm
@@ -57,11 +57,6 @@ provider_.handler = mock_handler_; } - void EnableFeatureVariationFullscreen() { - scoped_feature_list_.InitAndEnableFeature( - post_restore_signin::features::kIOSNewPostRestoreExperience); - } - void EnableFeatureVariationAlert() { scoped_feature_list_.InitWithFeaturesAndParameters( {base::test::FeatureRefAndParams( @@ -77,12 +72,6 @@ PostRestoreSignInProvider* provider_; }; -TEST_F(PostRestoreSignInProviderTest, hasIdentifierFullscreen) { - EnableFeatureVariationFullscreen(); - EXPECT_EQ(provider_.config.identifier, - promos_manager::Promo::PostRestoreSignInFullscreen); -} - TEST_F(PostRestoreSignInProviderTest, hasIdentifierAlert) { EnableFeatureVariationAlert(); EXPECT_EQ(provider_.config.identifier, @@ -90,7 +79,7 @@ } TEST_F(PostRestoreSignInProviderTest, standardPromoAlertDefaultAction) { - EnableFeatureVariationFullscreen(); + EnableFeatureVariationAlert(); SetupMockHandler(); OCMExpect([mock_handler_ showSignin:[OCMArg any]]); [provider_ standardPromoAlertDefaultAction]; @@ -98,12 +87,12 @@ } TEST_F(PostRestoreSignInProviderTest, title) { - EnableFeatureVariationFullscreen(); + EnableFeatureVariationAlert(); EXPECT_TRUE([[provider_ title] isEqualToString:@"Chrome is Signed Out"]); } TEST_F(PostRestoreSignInProviderTest, message) { - EnableFeatureVariationFullscreen(); + EnableFeatureVariationAlert(); NSString* expected; if (ui::GetDeviceFormFactor() == ui::DEVICE_FORM_FACTOR_TABLET) { expected = @"You were signed out of your account person@example.org as " @@ -131,7 +120,7 @@ } TEST_F(PostRestoreSignInProviderTest, viewController) { - EnableFeatureVariationFullscreen(); + EnableFeatureVariationAlert(); EXPECT_TRUE(provider_.viewController != nil); }
diff --git a/ios/chrome/browser/ui/promos_manager/promos_manager_coordinator_unittest.h b/ios/chrome/browser/ui/promos_manager/promos_manager_coordinator_unittest.h index 6ca687b..c872fd6 100644 --- a/ios/chrome/browser/ui/promos_manager/promos_manager_coordinator_unittest.h +++ b/ios/chrome/browser/ui/promos_manager/promos_manager_coordinator_unittest.h
@@ -14,6 +14,7 @@ #import "ios/chrome/browser/main/test_browser.h" #import "ios/chrome/browser/prefs/pref_names.h" #import "ios/chrome/browser/ui/promos_manager/promos_manager_coordinator.h" +#import "ios/chrome/test/ios_chrome_scoped_testing_local_state.h" #import "ios/chrome/test/scoped_key_window.h" #import "testing/platform_test.h" @@ -29,7 +30,7 @@ // Create pref registry for tests. void CreatePrefs(); - std::unique_ptr<TestingPrefServiceSimple> local_state_; + IOSChromeScopedTestingLocalState local_state_; base::test::ScopedFeatureList scoped_feature_list_; PromosManagerCoordinator* coordinator_; base::test::TaskEnvironment task_environment_;
diff --git a/ios/chrome/browser/ui/promos_manager/promos_manager_coordinator_unittest.mm b/ios/chrome/browser/ui/promos_manager/promos_manager_coordinator_unittest.mm index ef20970..f6dd338 100644 --- a/ios/chrome/browser/ui/promos_manager/promos_manager_coordinator_unittest.mm +++ b/ios/chrome/browser/ui/promos_manager/promos_manager_coordinator_unittest.mm
@@ -39,25 +39,11 @@ PromosManagerCoordinatorTest::~PromosManagerCoordinatorTest() {} void PromosManagerCoordinatorTest::CreatePromosManagerCoordinator() { - CreatePrefs(); - coordinator_ = [[PromosManagerCoordinator alloc] initWithBaseViewController:view_controller_ browser:browser_.get()]; } -// Create pref registry for tests. -void PromosManagerCoordinatorTest::CreatePrefs() { - local_state_ = std::make_unique<TestingPrefServiceSimple>(); - - local_state_->registry()->RegisterListPref( - prefs::kIosPromosManagerImpressions); - local_state_->registry()->RegisterListPref( - prefs::kIosPromosManagerActivePromos); - local_state_->registry()->RegisterListPref( - prefs::kIosPromosManagerSingleDisplayActivePromos); -} - // Tests a provider's standardPromoDismissAction is called when a // viewController's dismiss button is pressed. TEST_F(PromosManagerCoordinatorTest,
diff --git a/ios/chrome/browser/ui/settings/password/password_checkup/BUILD.gn b/ios/chrome/browser/ui/settings/password/password_checkup/BUILD.gn index a757337..bba2b97d 100644 --- a/ios/chrome/browser/ui/settings/password/password_checkup/BUILD.gn +++ b/ios/chrome/browser/ui/settings/password/password_checkup/BUILD.gn
@@ -36,6 +36,14 @@ ] } +source_set("password_checkup_constants") { + configs += [ "//build/config/compiler:enable_arc" ] + sources = [ + "password_checkup_constants.h", + "password_checkup_constants.mm", + ] +} + source_set("unit_tests") { configs += [ "//build/config/compiler:enable_arc" ] testonly = true
diff --git a/ios/chrome/browser/ui/settings/password/password_checkup/password_checkup_constants.h b/ios/chrome/browser/ui/settings/password/password_checkup/password_checkup_constants.h new file mode 100644 index 0000000..ec34f3a9 --- /dev/null +++ b/ios/chrome/browser/ui/settings/password/password_checkup/password_checkup_constants.h
@@ -0,0 +1,18 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_CHECKUP_PASSWORD_CHECKUP_CONSTANTS_H_ +#define IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_CHECKUP_PASSWORD_CHECKUP_CONSTANTS_H_ + +namespace password_manager { + +// URL to the help center article about changing unsafe passwords. +extern const char kPasswordManagerHelpCenterChangeUnsafePasswordsURL[]; + +// URL to the help center article about creating strong passwords. +extern const char kPasswordManagerHelpCenterCreateStrongPasswordsURL[]; + +} // namespace password_manager + +#endif // IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_CHECKUP_PASSWORD_CHECKUP_CONSTANTS_H_
diff --git a/ios/chrome/browser/ui/settings/password/password_checkup/password_checkup_constants.mm b/ios/chrome/browser/ui/settings/password/password_checkup/password_checkup_constants.mm new file mode 100644 index 0000000..d12d634b --- /dev/null +++ b/ios/chrome/browser/ui/settings/password/password_checkup/password_checkup_constants.mm
@@ -0,0 +1,19 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/settings/password/password_checkup/password_checkup_constants.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace password_manager { + +const char kPasswordManagerHelpCenterChangeUnsafePasswordsURL[] = + "https://support.google.com/accounts/answer/9457609"; + +const char kPasswordManagerHelpCenterCreateStrongPasswordsURL[] = + "https://support.google.com/accounts/answer/32040"; + +} // namespace password_manager
diff --git a/ios/chrome/browser/ui/start_surface/start_surface_egtest.mm b/ios/chrome/browser/ui/start_surface/start_surface_egtest.mm index ca7acbc..1488a02e 100644 --- a/ios/chrome/browser/ui/start_surface/start_surface_egtest.mm +++ b/ios/chrome/browser/ui/start_surface/start_surface_egtest.mm
@@ -146,6 +146,50 @@ assertWithMatcher:grey_notVisible()]; } +// Tests that navigating to a page and restarting upon cold start, an NTP page +// is opened with the Return to Recent Tab tile. Then, subsequently opening a +// new tab removes the Return To Recent Tab tile from both the new tab's NTP and +// the Start NTP. +- (void)testOpeningNewTabRemovesReturnToRecenTabTile { + GREYAssertTrue(self.testServer->Start(), @"Test server failed to start."); + const GURL destinationUrl = self.testServer->GetURL("/pony.html"); + [ChromeEarlGrey loadURL:destinationUrl]; + + [[AppLaunchManager sharedManager] backgroundAndForegroundApp]; + + // Give time for NTP to be fully loaded so all elements are accessible. + base::test::ios::SpinRunLoopWithMinDelay(base::Seconds(0.5)); + GREYAssertEqual([ChromeEarlGrey mainTabCount], 2, + @"Two tabs were expected to be open"); + // Assert NTP is visible by checking that the fake omnibox is here. + [[EarlGrey selectElementWithMatcher:chrome_test_util::FakeOmnibox()] + assertWithMatcher:grey_sufficientlyVisible()]; + [[EarlGrey + selectElementWithMatcher:grey_accessibilityLabel(l10n_util::GetNSString( + IDS_IOS_RETURN_TO_RECENT_TAB_TITLE))] + assertWithMatcher:grey_sufficientlyVisible()]; + + [ChromeEarlGreyUI openNewTab]; + [ChromeEarlGreyUI waitForAppToIdle]; + + // Assert that Return to Recent Tab has been removed. + [[EarlGrey + selectElementWithMatcher:grey_accessibilityLabel(l10n_util::GetNSString( + IDS_IOS_RETURN_TO_RECENT_TAB_TITLE))] + assertWithMatcher:grey_notVisible()]; + + // Close current tab to go back to the previous Start NTP. + [ChromeEarlGrey closeCurrentTab]; + [[EarlGrey + selectElementWithMatcher:grey_accessibilityLabel(l10n_util::GetNSString( + IDS_IOS_RETURN_TO_RECENT_TAB_TITLE))] + assertWithMatcher:grey_notVisible()]; + [[EarlGrey selectElementWithMatcher:chrome_test_util::NTPLogo()] + assertWithMatcher:grey_sufficientlyVisible()]; + [[EarlGrey selectElementWithMatcher:chrome_test_util::FakeOmnibox()] + assertWithMatcher:grey_sufficientlyVisible()]; +} + // Tests that the Return To Recent Tab tile is removed after opening the tab // grid (i.e. switching away from the Start Surface). - (void)testReturnToRecenTabTileRemovedAfterOpeningTabGrid {
diff --git a/ios/chrome/browser/ui/webui/policy/BUILD.gn b/ios/chrome/browser/ui/webui/policy/BUILD.gn index 04b564b9..f4fe746 100644 --- a/ios/chrome/browser/ui/webui/policy/BUILD.gn +++ b/ios/chrome/browser/ui/webui/policy/BUILD.gn
@@ -22,6 +22,7 @@ "//components/prefs", "//components/strings", "//components/version_info", + "//components/version_ui", "//ios/chrome/app/strings", "//ios/chrome/browser/application_context", "//ios/chrome/browser/browser_state",
diff --git a/ios/chrome/browser/ui/webui/policy/policy_ui.mm b/ios/chrome/browser/ui/webui/policy/policy_ui.mm index b37b092..34fd334 100644 --- a/ios/chrome/browser/ui/webui/policy/policy_ui.mm +++ b/ios/chrome/browser/ui/webui/policy/policy_ui.mm
@@ -7,11 +7,18 @@ #import <memory> #import <string> +#import "base/json/json_writer.h" #import "components/grit/policy_resources.h" +#import "components/policy/core/common/policy_logger.h" +#import "components/strings/grit/components_chromium_strings.h" +#import "components/strings/grit/components_google_chrome_strings.h" #import "components/strings/grit/components_strings.h" +#import "components/version_info/version_info.h" +#import "components/version_ui/version_handler_helper.h" #import "ios/chrome/browser/browser_state/chrome_browser_state.h" #import "ios/chrome/browser/ui/webui/policy/policy_ui_handler.h" #import "ios/chrome/browser/url/chrome_url_constants.h" +#import "ios/chrome/grit/ios_chromium_strings.h" #import "ios/web/public/webui/web_ui_ios.h" #import "ios/web/public/webui/web_ui_ios_data_source.h" #import "ios/web/public/webui/web_ui_ios_message_handler.h" @@ -23,6 +30,19 @@ namespace { +// Returns the version information to be displayed on the chrome://policy/logs +// page. +base::Value::Dict GetVersionInfo() { + base::Value::Dict version_info; + + version_info.Set("revision", version_info::GetLastChange()); + version_info.Set("version", version_info::GetVersionNumber()); + version_info.Set("deviceOs", "iOS"); + version_info.Set("variations", version_ui::GetVariationsList()); + + return version_info; +} + web::WebUIIOSDataSource* CreatePolicyUIHtmlSource() { web::WebUIIOSDataSource* source = web::WebUIIOSDataSource::Create(kChromeUIPolicyHost); @@ -89,6 +109,20 @@ }; source->AddLocalizedStrings(kStrings); + + // Localized strings for chrome://policy/logs. + static constexpr webui::LocalizedString kPolicyLogsStrings[] = { + {"browserName", IDS_IOS_PRODUCT_NAME}, + {"exportLogsJSON", IDS_EXPORT_POLICY_LOGS_JSON}, + {"logsTitle", IDS_POLICY_LOGS_TITLE}, + {"os", IDS_VERSION_UI_OS}, + {"refreshLogs", IDS_REFRESH_POLICY_LOGS}, + {"revision", IDS_VERSION_UI_REVISION}, + {"versionInfoLabel", IDS_VERSION_INFO}, + {"variations", IDS_VERSION_UI_VARIATIONS}, + }; + source->AddLocalizedStrings(kPolicyLogsStrings); + source->UseStringsJs(); source->AddBoolean("hideExportButton", true); @@ -110,6 +144,21 @@ source->AddResourcePath("policy_table.js", IDR_POLICY_POLICY_TABLE_JS); source->AddResourcePath("status_box.html.js", IDR_POLICY_STATUS_BOX_HTML_JS); source->AddResourcePath("status_box.js", IDR_POLICY_STATUS_BOX_JS); + + source->AddBoolean( + "loggingEnabled", + policy::PolicyLogger::GetInstance()->IsPolicyLoggingEnabled()); + + if (policy::PolicyLogger::GetInstance()->IsPolicyLoggingEnabled()) { + std::string variations_json_value; + base::JSONWriter::Write(GetVersionInfo(), &variations_json_value); + source->AddString("versionInfo", variations_json_value); + } + source->AddResourcePath("logs/policy_logs.js", + IDR_POLICY_LOGS_POLICY_LOGS_JS); + source->AddResourcePath("logs/", IDR_POLICY_LOGS_POLICY_LOGS_HTML); + source->AddResourcePath("logs", IDR_POLICY_LOGS_POLICY_LOGS_HTML); + source->SetDefaultResource(IDR_POLICY_POLICY_HTML); source->EnableReplaceI18nInJS(); return source;
diff --git a/ios/chrome/browser/ui/webui/policy/policy_ui_handler.h b/ios/chrome/browser/ui/webui/policy/policy_ui_handler.h index c3c8d7af..46d820f9 100644 --- a/ios/chrome/browser/ui/webui/policy/policy_ui_handler.h +++ b/ios/chrome/browser/ui/webui/policy/policy_ui_handler.h
@@ -73,6 +73,10 @@ // Called to handle the "uploadReport" WebUI message. void HandleUploadReport(const base::Value::List& args); + // Called to handle the "getPolicyLogs" WebUI message from + // chrome://policy/logs. + void HandleGetPolicyLogs(const base::Value::List& args); + // Send information about the current policy values to the UI. For each policy // whose value has been set, dictionaries containing the value and additional // metadata are sent.
diff --git a/ios/chrome/browser/ui/webui/policy/policy_ui_handler.mm b/ios/chrome/browser/ui/webui/policy/policy_ui_handler.mm index 00b013a..ffb5055 100644 --- a/ios/chrome/browser/ui/webui/policy/policy_ui_handler.mm +++ b/ios/chrome/browser/ui/webui/policy/policy_ui_handler.mm
@@ -23,6 +23,7 @@ #import "components/policy/core/browser/webui/machine_level_user_cloud_policy_status_provider.h" #import "components/policy/core/browser/webui/policy_webui_constants.h" #import "components/policy/core/common/cloud/machine_level_user_cloud_policy_manager.h" +#import "components/policy/core/common/policy_logger.h" #import "components/policy/core/common/policy_map.h" #import "components/policy/core/common/policy_types.h" #import "components/policy/core/common/schema.h" @@ -143,6 +144,10 @@ web_ui()->RegisterMessageCallback( "uploadReport", base::BindRepeating(&PolicyUIHandler::HandleUploadReport, base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "getPolicyLogs", + base::BindRepeating(&PolicyUIHandler::HandleGetPolicyLogs, + base::Unretained(this))); } void PolicyUIHandler::HandleCopyPoliciesJson(const base::Value::List& args) { @@ -166,6 +171,12 @@ } } +void PolicyUIHandler::HandleGetPolicyLogs(const base::Value::List& args) { + DCHECK(policy::PolicyLogger::GetInstance()->IsPolicyLoggingEnabled()); + web_ui()->ResolveJavascriptCallback( + args[0], policy::PolicyLogger::GetInstance()->GetAsList()); +} + std::string PolicyUIHandler::GetPoliciesAsJson() { auto client = std::make_unique<PolicyConversionsClientIOS>( ChromeBrowserState::FromWebUIIOS(web_ui()));
diff --git a/ios/chrome/test/BUILD.gn b/ios/chrome/test/BUILD.gn index caa6de7..02958f5 100644 --- a/ios/chrome/test/BUILD.gn +++ b/ios/chrome/test/BUILD.gn
@@ -305,7 +305,7 @@ "//ios/chrome/browser/ui/elements:unit_tests", "//ios/chrome/browser/ui/first_run:unit_tests", "//ios/chrome/browser/ui/first_run:unit_tests", - "//ios/chrome/browser/ui/first_run/welcome:unit_tests", + "//ios/chrome/browser/ui/first_run/tos:unit_tests", "//ios/chrome/browser/ui/fullscreen:unit_tests", "//ios/chrome/browser/ui/gestures:unit_tests", "//ios/chrome/browser/ui/history:unit_tests",
diff --git a/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1 b/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1 index 7bb7715..97d0da03 100644 --- a/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1 +++ b/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1
@@ -1 +1 @@ -efd0ff2b5e680245106e57c8714734943c36d605 \ No newline at end of file +ab0ee9a3e269c2d77342afa0bae165eb2c4d402b \ No newline at end of file
diff --git a/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1 b/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1 index 9db977ebc..69dea7e 100644 --- a/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1 +++ b/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1
@@ -1 +1 @@ -c89a3d99eebb59ad82b08c4145a9beea4fcdad60 \ No newline at end of file +51bfb281a75f37c4f0ea5f97f9250d2234b4122f \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 index 323ae04..0013894 100644 --- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -99082e4c0f305f976eb90d262a7199c881400763 \ No newline at end of file +93da811cafe5edbe259490e615335f6d08a298a8 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 index b69b1db..41c7c8f 100644 --- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -885705a2c128d40b2d72cccfcfddbc061986c331 \ No newline at end of file +d28415407c0377fd7e7df061a8aeae86b3fdc310 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 index 117c1475..97600a1 100644 --- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -2004981c7aead5a0f4d94026eb9910b6c4948eae \ No newline at end of file +c5d41b90a2974132f5381e6ff0f7c8b9e53ba3ab \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 index 8221bae6..6016d475 100644 --- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -469371fa82805156f6b8d44ef8d4b0dd3b9e8994 \ No newline at end of file +f1103cf3238d881459fafddb662f54b751eea9e6 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1 index 737bf46a..dbd5cf7 100644 --- a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -81dc53bf9562ce374ceaaa5c1bb422bc98725252 \ No newline at end of file +0c9879c49c3eaddfc319d35d3e7fe62b678681ac \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1 index 77c6528..a20c192 100644 --- a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -25eeede3aa36dca1f0b3ed8fecfcca373ae6a823 \ No newline at end of file +6e742042ea7d88b18aa060cc37bae2718334393e \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 index 1a73aa94..248806f 100644 --- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -05ba9b14904557d07f85cea2730d9d77d71f3c7f \ No newline at end of file +61cfe27d1ab74f3316218a65b99f44eea2b75739 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 index db190252..8762b39 100644 --- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -1b8ef59cdefd6cb04fdf97b94b31e582e9c183be \ No newline at end of file +c85c5352816a426a732b37e380dfe37d6882e9e7 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 index abea713..3206171 100644 --- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -e73a0af6e9cda480c8776a84a439c0a8a5b72682 \ No newline at end of file +06772e6472ca18cb5a88fba1845012853a9e7e57 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 index 016bb73..a6239f20 100644 --- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -d79e8da3d490432c8e4e6a4fa3f25594dd0ada56 \ No newline at end of file +baf2ef72971470f8d47804f98ad7835d47f342e5 \ No newline at end of file
diff --git a/ios/web/common/features.h b/ios/web/common/features.h index fb06720c..2b92eb2 100644 --- a/ios/web/common/features.h +++ b/ios/web/common/features.h
@@ -82,6 +82,9 @@ // Feature flag to prevent navigation without user interaction. BASE_DECLARE_FEATURE(kPreventNavigationWithoutUserInteraction); +// Feature flag to enable Web Inspector support. +BASE_DECLARE_FEATURE(kEnableWebInspector); + // When true, user control for camera and/or microphone access should be // enabled. bool IsMediaPermissionsControlEnabled();
diff --git a/ios/web/common/features.mm b/ios/web/common/features.mm index e5e49bcc..12f32b15 100644 --- a/ios/web/common/features.mm +++ b/ios/web/common/features.mm
@@ -85,6 +85,10 @@ "PreventNavigationWithoutUserInteraction", base::FEATURE_ENABLED_BY_DEFAULT); +BASE_FEATURE(kEnableWebInspector, + "EnableWebInspector", + base::FEATURE_ENABLED_BY_DEFAULT); + bool IsMediaPermissionsControlEnabled() { if (@available(iOS 15, *)) { return base::FeatureList::IsEnabled(kMediaPermissionsControl);
diff --git a/ios/web/find_in_page/find_in_page_js_unittest.mm b/ios/web/find_in_page/find_in_page_js_unittest.mm index f61a6cb8..fe32964c 100644 --- a/ios/web/find_in_page/find_in_page_js_unittest.mm +++ b/ios/web/find_in_page/find_in_page_js_unittest.mm
@@ -10,6 +10,7 @@ #import "base/run_loop.h" #import "base/test/ios/wait_util.h" #import "base/time/time.h" +#import "base/values.h" #import "ios/web/find_in_page/find_in_page_constants.h" #import "ios/web/find_in_page/find_in_page_java_script_feature.h" #import "ios/web/js_messaging/java_script_feature_manager.h" @@ -23,6 +24,7 @@ #import "ios/web/public/web_state.h" #import "ios/web/web_state/ui/wk_web_view_configuration_provider.h" #import "testing/gtest_mac.h" +#import "third_party/abseil-cpp/absl/types/optional.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -282,7 +284,7 @@ base::BindOnce(^(const base::Value* result) { highlight_done = true; context_string = - result->FindKey(kSelectAndScrollResultContextString)->GetString(); + *result->GetDict().FindString(kSelectAndScrollResultContextString); }), kWaitForJSCompletionTimeout); ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{ @@ -328,7 +330,7 @@ base::BindOnce(^(const base::Value* result) { highlight_done = true; context_string = - result->FindKey(kSelectAndScrollResultContextString)->GetString(); + *result->GetDict().FindString(kSelectAndScrollResultContextString); }), kWaitForJSCompletionTimeout); ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{ @@ -348,7 +350,7 @@ content_world_, base::BindOnce(^(const base::Value* result) { highlight_done = true; context_string = - result->FindKey(kSelectAndScrollResultContextString)->GetString(); + *result->GetDict().FindString(kSelectAndScrollResultContextString); }), kWaitForJSCompletionTimeout); ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{ @@ -624,13 +626,15 @@ base::BindOnce(^(const base::Value* result) { ASSERT_TRUE(result); ASSERT_TRUE(result->is_dict()); - const base::Value* count = - result->FindKey(kSelectAndScrollResultMatches); - ASSERT_TRUE(count->is_double()); - ASSERT_EQ(2.0, count->GetDouble()); - const base::Value* index = result->FindKey(kSelectAndScrollResultIndex); - ASSERT_TRUE(index->is_double()); - ASSERT_EQ(0.0, index->GetDouble()); + const base::Value::Dict& result_dict = result->GetDict(); + const absl::optional<double> count = + result_dict.FindDouble(kSelectAndScrollResultMatches); + ASSERT_TRUE(count); + ASSERT_EQ(2.0, count.value()); + const absl::optional<double> index = + result_dict.FindDouble(kSelectAndScrollResultIndex); + ASSERT_TRUE(index); + ASSERT_EQ(0.0, index.value()); message_received = true; }), kWaitForJSCompletionTimeout); @@ -673,9 +677,11 @@ base::BindOnce(^(const base::Value* result) { ASSERT_TRUE(result); ASSERT_TRUE(result->is_dict()); - const base::Value* index = result->FindKey(kSelectAndScrollResultIndex); - ASSERT_TRUE(index->is_double()); - EXPECT_EQ(3.0, index->GetDouble()); + const base::Value::Dict& result_dict = result->GetDict(); + const absl::optional<double> index = + result_dict.FindDouble(kSelectAndScrollResultIndex); + ASSERT_TRUE(index); + EXPECT_EQ(3.0, index.value()); select_last_match_message_received = true; }), kWaitForJSCompletionTimeout); @@ -695,13 +701,15 @@ content_world_, base::BindOnce(^(const base::Value* result) { ASSERT_TRUE(result); ASSERT_TRUE(result->is_dict()); - const base::Value* index = result->FindKey(kSelectAndScrollResultIndex); - ASSERT_TRUE(index->is_double()); + const base::Value::Dict& result_dict = result->GetDict(); + const absl::optional<double> index = + result_dict.FindDouble(kSelectAndScrollResultIndex); + ASSERT_TRUE(index); // Since there are only two visible matches now and this // kFindInPageSelectAndScrollToMatch call is asking Find in Page to // traverse to a previous match, Find in Page should look for the next // previous visible match. This happens to be the 2nd match. - EXPECT_EQ(1.0, index->GetDouble()); + EXPECT_EQ(1.0, index.value()); select_third_match_message_received = true; }), kWaitForJSCompletionTimeout);
diff --git a/ios/web/find_in_page/java_script_find_in_page_manager_impl.mm b/ios/web/find_in_page/java_script_find_in_page_manager_impl.mm index bef0f22..c2e7206 100644 --- a/ios/web/find_in_page/java_script_find_in_page_manager_impl.mm +++ b/ios/web/find_in_page/java_script_find_in_page_manager_impl.mm
@@ -18,6 +18,7 @@ #import "ios/web/public/thread/web_task_traits.h" #import "ios/web/public/thread/web_thread.h" #import "ios/web/web_state/web_state_impl.h" +#import "third_party/abseil-cpp/absl/types/optional.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -218,10 +219,12 @@ const base::Value* result) { std::string match_context_string; if (result && result->is_dict()) { + const base::Value::Dict& result_dict = result->GetDict(); // Get updated match count. - const base::Value* matches = result->FindKey(kSelectAndScrollResultMatches); - if (matches && matches->is_double()) { - int match_count = static_cast<int>(matches->GetDouble()); + const absl::optional<double> matches = + result_dict.FindDouble(kSelectAndScrollResultMatches); + if (matches) { + int match_count = static_cast<int>(matches.value()); if (match_count != last_find_request_.GetMatchCountForSelectedFrame()) { last_find_request_.SetMatchCountForSelectedFrame(match_count); if (delegate_) { @@ -232,17 +235,17 @@ } } // Get updated currently selected index. - const base::Value* index = result->FindKey(kSelectAndScrollResultIndex); - if (index && index->is_double()) { - int current_index = static_cast<int>(index->GetDouble()); + const absl::optional<double> index = + result_dict.FindDouble(kSelectAndScrollResultIndex); + if (index) { + int current_index = static_cast<int>(index.value()); last_find_request_.SetCurrentSelectedMatchFrameIndex(current_index); } // Get context string. - const base::Value* context_string = - result->FindKey(kSelectAndScrollResultContextString); - if (context_string && context_string->is_string()) { - match_context_string = - static_cast<std::string>(context_string->GetString()); + const std::string* context_string = + result_dict.FindString(kSelectAndScrollResultContextString); + if (context_string) { + match_context_string = *context_string; } } if (delegate_) {
diff --git a/ios/web/navigation/BUILD.gn b/ios/web/navigation/BUILD.gn index fa2fb668..ffb2ef2 100644 --- a/ios/web/navigation/BUILD.gn +++ b/ios/web/navigation/BUILD.gn
@@ -92,6 +92,7 @@ "crw_navigation_item_holder.mm", "navigation_context_impl.h", "navigation_context_impl.mm", + "navigation_initiation_type.h", "navigation_item_impl.h", "navigation_item_impl.mm", "navigation_manager_delegate.h",
diff --git a/ios/web/navigation/navigation_initiation_type.h b/ios/web/navigation/navigation_initiation_type.h new file mode 100644 index 0000000..f571830 --- /dev/null +++ b/ios/web/navigation/navigation_initiation_type.h
@@ -0,0 +1,35 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_WEB_NAVIGATION_NAVIGATION_INITIATION_TYPE_H_ +#define IOS_WEB_NAVIGATION_NAVIGATION_INITIATION_TYPE_H_ + +namespace web { + +// Defines the ways how a pending navigation can be initiated. +enum class NavigationInitiationType { + // Navigation initiation type is only valid for pending navigations, use NONE + // if a navigation is already committed. + NONE = 0, + + // Navigation was initiated by the browser by calling NavigationManager + // methods. Examples of methods which cause browser-initiated navigations + // include: + // * NavigationManager::Reload() + // * NavigationManager::GoBack() + // * NavigationManager::GoForward() + BROWSER_INITIATED, + + // Navigation was initiated by renderer. Examples of renderer-initiated + // navigations include: + // * <a> link click + // * changing window.location.href + // * redirect via the <meta http-equiv="refresh"> tag + // * using window.history.pushState + RENDERER_INITIATED, +}; + +} // namespace web + +#endif // IOS_WEB_NAVIGATION_NAVIGATION_INITIATION_TYPE_H_
diff --git a/ios/web/navigation/navigation_manager_impl.h b/ios/web/navigation/navigation_manager_impl.h index 1586479..dc69045 100644 --- a/ios/web/navigation/navigation_manager_impl.h +++ b/ios/web/navigation/navigation_manager_impl.h
@@ -11,6 +11,7 @@ #include <vector> #include "base/functional/callback.h" +#include "ios/web/navigation/navigation_initiation_type.h" #import "ios/web/navigation/navigation_item_impl.h" #include "ios/web/navigation/synthesized_session_restore.h" #include "ios/web/navigation/time_smoother.h" @@ -41,29 +42,6 @@ // restoration. extern const char kRestoreNavigationTime[]; -// Defines the ways how a pending navigation can be initiated. -enum class NavigationInitiationType { - // Navigation initiation type is only valid for pending navigations, use NONE - // if a navigation is already committed. - NONE = 0, - - // Navigation was initiated by the browser by calling NavigationManager - // methods. Examples of methods which cause browser-initiated navigations - // include: - // * NavigationManager::Reload() - // * NavigationManager::GoBack() - // * NavigationManager::GoForward() - BROWSER_INITIATED, - - // Navigation was initiated by renderer. Examples of renderer-initiated - // navigations include: - // * <a> link click - // * changing window.location.href - // * redirect via the <meta http-equiv="refresh"> tag - // * using window.history.pushState - RENDERER_INITIATED, -}; - // WKBackForwardList-based implementation of NavigationManager. // Generally mirrors upstream's NavigationController. //
diff --git a/ios/web/web_state/web_view_internal_creation_util.mm b/ios/web/web_state/web_view_internal_creation_util.mm index 4bed9f7..ce343731 100644 --- a/ios/web/web_state/web_view_internal_creation_util.mm +++ b/ios/web/web_state/web_view_internal_creation_util.mm
@@ -6,6 +6,7 @@ #import "base/check_op.h" #import "base/strings/sys_string_conversions.h" +#import "ios/web/common/features.h" #import "ios/web/public/web_client.h" #import "ios/web/web_state/crw_web_view.h" #import "ios/web/web_state/ui/wk_web_view_configuration_provider.h" @@ -73,7 +74,10 @@ web_view.scrollView.decelerationRate = UIScrollViewDecelerationRateNormal; if (@available(iOS 16.4, *)) { - web_view.inspectable = web::GetWebClient()->EnableWebInspector(); + if (base::FeatureList::IsEnabled(features::kEnableWebInspector) && + web::GetWebClient()->EnableWebInspector()) { + web_view.inspectable = YES; + } } return web_view;
diff --git a/media/audio/cras/audio_manager_cras.cc b/media/audio/cras/audio_manager_cras.cc index fc84ae0..bdf9889 100644 --- a/media/audio/cras/audio_manager_cras.cc +++ b/media/audio/cras/audio_manager_cras.cc
@@ -208,7 +208,6 @@ // Rephrase the field aec_supported to properly reflect its meaning in this // context (since it currently signals whether an CrAS APM with tuned settings // is available). - // TODO(crbug.com/1307680): add unit tests and caching cras_util_ results. const bool tuned_system_apm_available = cras_util_->CrasGetAecSupported(); // Don't use the system AEC if it is deactivated for this group ID. Also never @@ -218,12 +217,8 @@ (tuned_system_apm_available && tuned_system_aec_allowed) || enforce_system_aec; - // TODO(b/266242770): Reintroduce the scheme for setting this to follow what - // was previously done in (the now removed) - // media/audio/cras/audio_manager_chromeos.cc. Until then, the NS and AGC - // effects are hardcoded to never run in CRAS. - bool system_ns_supported = false; - bool system_agc_supported = false; + bool system_ns_supported = cras_util_->CrasGetNsSupported(); + bool system_agc_supported = cras_util_->CrasGetAgcSupported(); int aec_group_id = cras_util_->CrasGetAecGroupId(); if (!use_system_aec || IsSystemAecDeactivated(aec_group_id)) {
diff --git a/media/audio/cras/audio_manager_cras_unittest.cc b/media/audio/cras/audio_manager_cras_unittest.cc index 39f9bdf6..edcaace6 100644 --- a/media/audio/cras/audio_manager_cras_unittest.cc +++ b/media/audio/cras/audio_manager_cras_unittest.cc
@@ -11,8 +11,8 @@ #include "media/audio/cras/cras_util.h" #include "media/audio/fake_audio_log_factory.h" #include "media/audio/test_audio_thread.h" -#include "media/base/media_switches.h" #include "media/base/limits.h" +#include "media/base/media_switches.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -33,6 +33,8 @@ MOCK_METHOD(int, CrasGetAecSupported, (), (override)); MOCK_METHOD(int, CrasGetAecGroupId, (), (override)); MOCK_METHOD(int, CrasGetDefaultOutputBufferSize, (), (override)); + MOCK_METHOD(int, CrasGetNsSupported, (), (override)); + MOCK_METHOD(int, CrasGetAgcSupported, (), (override)); }; class AudioManagerCrasUnderTest : public AudioManagerCras { @@ -397,19 +399,35 @@ params.effects() & AudioParameters::ECHO_CANCELLER; } +bool DspNsAllowed(const AudioParameters& params) { + return params.effects() & AudioParameters::ALLOW_DSP_NOISE_SUPPRESSION && + params.effects() & AudioParameters::NOISE_SUPPRESSION; +} + +bool DspAgcAllowed(const AudioParameters& params) { + return params.effects() & AudioParameters::ALLOW_DSP_AUTOMATIC_GAIN_CONTROL && + params.effects() & AudioParameters::AUTOMATIC_GAIN_CONTROL; +} + class AudioManagerCrasTestAEC : public AudioManagerCrasTest, - public ::testing::WithParamInterface<std::tuple<bool, bool>> { + public ::testing::WithParamInterface<std::tuple<bool, bool, bool, bool>> { protected: void SetUp() override { std::unique_ptr<MockCrasUtil> util = std::make_unique<MockCrasUtil>(); auto aec_supported = std::get<0>(GetParam()); auto aec_group = std::get<1>(GetParam()); + auto ns_supported = std::get<2>(GetParam()); + auto agc_supported = std::get<3>(GetParam()); EXPECT_CALL(*util, CrasGetAecSupported()) .WillOnce(testing::Return(aec_supported)); EXPECT_CALL(*util, CrasGetAecGroupId()) .WillOnce(testing::Return(aec_group)); + EXPECT_CALL(*util, CrasGetNsSupported()) + .WillOnce(testing::Return(ns_supported)); + EXPECT_CALL(*util, CrasGetAgcSupported()) + .WillOnce(testing::Return(agc_supported)); audio_manager_->SetCrasUtil(std::move(util)); } @@ -419,8 +437,9 @@ AllInputParameters, AudioManagerCrasTestAEC, ::testing::Combine(::testing::Values(false, true), - ::testing::Values(kNoAecFlaggedGroupId, - kAecTestGroupId))); + ::testing::Values(kNoAecFlaggedGroupId, kAecTestGroupId), + ::testing::Values(false, true), + ::testing::Values(false, true))); TEST_P(AudioManagerCrasTestAEC, DefaultBehavior) { AudioParameters params = audio_manager_->GetInputStreamParameters(""); @@ -428,13 +447,8 @@ EXPECT_TRUE(ExperimentalAecActive(params)); EXPECT_EQ(AecActive(params), aec_supported); - if (aec_supported) { - EXPECT_FALSE(NsActive(params)); - EXPECT_FALSE(AgcActive(params)); - } else { - EXPECT_FALSE(NsActive(params)); - EXPECT_FALSE(AgcActive(params)); - } + EXPECT_FALSE(NsActive(params)); + EXPECT_FALSE(AgcActive(params)); } TEST_P(AudioManagerCrasTestAEC, DefaultBehaviorSystemAecEnforcedByPolicy) { @@ -513,8 +527,7 @@ BehaviorWithCrOSEnforceSystemAecNsAgcAndDisallowedSystemAec) { base::test::ScopedFeatureList feature_list; feature_list.InitWithFeaturesAndParameters( - {{media::kCrOSEnforceSystemAecNsAgc, {}}}, - {{media::kCrOSSystemAEC}}); + {{media::kCrOSEnforceSystemAecNsAgc, {}}}, {{media::kCrOSSystemAEC}}); AudioParameters params = audio_manager_->GetInputStreamParameters(""); auto aec_supported = std::get<0>(GetParam()); @@ -530,6 +543,64 @@ } } +TEST_P(AudioManagerCrasTestAEC, BehaviorWithCrOSEnforceSystemAecNs) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature(media::kCrOSEnforceSystemAecNs); + AudioParameters params = audio_manager_->GetInputStreamParameters(""); + + auto aec_supported = std::get<0>(GetParam()); + auto agc_supported = std::get<3>(GetParam()); + + EXPECT_TRUE(ExperimentalAecActive(params)); + EXPECT_TRUE(AecActive(params)); + if (aec_supported) { + EXPECT_FALSE(NsActive(params)); + EXPECT_FALSE(AgcActive(params)); + } else { + EXPECT_TRUE(NsActive(params)); + EXPECT_EQ(AgcActive(params), agc_supported); + } +} + +TEST_P(AudioManagerCrasTestAEC, BehaviorWithCrOSEnforceSystemAecAgc) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature(media::kCrOSEnforceSystemAecAgc); + AudioParameters params = audio_manager_->GetInputStreamParameters(""); + + auto aec_supported = std::get<0>(GetParam()); + auto ns_supported = std::get<2>(GetParam()); + + EXPECT_TRUE(ExperimentalAecActive(params)); + EXPECT_TRUE(AecActive(params)); + if (aec_supported) { + EXPECT_FALSE(NsActive(params)); + EXPECT_FALSE(AgcActive(params)); + } else { + EXPECT_EQ(NsActive(params), ns_supported); + EXPECT_TRUE(AgcActive(params)); + } +} + +TEST_P(AudioManagerCrasTestAEC, BehaviorWithCrOSEnforceSystemAec) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature(media::kCrOSEnforceSystemAec); + AudioParameters params = audio_manager_->GetInputStreamParameters(""); + + auto aec_supported = std::get<0>(GetParam()); + auto ns_supported = std::get<2>(GetParam()); + auto agc_supported = std::get<3>(GetParam()); + + EXPECT_TRUE(ExperimentalAecActive(params)); + EXPECT_TRUE(AecActive(params)); + if (aec_supported) { + EXPECT_FALSE(NsActive(params)); + EXPECT_FALSE(AgcActive(params)); + } else { + EXPECT_EQ(NsActive(params), ns_supported); + EXPECT_EQ(AgcActive(params), agc_supported); + } +} + class AudioManagerCrasTestDSP : public AudioManagerCrasTest, public ::testing::WithParamInterface<std::tuple<bool, bool, bool>> { @@ -560,6 +631,8 @@ EXPECT_CALL(*util, CrasGetAecSupported()).WillOnce(testing::Return(false)); EXPECT_CALL(*util, CrasGetAecGroupId()).WillOnce(testing::Return(0)); + EXPECT_CALL(*util, CrasGetNsSupported()).WillOnce(testing::Return(false)); + EXPECT_CALL(*util, CrasGetAgcSupported()).WillOnce(testing::Return(false)); audio_manager_->SetCrasUtil(std::move(util)); } @@ -582,6 +655,8 @@ AudioParameters params = audio_manager_->GetInputStreamParameters(""); EXPECT_FALSE(DspAecAllowed(params)); + EXPECT_FALSE(DspNsAllowed(params)); + EXPECT_FALSE(DspAgcAllowed(params)); } TEST_P(AudioManagerCrasTestDSP, BehaviorWithCrOSEnforceSystemAec) { @@ -592,6 +667,8 @@ EXPECT_TRUE(DspAecAllowed(params) && aec_on_dsp_allowed_ || !DspAecAllowed(params) && !aec_on_dsp_allowed_); + EXPECT_FALSE(DspNsAllowed(params)); + EXPECT_FALSE(DspAgcAllowed(params)); } TEST_P(AudioManagerCrasTestDSP, BehaviorWithCrOSEnforceSystemAecNs) { @@ -602,6 +679,9 @@ EXPECT_TRUE(DspAecAllowed(params) && aec_on_dsp_allowed_ || !DspAecAllowed(params) && !aec_on_dsp_allowed_); + EXPECT_TRUE(DspNsAllowed(params) && ns_on_dsp_allowed_ || + !DspNsAllowed(params) && !ns_on_dsp_allowed_); + EXPECT_FALSE(DspAgcAllowed(params)); } TEST_P(AudioManagerCrasTestDSP, BehaviorWithCrOSEnforceSystemAecAgc) { @@ -612,6 +692,9 @@ EXPECT_TRUE(DspAecAllowed(params) && aec_on_dsp_allowed_ || !DspAecAllowed(params) && !aec_on_dsp_allowed_); + EXPECT_FALSE(DspNsAllowed(params)); + EXPECT_TRUE(DspAgcAllowed(params) && agc_on_dsp_allowed_ || + !DspAgcAllowed(params) && !agc_on_dsp_allowed_); } TEST_P(AudioManagerCrasTestDSP, BehaviorWithCrOSEnforceSystemAecNsAgc) { @@ -622,6 +705,10 @@ EXPECT_TRUE(DspAecAllowed(params) && aec_on_dsp_allowed_ || !DspAecAllowed(params) && !aec_on_dsp_allowed_); + EXPECT_TRUE(DspNsAllowed(params) && ns_on_dsp_allowed_ || + !DspNsAllowed(params) && !ns_on_dsp_allowed_); + EXPECT_TRUE(DspAgcAllowed(params) && agc_on_dsp_allowed_ || + !DspAgcAllowed(params) && !agc_on_dsp_allowed_); } } // namespace
diff --git a/media/audio/cras/cras_util.cc b/media/audio/cras/cras_util.cc index cb1b41a..01e28bd 100644 --- a/media/audio/cras/cras_util.cc +++ b/media/audio/cras/cras_util.cc
@@ -184,6 +184,37 @@ CrasUtil::~CrasUtil() = default; +bool CrasUtil::CacheEffects() { + libcras_client* client = CrasConnect(); + if (!client) { + LOG(ERROR) << "Failed to cache effects"; + return false; + } + if (libcras_client_get_aec_supported(client, &aec_supported_) < 0) { + LOG(ERROR) << "Fail to query AEC supported"; + aec_supported_ = false; + } + if (libcras_client_get_agc_supported(client, &agc_supported_) < 0) { + LOG(ERROR) << "Fail to query AGC supported"; + agc_supported_ = false; + } + if (libcras_client_get_ns_supported(client, &ns_supported_) < 0) { + LOG(ERROR) << "Fail to query NS supported"; + ns_supported_ = false; + } + if (libcras_client_get_aec_group_id(client, &aec_group_id_) < 0) { + LOG(ERROR) << "Fail to query AEC group ID"; + aec_group_id_ = -1; // The default group ID is -1 + } + if (libcras_client_get_default_output_buffer_size( + client, &default_output_buffer_size_) < 0) { + LOG(ERROR) << "Fail to query default output buffer size"; + default_output_buffer_size_ = 0; + } + CrasDisconnect(&client); + return true; +} + std::vector<CrasDevice> CrasUtil::CrasGetAudioDevices(DeviceType type) { std::vector<CrasDevice> devices; @@ -236,42 +267,38 @@ } int CrasUtil::CrasGetAecSupported() { - libcras_client* client = CrasConnect(); - if (!client) { - return 0; + if (!cras_effects_cached_) { + cras_effects_cached_ = CacheEffects(); } + return aec_supported_; +} - int supported; - libcras_client_get_aec_supported(client, &supported); - CrasDisconnect(&client); +int CrasUtil::CrasGetAgcSupported() { + if (!cras_effects_cached_) { + cras_effects_cached_ = CacheEffects(); + } + return agc_supported_; +} - return supported; +int CrasUtil::CrasGetNsSupported() { + if (!cras_effects_cached_) { + cras_effects_cached_ = CacheEffects(); + } + return ns_supported_; } int CrasUtil::CrasGetAecGroupId() { - libcras_client* client = CrasConnect(); - if (!client) { - return -1; + if (!cras_effects_cached_) { + cras_effects_cached_ = CacheEffects(); } - - int id; - int rc = libcras_client_get_aec_group_id(client, &id); - CrasDisconnect(&client); - - return rc < 0 ? rc : id; + return aec_group_id_; } int CrasUtil::CrasGetDefaultOutputBufferSize() { - libcras_client* client = CrasConnect(); - if (!client) { - return -1; + if (!cras_effects_cached_) { + cras_effects_cached_ = CacheEffects(); } - - int size; - int rc = libcras_client_get_default_output_buffer_size(client, &size); - CrasDisconnect(&client); - - return rc < 0 ? rc : size; + return default_output_buffer_size_; } } // namespace media
diff --git a/media/audio/cras/cras_util.h b/media/audio/cras/cras_util.h index f76e1ce93..4b3ece7 100644 --- a/media/audio/cras/cras_util.h +++ b/media/audio/cras/cras_util.h
@@ -48,17 +48,40 @@ virtual ~CrasUtil(); // Enumerates all devices of |type|. + // Virtual for testing. virtual std::vector<CrasDevice> CrasGetAudioDevices(DeviceType type); // Returns if system AEC is supported in CRAS. + // Virtual for testing. virtual int CrasGetAecSupported(); + // Returns if system AGC is supported in CRAS. + // Virtual for testing. + virtual int CrasGetAgcSupported(); + + // Returns if system NS is supported in CRAS. + // Virtual for testing. + virtual int CrasGetNsSupported(); + // Returns the system AEC group ID. If no group ID is specified, -1 is // returned. + // Virtual for testing. virtual int CrasGetAecGroupId(); // Returns the default output buffer size. + // Virtual for testing. virtual int CrasGetDefaultOutputBufferSize(); + + private: + int aec_supported_ = false; + int agc_supported_ = false; + int ns_supported_ = false; + int aec_group_id_ = -1; + int default_output_buffer_size_ = 0; + bool cras_effects_cached_ = false; + + // Caches constant effect config from CRAS. + bool CacheEffects(); }; } // namespace media
diff --git a/mojo/core/platform_wrapper_unittest.cc b/mojo/core/platform_wrapper_unittest.cc index 72ee50c..7d65ffb 100644 --- a/mojo/core/platform_wrapper_unittest.cc +++ b/mojo/core/platform_wrapper_unittest.cc
@@ -70,9 +70,7 @@ base::FilePath temp_file_path; ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path)); const std::string kMessage = "Hello, world!"; - EXPECT_EQ(base::WriteFile(temp_file_path, kMessage.data(), - static_cast<int>(kMessage.size())), - static_cast<int>(kMessage.size())); + ASSERT_TRUE(base::WriteFile(temp_file_path, kMessage)); RunTestClient("ReadPlatformFile", [&](MojoHandle h) { // Open the temporary file for reading, wrap its handle, and send it to
diff --git a/mojo/public/rust/system/handle.rs b/mojo/public/rust/system/handle.rs index 80e9d08b..8008a61 100644 --- a/mojo/public/rust/system/handle.rs +++ b/mojo/public/rust/system/handle.rs
@@ -76,6 +76,7 @@ /// `UntypedHandle` must hold either a valid `MojoHandle` or be /// `UntypedHandle::invalid()` (i.e. a 0 `MojoHandle`). The handle will be /// closed on `drop` if it is not `invalid()`. +#[derive(Debug)] #[repr(transparent)] pub struct UntypedHandle { /// The native Mojo handle.
diff --git a/mojo/public/rust/system/shared_buffer.rs b/mojo/public/rust/system/shared_buffer.rs index dabfb14..d0277f42 100644 --- a/mojo/public/rust/system/shared_buffer.rs +++ b/mojo/public/rust/system/shared_buffer.rs
@@ -165,9 +165,8 @@ } } - /// Retrieves information about a shared buffer the this handle. The return - /// value is a set of flags (a bit vector in a u32) representing different - /// aspects of the shared buffer and the size of the shared buffer. + /// Retrieves information about this shared buffer. The return value is just + /// the size of the shared buffer. pub fn get_info(&self) -> Result<u64, MojoResult> { let mut info = ffi::MojoSharedBufferInfo::new(0); let r = MojoResult::from_code(unsafe {
diff --git a/mojo/public/rust/tests/encoding.rs b/mojo/public/rust/tests/encoding.rs index 24f44d4a..497e132b 100644 --- a/mojo/public/rust/tests/encoding.rs +++ b/mojo/public/rust/tests/encoding.rs
@@ -39,43 +39,41 @@ /// output, and decoding that once again. macro_rules! encoding_tests { ($($name:ident { MessageHeader => $header_cls:expr, $req_type:ident => $cls:expr } )*) => { - tests! { - $( - fn $name() { - let data = include_str!(concat!("../../interfaces/bindings/tests/data/validation/", - stringify!($name), - ".data")); - match util::parse_validation_test(data) { - Ok((mut data, num_handles)) => { - let mut mock_handles = Vec::with_capacity(num_handles); - for _ in 0..num_handles { - mock_handles.push(unsafe { system::acquire(0) }); - } - println!("{}: Decoding header", stringify!($name)); - let header = MessageHeader::deserialize(&mut data[..], Vec::new()).expect("Should not error"); - let ctxt: Context = Default::default(); - let header_size = header.serialized_size(&ctxt); - let header_cls = $header_cls; - println!("{}: Verifying decoded header", stringify!($name)); - header_cls(header); - let payload_buffer = &mut data[header_size..]; - let cls = $cls; - println!("{}: Decoding payload", stringify!($name)); - let decoded_payload = $req_type::deserialize(payload_buffer, mock_handles).expect("Should not error"); - println!("{}: Verifying decoded payload", stringify!($name)); - cls(&decoded_payload); - println!("{}: Re-encoding payload", stringify!($name)); - let (mut encoded_payload, handles) = decoded_payload.auto_serialize(); - println!("{}: Decoding payload again", stringify!($name)); - let redecoded_payload = $req_type::deserialize(&mut encoded_payload[..], handles).expect("Should not error"); - println!("{}: Verifying decoded payload again", stringify!($name)); - cls(&redecoded_payload); - }, - Err(msg) => panic!("Error: {}", msg), - } + $( + mojo_test!($name, { + let data = include_str!(concat!("../../interfaces/bindings/tests/data/validation/", + stringify!($name), + ".data")); + match util::parse_validation_test(data) { + Ok((mut data, num_handles)) => { + let mut mock_handles = Vec::with_capacity(num_handles); + for _ in 0..num_handles { + mock_handles.push(unsafe { system::acquire(0) }); + } + println!("{}: Decoding header", stringify!($name)); + let header = MessageHeader::deserialize(&mut data[..], Vec::new()).expect("Should not error"); + let ctxt: Context = Default::default(); + let header_size = header.serialized_size(&ctxt); + let header_cls = $header_cls; + println!("{}: Verifying decoded header", stringify!($name)); + header_cls(header); + let payload_buffer = &mut data[header_size..]; + let cls = $cls; + println!("{}: Decoding payload", stringify!($name)); + let decoded_payload = $req_type::deserialize(payload_buffer, mock_handles).expect("Should not error"); + println!("{}: Verifying decoded payload", stringify!($name)); + cls(&decoded_payload); + println!("{}: Re-encoding payload", stringify!($name)); + let (mut encoded_payload, handles) = decoded_payload.auto_serialize(); + println!("{}: Decoding payload again", stringify!($name)); + let redecoded_payload = $req_type::deserialize(&mut encoded_payload[..], handles).expect("Should not error"); + println!("{}: Verifying decoded payload again", stringify!($name)); + cls(&redecoded_payload); + }, + Err(msg) => panic!("Error: {}", msg), } - )* - } + }); + )* } }
diff --git a/mojo/public/rust/tests/integration.rs b/mojo/public/rust/tests/integration.rs index 1e955e3..a934202 100644 --- a/mojo/public/rust/tests/integration.rs +++ b/mojo/public/rust/tests/integration.rs
@@ -16,47 +16,46 @@ use crate::util::mojom_validation::*; -tests! { - // Tests basic client and server interaction over a thread - fn send_and_recv() { - let (endpt0, endpt1) = message_pipe::create().unwrap(); - // Client and server handles - let client = IntegrationTestInterfaceClient::new(endpt0); - let server = IntegrationTestInterfaceServer::with_version(endpt1, 0); +// Tests basic client and server interaction over a thread +mojo_test!(send_and_recv, { + let (endpt0, endpt1) = message_pipe::create().unwrap(); + // Client and server handles + let client = IntegrationTestInterfaceClient::new(endpt0); + let server = IntegrationTestInterfaceServer::with_version(endpt1, 0); - // Client thread - let handle = thread::spawn(move || { - // Send request - client.send_request(5, IntegrationTestInterfaceMethod0Request { - param0: BasicStruct { - a: -1, - }, - }).unwrap(); - // Wait for response - client.pipe().wait(HandleSignals::READABLE); - // Decode response - let (req_id, options) = client.recv_response().unwrap(); - assert_eq!(req_id, 5); - match options { - IntegrationTestInterfaceResponseOption::IntegrationTestInterfaceMethod0(msg) => { - assert_eq!(msg.param0, vec![1, 2, 3]); - }, - } - }); - // Wait for request - server.pipe().wait(HandleSignals::READABLE); - // Decode request - let (req_id, options) = server.recv_response().unwrap(); + // Client thread + let handle = thread::spawn(move || { + // Send request + client + .send_request( + 5, + IntegrationTestInterfaceMethod0Request { param0: BasicStruct { a: -1 } }, + ) + .unwrap(); + // Wait for response + client.pipe().wait(HandleSignals::READABLE); + // Decode response + let (req_id, options) = client.recv_response().unwrap(); assert_eq!(req_id, 5); match options { - IntegrationTestInterfaceRequestOption::IntegrationTestInterfaceMethod0(msg) => { - assert_eq!(msg.param0.a, -1); - }, + IntegrationTestInterfaceResponseOption::IntegrationTestInterfaceMethod0(msg) => { + assert_eq!(msg.param0, vec![1, 2, 3]); + } } - // Send response - server.send_request(5, IntegrationTestInterfaceMethod0Response { - param0: vec![1, 2, 3], - }).unwrap(); - let _ = handle.join(); + }); + // Wait for request + server.pipe().wait(HandleSignals::READABLE); + // Decode request + let (req_id, options) = server.recv_response().unwrap(); + assert_eq!(req_id, 5); + match options { + IntegrationTestInterfaceRequestOption::IntegrationTestInterfaceMethod0(msg) => { + assert_eq!(msg.param0.a, -1); + } } -} + // Send response + server + .send_request(5, IntegrationTestInterfaceMethod0Response { param0: vec![1, 2, 3] }) + .unwrap(); + let _ = handle.join(); +});
diff --git a/mojo/public/rust/tests/lib.rs b/mojo/public/rust/tests/lib.rs index aea7fcfd..63e016ff 100644 --- a/mojo/public/rust/tests/lib.rs +++ b/mojo/public/rust/tests/lib.rs
@@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#![feature(assert_matches)] +#![feature(maybe_uninit_write_slice)] + #[macro_use] extern crate mojo;
diff --git a/mojo/public/rust/tests/regression.rs b/mojo/public/rust/tests/regression.rs index 470eb9d..844efb2 100644 --- a/mojo/public/rust/tests/regression.rs +++ b/mojo/public/rust/tests/regression.rs
@@ -57,40 +57,37 @@ impl<T: MojomEncodable> MojomStruct for StructA<T> {} -tests! { - // Fixed size arrays have complex and unsafe semantics to ensure - // there are no memory leaks. We test this behavior here to make - // sure memory isn't becoming corrupted. - fn regression_fixed_size_array_error_propagates_safely() { - let handle1 = unsafe { system::acquire(0) }; - let handle2 = unsafe { system::acquire(0) }; - let handle3 = unsafe { system::acquire(0) }; - let val = StructA { - param0: [handle1, handle2, handle3], - }; - let (mut buffer, mut handles) = val.auto_serialize(); - handles.truncate(1); - let new_val = <StructA<UntypedHandle>>::deserialize(&mut buffer[..], handles); - match new_val { - Ok(_) => panic!("Value should not be okay!"), - Err(err) => assert_eq!(err, ValidationError::IllegalHandle), - } +// Fixed size arrays have complex and unsafe semantics to ensure +// there are no memory leaks. We test this behavior here to make +// sure memory isn't becoming corrupted. +mojo_test!(regression_fixed_size_array_error_propagates_safely, { + let handle1 = unsafe { system::acquire(0) }; + let handle2 = unsafe { system::acquire(0) }; + let handle3 = unsafe { system::acquire(0) }; + let val = StructA { param0: [handle1, handle2, handle3] }; + let (mut buffer, mut handles) = val.auto_serialize(); + handles.truncate(1); + let new_val = <StructA<UntypedHandle>>::deserialize(&mut buffer[..], handles); + match new_val { + Ok(_) => panic!("Value should not be okay!"), + Err(err) => assert_eq!(err, ValidationError::IllegalHandle), } +}); - // Same as the above test, but verifies that drop() is called. - // For the only handle that should drop, we make the handle some - // random number which is potentially a valid handle. When on - // drop() we try to close it, we should panic. - #[should_panic] +// Same as the above test, but verifies that drop() is called. +// For the only handle that should drop, we make the handle some +// random number which is potentially a valid handle. When on +// drop() we try to close it, we should panic. +mojo_test!( + regression_fixed_size_array_verify_drop, // Ignore this test, it panics while panicking #[ignore] - fn regression_fixed_size_array_verify_drop() { + #[should_panic] + { let handle1 = unsafe { system::acquire(42) }; let handle2 = unsafe { system::acquire(0) }; let handle3 = unsafe { system::acquire(0) }; - let val = StructA { - param0: [handle1, handle2, handle3], - }; + let val = StructA { param0: [handle1, handle2, handle3] }; let (mut buffer, mut handles) = val.auto_serialize(); handles.truncate(1); let new_val = <StructA<UntypedHandle>>::deserialize(&mut buffer[..], handles); @@ -99,4 +96,4 @@ Err(err) => assert_eq!(err, ValidationError::IllegalHandle), } } -} +);
diff --git a/mojo/public/rust/tests/run_loop.rs b/mojo/public/rust/tests/run_loop.rs index eaa4a99d..9a82bf0c 100644 --- a/mojo/public/rust/tests/run_loop.rs +++ b/mojo/public/rust/tests/run_loop.rs
@@ -243,209 +243,263 @@ } } -tests! { - // Verifies that after adding and removing, we can run, exit and be - // left in a consistent state. - fn add_remove() { - run_loop::with_current(|runloop| { - let (endpt0, endpt1) = message_pipe::create().unwrap(); - let token0 = runloop.register(&endpt0, HandleSignals::WRITABLE, 0, HandlerExpectReady {}); - let token1 = runloop.register(&endpt1, HandleSignals::WRITABLE, 0, HandlerExpectReady {}); - runloop.deregister(token1); - runloop.deregister(token0); - runloop.run(); - }) - } +// Verifies that after adding and removing, we can run, exit and be left in a +// consistent state. +mojo_test!(add_remove, { + run_loop::with_current(|runloop| { + let (endpt0, endpt1) = message_pipe::create().unwrap(); + let token0 = runloop.register(&endpt0, HandleSignals::WRITABLE, 0, HandlerExpectReady {}); + let token1 = runloop.register(&endpt1, HandleSignals::WRITABLE, 0, HandlerExpectReady {}); + runloop.deregister(token1); + runloop.deregister(token0); + runloop.run(); + }) +}); - // Verifies that generated tokens are unique. - fn tokens() { - let mut vec = Vec::new(); - run_loop::with_current(|runloop| { - for _ in 0..10 { - let (_endpt0, endpt1) = message_pipe::create().unwrap(); - vec.push(runloop.register(&endpt1, HandleSignals::empty(), 0, HandlerExpectReady {})); - } - for i in 0..10 { - for j in 0..10 { - if i != j { - assert!(vec[i] != vec[j]); - } +// Verifies that generated tokens are unique. +mojo_test!(tokens, { + let mut vec = Vec::new(); + run_loop::with_current(|runloop| { + for _ in 0..10 { + let (_endpt0, endpt1) = message_pipe::create().unwrap(); + vec.push(runloop.register(&endpt1, HandleSignals::empty(), 0, HandlerExpectReady {})); + } + for i in 0..10 { + for j in 0..10 { + if i != j { + assert!(vec[i] != vec[j]); } } - }); - } + } + }); +}); - // Verifies that the handler's "on_ready" function is called. - fn notify_results() { - let (_endpt0, endpt1) = message_pipe::create().unwrap(); - run_loop::with_current(|runloop| { - let _ = runloop.register(&endpt1, HandleSignals::WRITABLE, MOJO_INDEFINITE, HandlerExpectReady {}); - runloop.run(); - }); - } +// Verifies that the handler's "on_ready" function is called. +mojo_test!(notify_results, { + let (_endpt0, endpt1) = message_pipe::create().unwrap(); + run_loop::with_current(|runloop| { + let _ = runloop.register( + &endpt1, + HandleSignals::WRITABLE, + MOJO_INDEFINITE, + HandlerExpectReady {}, + ); + runloop.run(); + }); +}); - // Verifies that the handler's "on_error" function is called. - fn notify_error() { - // Drop the first endpoint immediately - let (_, endpt1) = message_pipe::create().unwrap(); - run_loop::with_current(|runloop| { - let was_called = Rc::new(Cell::new(false)); - let _ = runloop.register(&endpt1, HandleSignals::READABLE, 0, - HandlerExpectError { - was_called: was_called.clone(), - }); - runloop.run(); - assert!(was_called.get(), "on_error was not called"); - }); - } +// Verifies that the handler's "on_error" function is called. +mojo_test!(notify_error, { + // Drop the first endpoint immediately + let (_, endpt1) = message_pipe::create().unwrap(); + run_loop::with_current(|runloop| { + let was_called = Rc::new(Cell::new(false)); + let _ = runloop.register( + &endpt1, + HandleSignals::READABLE, + 0, + HandlerExpectError { was_called: was_called.clone() }, + ); + runloop.run(); + assert!(was_called.get(), "on_error was not called"); + }); +}); - // Verifies that the handler's "on_ready" function is called which only - // quits. - fn notify_ready_quit() { - let (_endpt0, endpt1) = message_pipe::create().unwrap(); - run_loop::with_current(|runloop| { - let _ = runloop.register(&endpt1, HandleSignals::WRITABLE, MOJO_INDEFINITE, HandlerQuit {}); - runloop.run(); - }); - } +// Verifies that the handler's "on_ready" function is called which only quits. +mojo_test!(notify_ready_quit, { + let (_endpt0, endpt1) = message_pipe::create().unwrap(); + run_loop::with_current(|runloop| { + let _ = runloop.register(&endpt1, HandleSignals::WRITABLE, MOJO_INDEFINITE, HandlerQuit {}); + runloop.run(); + }); +}); - // Tests more complex behavior, i.e. the interaction between two handlers. - fn register_deregister() { - let (_endpt0, endpt1) = message_pipe::create().unwrap(); - run_loop::with_current(|runloop| { - let _ = runloop.register(&endpt1, HandleSignals::WRITABLE, MOJO_INDEFINITE, HandlerRegister {}); - runloop.run(); - }); - } +// Tests more complex behavior, i.e. the interaction between two handlers. +mojo_test!(register_deregister, { + let (_endpt0, endpt1) = message_pipe::create().unwrap(); + run_loop::with_current(|runloop| { + let _ = + runloop.register(&endpt1, HandleSignals::WRITABLE, MOJO_INDEFINITE, HandlerRegister {}); + runloop.run(); + }); +}); - // Tests reregistering. +// Tests reregistering. +mojo_test!( + reregister, #[ignore] - fn reregister() { + { let (_endpt0, endpt1) = message_pipe::create().unwrap(); run_loop::with_current(|runloop| { - let _ = runloop.register(&endpt1, HandleSignals::READABLE, 0, HandlerReregister { count: 0 }); + let _ = runloop.register( + &endpt1, + HandleSignals::READABLE, + 0, + HandlerReregister { count: 0 }, + ); runloop.run(); }); } +); - // Tests nesting run loops by having a handler create a new one. +// Tests nesting run loops by having a handler create a new one. +mojo_test!( + nesting, #[ignore] - fn nesting() { + { let (_endpt0, endpt1) = message_pipe::create().unwrap(); run_loop::with_current(|runloop| { - let _ = runloop.register(&endpt1, HandleSignals::READABLE, 0, HandlerNesting { count: 0 }); + let _ = + runloop.register(&endpt1, HandleSignals::READABLE, 0, HandlerNesting { count: 0 }); runloop.run(); }); } +); - // Tests to make sure nesting with the SAME runloop fails. +// Tests to make sure nesting with the SAME runloop fails. +mojo_test!( + bad_nesting, #[should_panic] #[ignore] - fn bad_nesting() { + { let (_endpt0, endpt1) = message_pipe::create().unwrap(); run_loop::with_current(|runloop| { let _ = runloop.register(&endpt1, HandleSignals::READABLE, 0, HandlerBadNesting {}); runloop.run(); }); } +); - // Tests adding a simple task that adds a handler. - fn simple_task() { - run_loop::with_current(|runloop| { - let was_called = Rc::new(Cell::new(false)); - // The inner closure cannot take `was_called` by reference since we - // cannot prove it lives long enough to the borrow checker. It must - // be cloned first. - let was_called_clone = was_called.clone(); - let (_, endpt1) = message_pipe::create().unwrap(); - // If `endpt1` is moved into the task closure, it is dropped at the - // end of its call. This means we won't get the signal we're looking - // for: we'll just get a notification that the handle was closed. - // Make it live longer by wrapping it in an Rc. - let endpt1 = Rc::new(endpt1); - let endpt1_clone = endpt1.clone(); - let _ = runloop.post_task(move |runloop: &mut RunLoop| { - let _ = runloop.register(&*endpt1_clone, HandleSignals::READABLE, 0, - HandlerExpectError { - was_called: was_called_clone, - }); - }, 0).unwrap(); - runloop.run(); +// Tests adding a simple task that adds a handler. +mojo_test!(simple_task, { + run_loop::with_current(|runloop| { + let was_called = Rc::new(Cell::new(false)); + // The inner closure cannot take `was_called` by reference since we + // cannot prove it lives long enough to the borrow checker. It must be + // cloned first. + let was_called_clone = was_called.clone(); + let (_, endpt1) = message_pipe::create().unwrap(); + // If `endpt1` is moved into the task closure, it is dropped at the + // end of its call. This means we won't get the signal we're looking + // for: we'll just get a notification that the handle was closed. + // Make it live longer by wrapping it in an Rc. + let endpt1 = Rc::new(endpt1); + let endpt1_clone = endpt1.clone(); + let _ = runloop + .post_task( + move |runloop: &mut RunLoop| { + let _ = runloop.register( + &*endpt1_clone, + HandleSignals::READABLE, + 0, + HandlerExpectError { was_called: was_called_clone }, + ); + }, + 0, + ) + .unwrap(); + runloop.run(); - // Ensure we got the `on_error` call for the unsatisfiable signal. - assert!(was_called.get(), "on_error was not called"); - }); - } + // Ensure we got the `on_error` call for the unsatisfiable signal. + assert!(was_called.get(), "on_error was not called"); + }); +}); - // Tests using a handler that adds a bunch of tasks. - fn handler_tasks() { - let (_endpt0, endpt1) = message_pipe::create().unwrap(); - let r = Rc::new(Cell::new(0)); - run_loop::with_current(|runloop| { - let _ = runloop.register(&endpt1, HandleSignals::WRITABLE, 0, HandlerTasks { count: r.clone() }); - runloop.run(); - assert!((*r).get() >= 11); - }); - } +// Tests using a handler that adds a bunch of tasks. +mojo_test!(handler_tasks, { + let (_endpt0, endpt1) = message_pipe::create().unwrap(); + let r = Rc::new(Cell::new(0)); + run_loop::with_current(|runloop| { + let _ = runloop.register( + &endpt1, + HandleSignals::WRITABLE, + 0, + HandlerTasks { count: r.clone() }, + ); + runloop.run(); + assert!((*r).get() >= 11); + }); +}); - // Tests using a handler that adds a bunch of tasks. - fn nested_tasks() { - let (_endpt0, endpt1) = message_pipe::create().unwrap(); - let r = Rc::new(Cell::new(0)); - run_loop::with_current(|runloop| { - let _ = runloop.register(&endpt1, HandleSignals::WRITABLE, 0, NestedTasks { count: r.clone(), quitter: false }); - runloop.run(); - assert!((*r).get() >= 10); - }); - } +// Tests using a handler that adds a bunch of tasks. +mojo_test!(nested_tasks, { + let (_endpt0, endpt1) = message_pipe::create().unwrap(); + let r = Rc::new(Cell::new(0)); + run_loop::with_current(|runloop| { + let _ = runloop.register( + &endpt1, + HandleSignals::WRITABLE, + 0, + NestedTasks { count: r.clone(), quitter: false }, + ); + runloop.run(); + assert!((*r).get() >= 10); + }); +}); - // Tests using a handler that adds a bunch of tasks. - // - // This test is disabled because it posts tasks which call `RunLoop::quit`, - // some of which get left on the `RunLoop` after the test ends. These - // interfere with later tests on the same thread. +// Tests using a handler that adds a bunch of tasks. +// +// This test is disabled because it posts tasks which call `RunLoop::quit`, some +// of which get left on the `RunLoop` after the test ends. These interfere with +// later tests on the same thread. +mojo_test!( + nested_tasks_quit, #[ignore] - fn nested_tasks_quit() { + { let (_endpt0, endpt1) = message_pipe::create().unwrap(); let r = Rc::new(Cell::new(0)); run_loop::with_current(|runloop| { - let _ = runloop.register(&endpt1, HandleSignals::WRITABLE, 0, NestedTasks { count: r.clone(), quitter: true }); + let _ = runloop.register( + &endpt1, + HandleSignals::WRITABLE, + 0, + NestedTasks { count: r.clone(), quitter: true }, + ); runloop.run(); assert!((*r).get() >= 10); }); } +); - fn close_handle() { - let (_endpt0, endpt1) = message_pipe::create().unwrap(); - run_loop::with_current(|runloop| { - let _ = runloop.register(&endpt1, HandleSignals::WRITABLE, 0, HandlerQuit {}); - drop(endpt1); - runloop.run(); - }) - } +mojo_test!(close_handle, { + let (_endpt0, endpt1) = message_pipe::create().unwrap(); + run_loop::with_current(|runloop| { + let _ = runloop.register(&endpt1, HandleSignals::WRITABLE, 0, HandlerQuit {}); + drop(endpt1); + runloop.run(); + }) +}); - // Tests that `RunLoop::run` will run posted tasks even if there's no - // handles to wait on. - fn post_tasks_without_handles() { - let outer_called = Rc::new(Cell::new(false)); - let outer_called_clone = outer_called.clone(); - let inner_called = Rc::new(Cell::new(false)); - let inner_called_clone = inner_called.clone(); +// Tests that `RunLoop::run` will run posted tasks even if there's no handles to +// wait on. +mojo_test!(post_tasks_without_handles, { + let outer_called = Rc::new(Cell::new(false)); + let outer_called_clone = outer_called.clone(); + let inner_called = Rc::new(Cell::new(false)); + let inner_called_clone = inner_called.clone(); - run_loop::with_current(move |runloop| { - // Post a task, and then post another task from within the first. - // This is to check RunLoop will run all the tasks it can before - // quitting. - runloop.post_task(move |runloop| { - outer_called_clone.set(true); - runloop.post_task(move |_| { - inner_called_clone.set(true); - }, 0).unwrap(); - }, 0).unwrap(); - runloop.run(); - }); + run_loop::with_current(move |runloop| { + // Post a task, and then post another task from within the first. This + // is to check RunLoop will run all the tasks it can before quitting. + runloop + .post_task( + move |runloop| { + outer_called_clone.set(true); + runloop + .post_task( + move |_| { + inner_called_clone.set(true); + }, + 0, + ) + .unwrap(); + }, + 0, + ) + .unwrap(); + runloop.run(); + }); - assert!(outer_called.get()); - assert!(inner_called.get()); - } -} + assert!(outer_called.get()); + assert!(inner_called.get()); +});
diff --git a/mojo/public/rust/tests/system.rs b/mojo/public/rust/tests/system.rs index 739e7fe..db680cb4 100644 --- a/mojo/public/rust/tests/system.rs +++ b/mojo/public/rust/tests/system.rs
@@ -8,7 +8,6 @@ //! and the result being caught in the test! macro. If a test function //! returns without panicking, it is assumed to pass. -use mojo::system::core; use mojo::system::data_pipe; use mojo::system::message_pipe; use mojo::system::shared_buffer::{self, SharedBuffer}; @@ -18,405 +17,400 @@ use mojo::system::wait_set; use mojo::system::{self, CastHandle, Handle, HandleSignals, MojoResult, SignalsState}; +use std::assert_matches::assert_matches; +use std::mem::drop; use std::string::String; use std::sync::{Arc, Condvar, Mutex}; use std::thread; use std::vec::Vec; -tests! { - fn get_time_ticks_now() { - let x = core::get_time_ticks_now(); - assert!(x >= 10); +mojo_test!(handle, { + let sb = SharedBuffer::new(1).unwrap(); + let handle = sb.as_untyped(); + unsafe { + assert_ne!(handle.get_native_handle(), 0); + assert!(handle.is_valid()); + let mut h2 = system::acquire(handle.get_native_handle()); + assert!(h2.is_valid()); + h2.invalidate(); + assert!(!h2.is_valid()); + } +}); + +mojo_test!(shared_buffer, { + let bufsize = 100; + + // Create a shared buffer and test round trip through `UntypedHandle`. + let sb_first = SharedBuffer::new(bufsize).unwrap(); + // Get original native handle to check against. + let sb_native_handle = sb_first.get_native_handle(); + + let sb_untyped = sb_first.as_untyped(); + assert_eq!(sb_untyped.get_native_handle(), sb_native_handle); + let sb = unsafe { SharedBuffer::from_untyped(sb_untyped) }; + assert_eq!(sb.get_native_handle(), sb_native_handle); + + // Check the reported size is the same as our requested size. + let size = sb.get_info().unwrap(); + assert_eq!(size, bufsize); + + // Map the buffer. + let mut buf = sb.map(0, bufsize).unwrap(); + assert_eq!(buf.len(), bufsize as usize); + buf.write(50, 34); + + // Duplicate it and drop the original handle, which should maintain the + // `buf` mapping. + let sb1 = sb.duplicate(shared_buffer::DuplicateFlags::empty()).unwrap(); + drop(sb); + + buf.write(51, 35); + + // Unmap `buf` by dropping it. + drop(buf); + + // Create a new mapping and check for what we wrote. + let buf1 = sb1.map(50, 50).unwrap(); + assert_eq!(buf1.len(), 50); + // verify buffer contents + assert_eq!(buf1.read(0), 34); + assert_eq!(buf1.read(1), 35); +}); + +mojo_test!(message_pipe, { + let (end_a, end_b) = message_pipe::create().unwrap(); + + // Extract original handle to check against. + let end_a_native_handle = end_a.get_native_handle(); + // Test casting of handle types. + let end_a_untyped = end_a.as_untyped(); + assert_eq!(end_a_untyped.get_native_handle(), end_a_native_handle); + + // Test after UntypedHandle round trip. + let end_a = unsafe { message_pipe::MessageEndpoint::from_untyped(end_a_untyped) }; + assert_eq!(end_a.get_native_handle(), end_a_native_handle); + let s: SignalsState = end_a.wait(HandleSignals::WRITABLE).satisfied().unwrap(); + assert!(s.satisfied().is_writable()); + assert!(s.satisfiable().is_readable()); + assert!(s.satisfiable().is_writable()); + assert!(s.satisfiable().is_peer_closed()); + + assert_matches!(end_a.read(), Err(mojo::MojoResult::ShouldWait)); + let hello = "hello".to_string().into_bytes(); + let write_result = end_b.write(&hello, Vec::new()); + assert_eq!(write_result, mojo::MojoResult::Okay); + let s: SignalsState = end_a.wait(HandleSignals::READABLE).satisfied().unwrap(); + assert!(s.satisfied().is_readable()); + assert!(s.satisfied().is_writable()); + assert!(s.satisfiable().is_readable()); + assert!(s.satisfiable().is_writable()); + assert!(s.satisfiable().is_peer_closed()); + + let (hello_data, _handles) = end_a.read().expect("failed to read from end_a"); + assert_eq!(String::from_utf8(hello_data), Ok("hello".to_string())); + + // Closing one endpoint should be seen by the other. + drop(end_a); + + let s: SignalsState = + end_b.wait(HandleSignals::READABLE | HandleSignals::WRITABLE).unsatisfiable().unwrap(); + assert!(s.satisfied().is_peer_closed()); + // For some reason QuotaExceeded is also set. TOOD(collinbaker): investigate. + assert!(s.satisfiable().is_peer_closed()); +}); + +mojo_test!(data_pipe, { + let (consumer, producer) = data_pipe::create_default().unwrap(); + // Extract original handle to check against + let consumer_native_handle = consumer.get_native_handle(); + let producer_native_handle = producer.get_native_handle(); + // Test casting of handle types + let consumer_untyped = consumer.as_untyped(); + let producer_untyped = producer.as_untyped(); + assert_eq!(consumer_untyped.get_native_handle(), consumer_native_handle); + assert_eq!(producer_untyped.get_native_handle(), producer_native_handle); + let consumer = unsafe { data_pipe::Consumer::<u8>::from_untyped(consumer_untyped) }; + let producer = unsafe { data_pipe::Producer::<u8>::from_untyped(producer_untyped) }; + assert_eq!(consumer.get_native_handle(), consumer_native_handle); + assert_eq!(producer.get_native_handle(), producer_native_handle); + + // Ensure the producer is writable, and check that we can wait on this + // (which should return immediately). + producer.wait(HandleSignals::WRITABLE).satisfied().unwrap(); + + // Try writing a message. + let hello = "hello".to_string().into_bytes(); + let bytes_written = producer.write(&hello, data_pipe::WriteFlags::empty()).unwrap(); + assert_eq!(bytes_written, hello.len()); + + // Try reading our message. + consumer.wait(HandleSignals::READABLE).satisfied().unwrap(); + let data_string = + String::from_utf8(consumer.read(data_pipe::ReadFlags::empty()).unwrap()).unwrap(); + assert_eq!(data_string, "hello".to_string()); + + // Test two-phase read/write, where we acquire a buffer to use then + // commit the read/write when done. + let goodbye = "goodbye".to_string().into_bytes(); + let mut write_buf = producer.begin().expect("error on write begin"); + assert!(write_buf.len() >= goodbye.len()); + std::mem::MaybeUninit::write_slice(&mut write_buf[0..goodbye.len()], &goodbye); + // SAFETY: we wrote `goodbye.len()` valid elements to `write_buf`, + // so they are initialized. + unsafe { + write_buf.commit(goodbye.len()); } - fn handle() { - let sb = SharedBuffer::new(1).unwrap(); - let handle = sb.as_untyped(); - unsafe { - assert_eq!((handle.get_native_handle() != 0), handle.is_valid()); - assert!(handle.get_native_handle() != 0 && handle.is_valid()); - let mut h2 = system::acquire(handle.get_native_handle()); - assert!(h2.is_valid()); - h2.invalidate(); - assert!(!h2.is_valid()); - } - } + // Try a two-phase read and check that we get the same result. + consumer.wait(HandleSignals::READABLE).satisfied().unwrap(); + let read_buf = consumer.begin().expect("error on read begin"); - fn shared_buffer() { - let bufsize = 100; - let sb1; - { - let mut buf; - { - let sb_c = SharedBuffer::new(bufsize).unwrap(); - // Extract original handle to check against - let sb_h = sb_c.get_native_handle(); - // Test casting of handle types - let sb_u = sb_c.as_untyped(); - assert_eq!(sb_u.get_native_handle(), sb_h); - let sb = unsafe { SharedBuffer::from_untyped(sb_u) }; - assert_eq!(sb.get_native_handle(), sb_h); - // Test map - buf = sb.map(0, bufsize).unwrap(); - assert_eq!(buf.len(), bufsize as usize); - // Test get info - let size = sb.get_info().unwrap(); - assert_eq!(size, bufsize); - buf.write(50, 34); - // Test duplicate - sb1 = sb.duplicate(shared_buffer::DuplicateFlags::empty()).unwrap(); - } - // sb gets closed - buf.write(51, 35); - } - // buf just got closed - // remap to buf1 from sb1 - let buf1 = sb1.map(50, 50).unwrap(); - assert_eq!(buf1.len(), 50); - // verify buffer contents - assert_eq!(buf1.read(0), 34); - assert_eq!(buf1.read(1), 35); - } + // Ensure we get an error when attempting another read. + assert_matches!(consumer.read(data_pipe::ReadFlags::empty()), Err(mojo::MojoResult::Busy)); - fn message_pipe() { - let (endpt, endpt1) = message_pipe::create().unwrap(); - // Extract original handle to check against - let endpt_h = endpt.get_native_handle(); - // Test casting of handle types - let endpt_u = endpt.as_untyped(); - assert_eq!(endpt_u.get_native_handle(), endpt_h); - { - let endpt0 = unsafe { message_pipe::MessageEndpoint::from_untyped(endpt_u) }; - assert_eq!(endpt0.get_native_handle(), endpt_h); - { - let s: SignalsState = endpt0.wait(HandleSignals::WRITABLE).satisfied().unwrap(); - assert!(s.satisfied().is_writable()); - assert!(s.satisfiable().is_readable()); - assert!(s.satisfiable().is_writable()); - assert!(s.satisfiable().is_peer_closed()); - } - match endpt0.read() { - Ok((_msg, _handles)) => panic!("Read should not have succeeded."), - Err(r) => assert_eq!(r, mojo::MojoResult::ShouldWait), - } - let hello = "hello".to_string().into_bytes(); - let write_result = endpt1.write(&hello, Vec::new()); - assert_eq!(write_result, mojo::MojoResult::Okay); - { - let s: SignalsState = endpt0.wait(HandleSignals::READABLE).satisfied().unwrap(); - assert!(s.satisfied().is_readable()); - assert!(s.satisfied().is_writable()); - assert!(s.satisfiable().is_readable()); - assert!(s.satisfiable().is_writable()); - assert!(s.satisfiable().is_peer_closed()); - } - let hello_data; - match endpt0.read() { - Ok((msg, _handles)) => hello_data = msg, - Err(r) => panic!("Failed to read message on endpt0, error: {}", r), - } - assert_eq!(String::from_utf8(hello_data).unwrap(), "hello".to_string()); - } - let s: SignalsState = endpt1.wait(HandleSignals::READABLE | HandleSignals::WRITABLE).unsatisfiable().unwrap(); - assert!(s.satisfied().is_peer_closed()); - // For some reason QuotaExceeded is also set. TOOD(collinbaker): investigate. - assert!(s.satisfiable().is_peer_closed()); - } + // Copy the buffer to ensure we commit the read before asserting. + let data = read_buf.to_vec(); + read_buf.commit(data.len()); - fn data_pipe() { - let (cons0, prod0) = data_pipe::create_default().unwrap(); - // Extract original handle to check against - let cons_h = cons0.get_native_handle(); - let prod_h = prod0.get_native_handle(); - // Test casting of handle types - let cons_u = cons0.as_untyped(); - let prod_u = prod0.as_untyped(); - assert_eq!(cons_u.get_native_handle(), cons_h); - assert_eq!(prod_u.get_native_handle(), prod_h); - let cons = unsafe { data_pipe::Consumer::<u8>::from_untyped(cons_u) }; - let prod = unsafe { data_pipe::Producer::<u8>::from_untyped(prod_u) }; - assert_eq!(cons.get_native_handle(), cons_h); - assert_eq!(prod.get_native_handle(), prod_h); - // Test waiting on producer - prod.wait(HandleSignals::WRITABLE).satisfied().unwrap(); - // Test one-phase read/write. - // Writing. + assert_eq!(data, goodbye); +}); + +mojo_test!(wait_set, { + let mut set = wait_set::WaitSet::new().unwrap(); + let (endpt0, endpt1) = message_pipe::create().unwrap(); + let cookie1 = wait_set::WaitSetCookie(245); + let cookie2 = wait_set::WaitSetCookie(123); + let signals = HandleSignals::READABLE; + assert_eq!(set.add(&endpt0, signals, cookie1), mojo::MojoResult::Okay); + assert_eq!(set.add(&endpt0, signals, cookie1), mojo::MojoResult::AlreadyExists); + assert_eq!(set.remove(cookie1), mojo::MojoResult::Okay); + assert_eq!(set.remove(cookie1), mojo::MojoResult::NotFound); + assert_eq!(set.add(&endpt0, signals, cookie2), mojo::MojoResult::Okay); + thread::spawn(move || { let hello = "hello".to_string().into_bytes(); - let bytes_written = prod.write(&hello, data_pipe::WriteFlags::empty()).unwrap(); - assert_eq!(bytes_written, hello.len()); - // Reading. - cons.wait(HandleSignals::READABLE).satisfied().unwrap(); - let data_string = String::from_utf8(cons.read(data_pipe::ReadFlags::empty()).unwrap()).unwrap(); - assert_eq!(data_string, "hello".to_string()); - { - // Test two-phase read/write. - // Writing. - let goodbye = "goodbye".to_string().into_bytes(); - let mut write_buf = match prod.begin() { - Ok(buf) => buf, - Err(err) => panic!("Error on write begin: {}", err), - }; - assert!(write_buf.len() >= goodbye.len()); - for i in 0..goodbye.len() { - write_buf[i].write(goodbye[i]); - } - // SAFETY: we wrote `goodbye.len()` valid elements to `write_buf`, - // so they are initialized. - unsafe { - write_buf.commit(goodbye.len()); - } - // Reading. - cons.wait(HandleSignals::READABLE).satisfied().unwrap(); - let mut data_goodbye: Vec<u8> = Vec::with_capacity(goodbye.len()); - { - let read_buf = match cons.begin() { - Ok(buf) => buf, - Err(err) => panic!("Error on read begin: {}", err), - }; - for i in 0..read_buf.len() { - data_goodbye.push(read_buf[i]); - } - match cons.read(data_pipe::ReadFlags::empty()) { - Ok(_bytes) => assert!(false), - Err(r) => assert_eq!(r, mojo::MojoResult::Busy), - } - read_buf.commit(data_goodbye.len()) - } - assert_eq!(data_goodbye.len(), goodbye.len()); - assert_eq!(String::from_utf8(data_goodbye).unwrap(), "goodbye".to_string()); - } - } + let write_result = endpt1.write(&hello, Vec::new()); + assert_eq!(write_result, mojo::MojoResult::Okay); + }); + let mut output = Vec::with_capacity(2); + let result = set.wait_on_set(&mut output); + assert_eq!(result, mojo::MojoResult::Okay); + assert_eq!(output.len(), 1); + assert_eq!(output[0].cookie, cookie2); + assert_eq!(output[0].wait_result, mojo::MojoResult::Okay); + assert!(output[0].signals_state.satisfied().is_readable()); +}); - fn wait_set() { - let mut set = wait_set::WaitSet::new().unwrap(); - let (endpt0, endpt1) = message_pipe::create().unwrap(); - let cookie1 = wait_set::WaitSetCookie(245); - let cookie2 = wait_set::WaitSetCookie(123); - let signals = HandleSignals::READABLE; - assert_eq!(set.add(&endpt0, signals, cookie1), mojo::MojoResult::Okay); - assert_eq!(set.add(&endpt0, signals, cookie1), mojo::MojoResult::AlreadyExists); - assert_eq!(set.remove(cookie1), mojo::MojoResult::Okay); - assert_eq!(set.remove(cookie1), mojo::MojoResult::NotFound); - assert_eq!(set.add(&endpt0, signals, cookie2), mojo::MojoResult::Okay); - thread::spawn(move || { - let hello = "hello".to_string().into_bytes(); - let write_result = endpt1.write(&hello, Vec::new()); - assert_eq!(write_result, mojo::MojoResult::Okay); - }); - let mut output = Vec::with_capacity(2); - let result = set.wait_on_set(&mut output); - assert_eq!(result, mojo::MojoResult::Okay); - assert_eq!(output.len(), 1); - assert_eq!(output[0].cookie, cookie2); - assert_eq!(output[0].wait_result, mojo::MojoResult::Okay); - assert!(output[0].signals_state.satisfied().is_readable()); - } +mojo_test!(trap_signals_on_readable, { + // These tests unfortunately need global state, so we have to ensure + // exclusive access (generally Rust tests run on multiple threads). + let _test_lock = TRAP_TEST_LOCK.lock().unwrap(); - fn trap_signals_on_readable() { - // These tests unfortunately need global state, so we have to ensure - // exclusive access (generally Rust tests run on multiple threads). - let _test_lock = TRAP_TEST_LOCK.lock().unwrap(); + let trap = UnsafeTrap::new(test_trap_event_handler).unwrap(); - let trap = UnsafeTrap::new(test_trap_event_handler).unwrap(); - - let (cons, prod) = data_pipe::create_default().unwrap(); - assert_eq!(MojoResult::Okay, - trap.add_trigger(cons.get_native_handle(), - HandleSignals::READABLE, - TriggerCondition::SignalsSatisfied, - 1)); - assert_eq!(MojoResult::Okay, - trap.add_trigger(prod.get_native_handle(), - HandleSignals::PEER_CLOSED, - TriggerCondition::SignalsSatisfied, - 2)); - - let mut blocking_events_buf = [std::mem::MaybeUninit::uninit(); 16]; - // The trap should arm with no blocking events since nothing should be - // triggered yet. - match trap.arm(Some(&mut blocking_events_buf)) { - ArmResult::Armed => (), - ArmResult::Blocked(events) => panic!("unexpected blocking events {:?}", events), - ArmResult::Failed(e) => panic!("unexpected mojo error {:?}", e), - } - - // Check that there are no events in the list (though of course this - // check is uncertain if a race condition bug exists). - assert_eq!(TRAP_EVENT_LIST.lock().unwrap().len(), 0); - - // Write to `prod` making `cons` readable. - assert_eq!(prod.write(&[128u8], data_pipe::WriteFlags::empty()).unwrap(), 1); - { - let list = wait_for_trap_events(TRAP_EVENT_LIST.lock().unwrap(), 1); - assert_eq!(list.len(), 1); - let event = list[0]; - assert_eq!(event.trigger_context(), 1); - assert_eq!(event.result(), MojoResult::Okay); - assert!(event.signals_state().satisfiable().is_readable(), - "{:?}", event.signals_state()); - assert!(event.signals_state().satisfied().is_readable(), - "{:?}", event.signals_state()); - } - - // Once the above event has fired, `trap` is disarmed. - - // Re-arming should block and return the event above. - match trap.arm(Some(&mut blocking_events_buf)) { - ArmResult::Blocked(events) => { - let event: &UnsafeTrapEvent = events.get(0).unwrap(); - assert_eq!(event.trigger_context(), 1); - assert_eq!(event.result(), MojoResult::Okay); - } - ArmResult::Armed => panic!("expected event did not arrive"), - ArmResult::Failed(e) => panic!("unexpected Mojo error {:?}", e), - } - - clear_trap_events(1); - - // Read the data so we don't receive the same event again. - cons.read(data_pipe::ReadFlags::DISCARD).unwrap(); - match trap.arm(Some(&mut blocking_events_buf)) { - ArmResult::Armed => (), - ArmResult::Blocked(events) => panic!("unexpected blocking events {:?}", events), - ArmResult::Failed(e) => panic!("unexpected Mojo error {:?}", e), - } - - // Close `prod` making `cons` permanently unreadable. - drop(prod); - - // Now we should have two events: one to indicate that cons will never - // be readable again, and one to indicate that `prod` has been closed - // and removed from the trap. - { - let list = wait_for_trap_events(TRAP_EVENT_LIST.lock().unwrap(), 1); - assert_eq!(list.len(), 2); - let (event1, event2) = (list[0], list[1]); - // Sort the events since the ordering isn't deterministic. - let (cons_event, prod_event) = if event1.trigger_context() == 1 { - (event1, event2) - } else { - (event2, event1) - }; - - // 1. `cons` can no longer be readable. - assert_eq!(cons_event.trigger_context(), 1); - assert_eq!(cons_event.result(), MojoResult::FailedPrecondition); - assert!(!cons_event.signals_state().satisfiable().is_readable()); - - // 2. `prod` was closed, yielding a `Cancelled` event. - assert_eq!(prod_event.trigger_context(), 2); - assert_eq!(prod_event.result(), MojoResult::Cancelled); - }; - - drop(trap); - - // We should have 3 events: the two we saw above, plus one Cancelled - // event for `prod` corresponding to removing `prod` from `trap` (which - // happens automatically on `Trap` closure). - clear_trap_events(3); - } - - fn trap_handle_closed_before_arm() { - let _test_lock = TRAP_TEST_LOCK.lock().unwrap(); - - let trap = UnsafeTrap::new(test_trap_event_handler).unwrap(); - - let (cons, _prod) = data_pipe::create_default().unwrap(); - assert_eq!(MojoResult::Okay, - trap.add_trigger(cons.get_native_handle(), - HandleSignals::READABLE, - TriggerCondition::SignalsSatisfied, 1)); - - drop(cons); - - // A cancelled event will be reported even without arming. - { - let events = wait_for_trap_events(TRAP_EVENT_LIST.lock().unwrap(), 1); - assert_eq!(events.len(), 1, "unexpected events {:?}", *events); - let event = events[0]; - assert_eq!(event.trigger_context(), 1); - assert_eq!(event.result(), MojoResult::Cancelled); - } - - drop(trap); - clear_trap_events(1); - } - - fn safe_trap() { - struct SharedContext { - events: Mutex<Vec<TrapEvent>>, - cond: Condvar, - } - - let handler = |event: &TrapEvent, context: &Arc<SharedContext>| { - if let Ok(mut events) = context.events.lock() { - events.push(*event); - context.cond.notify_all(); - } - }; - - let context = Arc::new(SharedContext { - events: Mutex::new(Vec::new()), - cond: Condvar::new(), - }); - let trap = Trap::new(handler).unwrap(); - - let (cons, prod) = data_pipe::create_default().unwrap(); - let _cons_token = trap.add_trigger( + let (cons, prod) = data_pipe::create_default().unwrap(); + assert_eq!( + MojoResult::Okay, + trap.add_trigger( cons.get_native_handle(), HandleSignals::READABLE, TriggerCondition::SignalsSatisfied, - context.clone()); - let _prod_token = trap.add_trigger( + 1 + ) + ); + assert_eq!( + MojoResult::Okay, + trap.add_trigger( prod.get_native_handle(), HandleSignals::PEER_CLOSED, TriggerCondition::SignalsSatisfied, - context.clone()); + 2 + ) + ); - assert_eq!(trap.arm(), MojoResult::Okay); + let mut blocking_events_buf = [std::mem::MaybeUninit::uninit(); 16]; + // The trap should arm with no blocking events since nothing should be + // triggered yet. + match trap.arm(Some(&mut blocking_events_buf)) { + ArmResult::Armed => (), + ArmResult::Blocked(events) => panic!("unexpected blocking events {:?}", events), + ArmResult::Failed(e) => panic!("unexpected mojo error {:?}", e), + } - // Make `cons` readable. - assert_eq!(prod.write(&[128u8], data_pipe::WriteFlags::empty()), Ok(1)); - { - let mut events = - context.cond.wait_while(context.events.lock().unwrap(), |e| e.is_empty()).unwrap(); - assert_eq!(events.len(), 1, "unexpected events {:?}", events); - let event = events[0]; - assert_eq!(event.handle(), cons.get_native_handle()); + // Check that there are no events in the list (though of course this + // check is uncertain if a race condition bug exists). + assert_eq!(TRAP_EVENT_LIST.lock().unwrap().len(), 0); + + // Write to `prod` making `cons` readable. + assert_eq!(prod.write(&[128u8], data_pipe::WriteFlags::empty()).unwrap(), 1); + { + let list = wait_for_trap_events(TRAP_EVENT_LIST.lock().unwrap(), 1); + assert_eq!(list.len(), 1); + let event = list[0]; + assert_eq!(event.trigger_context(), 1); + assert_eq!(event.result(), MojoResult::Okay); + assert!(event.signals_state().satisfiable().is_readable(), "{:?}", event.signals_state()); + assert!(event.signals_state().satisfied().is_readable(), "{:?}", event.signals_state()); + } + + // Once the above event has fired, `trap` is disarmed. + + // Re-arming should block and return the event above. + match trap.arm(Some(&mut blocking_events_buf)) { + ArmResult::Blocked(events) => { + let event: &UnsafeTrapEvent = events.get(0).unwrap(); + assert_eq!(event.trigger_context(), 1); assert_eq!(event.result(), MojoResult::Okay); - assert!(event.signals_state().satisfied().is_readable(), "{:?}", event.signals_state()); - events.clear(); } + ArmResult::Armed => panic!("expected event did not arrive"), + ArmResult::Failed(e) => panic!("unexpected Mojo error {:?}", e), + } - // Close `cons` to get two events: peer closure on `prod`, and Cancelled on `cons`. - let cons_native = cons.get_native_handle(); - drop(cons); - { - // We get the Cancelled event while unarmed. - let mut events = - context.cond.wait_while(context.events.lock().unwrap(), |e| e.is_empty()).unwrap(); - assert_eq!(events.len(), 1, "unexpected events {:?}", events); - let event = events[0]; - assert_eq!(event.handle(), cons_native); - assert_eq!(event.result(), MojoResult::Cancelled); - events.clear(); - } + clear_trap_events(1); - // When we try to arm, we'll get the `prod` event. - assert_eq!(trap.arm(), MojoResult::FailedPrecondition); - { - let mut events = - context.cond.wait_while(context.events.lock().unwrap(), |e| e.is_empty()).unwrap(); - assert_eq!(events.len(), 1, "unexpected events {:?}", events); - let event = events[0]; - assert_eq!(event.handle(), prod.get_native_handle()); - assert_eq!(event.result(), MojoResult::Okay); - assert!(event.signals_state().satisfied().is_peer_closed(), - "{:?}", event.signals_state()); - events.clear(); + // Read the data so we don't receive the same event again. + cons.read(data_pipe::ReadFlags::DISCARD).unwrap(); + match trap.arm(Some(&mut blocking_events_buf)) { + ArmResult::Armed => (), + ArmResult::Blocked(events) => panic!("unexpected blocking events {:?}", events), + ArmResult::Failed(e) => panic!("unexpected Mojo error {:?}", e), + } + + // Close `prod` making `cons` permanently unreadable. + drop(prod); + + // Now we should have two events: one to indicate that cons will never + // be readable again, and one to indicate that `prod` has been closed + // and removed from the trap. + { + let list = wait_for_trap_events(TRAP_EVENT_LIST.lock().unwrap(), 1); + assert_eq!(list.len(), 2); + let (event1, event2) = (list[0], list[1]); + // Sort the events since the ordering isn't deterministic. + let (cons_event, prod_event) = + if event1.trigger_context() == 1 { (event1, event2) } else { (event2, event1) }; + + // 1. `cons` can no longer be readable. + assert_eq!(cons_event.trigger_context(), 1); + assert_eq!(cons_event.result(), MojoResult::FailedPrecondition); + assert!(!cons_event.signals_state().satisfiable().is_readable()); + + // 2. `prod` was closed, yielding a `Cancelled` event. + assert_eq!(prod_event.trigger_context(), 2); + assert_eq!(prod_event.result(), MojoResult::Cancelled); + }; + + drop(trap); + + // We should have 3 events: the two we saw above, plus one Cancelled + // event for `prod` corresponding to removing `prod` from `trap` (which + // happens automatically on `Trap` closure). + clear_trap_events(3); +}); + +mojo_test!(trap_handle_closed_before_arm, { + let _test_lock = TRAP_TEST_LOCK.lock().unwrap(); + + let trap = UnsafeTrap::new(test_trap_event_handler).unwrap(); + + let (cons, _prod) = data_pipe::create_default().unwrap(); + assert_eq!( + MojoResult::Okay, + trap.add_trigger( + cons.get_native_handle(), + HandleSignals::READABLE, + TriggerCondition::SignalsSatisfied, + 1 + ) + ); + + drop(cons); + + // A cancelled event will be reported even without arming. + { + let events = wait_for_trap_events(TRAP_EVENT_LIST.lock().unwrap(), 1); + assert_eq!(events.len(), 1, "unexpected events {:?}", *events); + let event = events[0]; + assert_eq!(event.trigger_context(), 1); + assert_eq!(event.result(), MojoResult::Cancelled); + } + + drop(trap); + clear_trap_events(1); +}); + +mojo_test!(safe_trap, { + struct SharedContext { + events: Mutex<Vec<TrapEvent>>, + cond: Condvar, + } + + let handler = |event: &TrapEvent, context: &Arc<SharedContext>| { + if let Ok(mut events) = context.events.lock() { + events.push(*event); + context.cond.notify_all(); } - } -} + }; + + let context = Arc::new(SharedContext { events: Mutex::new(Vec::new()), cond: Condvar::new() }); + let trap = Trap::new(handler).unwrap(); + + let (cons, prod) = data_pipe::create_default().unwrap(); + let _cons_token = trap.add_trigger( + cons.get_native_handle(), + HandleSignals::READABLE, + TriggerCondition::SignalsSatisfied, + context.clone(), + ); + let _prod_token = trap.add_trigger( + prod.get_native_handle(), + HandleSignals::PEER_CLOSED, + TriggerCondition::SignalsSatisfied, + context.clone(), + ); + + assert_eq!(trap.arm(), MojoResult::Okay); + + // Make `cons` readable. + assert_eq!(prod.write(&[128u8], data_pipe::WriteFlags::empty()), Ok(1)); + { + let mut events = + context.cond.wait_while(context.events.lock().unwrap(), |e| e.is_empty()).unwrap(); + assert_eq!(events.len(), 1, "unexpected events {:?}", events); + let event = events[0]; + assert_eq!(event.handle(), cons.get_native_handle()); + assert_eq!(event.result(), MojoResult::Okay); + assert!(event.signals_state().satisfied().is_readable(), "{:?}", event.signals_state()); + events.clear(); + } + + // Close `cons` to get two events: peer closure on `prod`, and Cancelled on + // `cons`. + let cons_native = cons.get_native_handle(); + drop(cons); + { + // We get the Cancelled event while unarmed. + let mut events = + context.cond.wait_while(context.events.lock().unwrap(), |e| e.is_empty()).unwrap(); + assert_eq!(events.len(), 1, "unexpected events {:?}", events); + let event = events[0]; + assert_eq!(event.handle(), cons_native); + assert_eq!(event.result(), MojoResult::Cancelled); + events.clear(); + } + + // When we try to arm, we'll get the `prod` event. + assert_eq!(trap.arm(), MojoResult::FailedPrecondition); + { + let mut events = + context.cond.wait_while(context.events.lock().unwrap(), |e| e.is_empty()).unwrap(); + assert_eq!(events.len(), 1, "unexpected events {:?}", events); + let event = events[0]; + assert_eq!(event.handle(), prod.get_native_handle()); + assert_eq!(event.result(), MojoResult::Okay); + assert!(event.signals_state().satisfied().is_peer_closed(), "{:?}", event.signals_state()); + events.clear(); + } +}); fn clear_trap_events(expected_len: usize) { let mut list = TRAP_EVENT_LIST.lock().unwrap();
diff --git a/mojo/public/rust/tests/util/mod.rs b/mojo/public/rust/tests/util/mod.rs index 075e69754..161add8 100644 --- a/mojo/public/rust/tests/util/mod.rs +++ b/mojo/public/rust/tests/util/mod.rs
@@ -13,20 +13,21 @@ use std::slice; use std::vec::Vec; -/// This macro sets up tests by adding in Mojo embedder -/// initialization. -macro_rules! tests { - { $( $( #[ $attr:meta ] )* fn $i:ident() $b:block)* } => { +/// This macro sets up tests by adding in Mojo embedder initialization. +/// +/// Note: this macro is quite delicate because of rustmt's inconsistent handling +/// of macro invocations. Slight changes to macro syntax can make rustfmt ignore +/// the inside of an invocation, which is not what we want. +macro_rules! mojo_test { + {$i: ident, $(#[$attr:meta])* $b:block} => { + #[test] $( - #[test] - $( - #[ $attr ] - )* - fn $i() { - $crate::util::init(); - $b - } + #[ $attr ] )* + fn $i() { + $crate::util::init(); + $b + } } }
diff --git a/mojo/public/rust/tests/validation.rs b/mojo/public/rust/tests/validation.rs index 1e20f46..154fb43 100644 --- a/mojo/public/rust/tests/validation.rs +++ b/mojo/public/rust/tests/validation.rs
@@ -24,31 +24,29 @@ /// error. macro_rules! validation_tests { ($($name:ident => $req_type:ident;)*) => { - tests! { - $( - fn $name() { - let data = include_str!(concat!("../../interfaces/bindings/tests/data/validation/", + $( + mojo_test!($name, { + let data = include_str!(concat!("../../interfaces/bindings/tests/data/validation/", + stringify!($name), + ".data")); + let expected = include_str!(concat!("../../interfaces/bindings/tests/data/validation/", stringify!($name), - ".data")); - let expected = include_str!(concat!("../../interfaces/bindings/tests/data/validation/", - stringify!($name), - ".expected")).trim(); - match util::parse_validation_test(data) { - Ok((data, num_handles)) => { - let mut mock_handles = Vec::with_capacity(num_handles); - for _ in 0..num_handles { - mock_handles.push(unsafe { system::acquire(0) }); - } - match $req_type::decode_message(data, mock_handles) { - Ok(_) => panic!("Should not be valid!"), - Err(err) => assert_eq!(err.as_str(), expected), - } - }, - Err(msg) => panic!("Error: {}", msg), - } + ".expected")).trim(); + match util::parse_validation_test(data) { + Ok((data, num_handles)) => { + let mut mock_handles = Vec::with_capacity(num_handles); + for _ in 0..num_handles { + mock_handles.push(unsafe { system::acquire(0) }); + } + match $req_type::decode_message(data, mock_handles) { + Ok(_) => panic!("Should not be valid!"), + Err(err) => assert_eq!(err.as_str(), expected), + } + }, + Err(msg) => panic!("Error: {}", msg), } - )* - } + }); + )* } }
diff --git a/net/base/features.cc b/net/base/features.cc index 59a8203..7c048f8 100644 --- a/net/base/features.cc +++ b/net/base/features.cc
@@ -77,6 +77,10 @@ "EncryptedClientHello", base::FEATURE_DISABLED_BY_DEFAULT); +BASE_FEATURE(kEncryptedClientHelloQuic, + "EncryptedClientHelloQuic", + base::FEATURE_DISABLED_BY_DEFAULT); + BASE_FEATURE(kNetworkQualityEstimator, "NetworkQualityEstimator", base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/net/base/features.h b/net/base/features.h index e72d8dd..7a5062b2d 100644 --- a/net/base/features.h +++ b/net/base/features.h
@@ -98,6 +98,13 @@ // https://datatracker.ietf.org/doc/html/draft-ietf-tls-esni-13 NET_EXPORT BASE_DECLARE_FEATURE(kEncryptedClientHello); +// Enables the TLS Encrypted ClientHello feature for QUIC. Only takes effect if +// kEncryptedClientHello is also enabled. +// +// TODO(crbug.com/1287248): Remove this flag when ECH for QUIC is fully +// implemented. This flag is just a temporary mechanism for now. +NET_EXPORT BASE_DECLARE_FEATURE(kEncryptedClientHelloQuic); + // Enables optimizing the network quality estimation algorithms in network // quality estimator (NQE). NET_EXPORT BASE_DECLARE_FEATURE(kNetworkQualityEstimator);
diff --git a/net/base/isolation_info_unittest.cc b/net/base/isolation_info_unittest.cc index 13b0cf0e..91145c85 100644 --- a/net/base/isolation_info_unittest.cc +++ b/net/base/isolation_info_unittest.cc
@@ -179,10 +179,7 @@ // A 2.5-keyed NAK created with two identical opaque origins should be // same-site. -// TODO(crbug.com/1419563): Disabled as it was causing consistent failures -// across multiple builders -TEST_P(IsolationInfoTest, - DISABLED_CreateNetworkAnonymizationKeyForIsolationInfoOpaque) { +TEST_P(IsolationInfoTest, CreateNetworkAnonymizationKeyForIsolationInfoOpaque) { url::Origin opaque; IsolationInfo isolation_info = IsolationInfo::Create( IsolationInfo::RequestType::kMainFrame, opaque, opaque, @@ -194,7 +191,7 @@ if (IsDoubleKeyAndCrossSiteBitNetworkAnonymizationKeyEnabled()) { EXPECT_FALSE(nak.GetIsCrossSite().value()); } else { - EXPECT_DEATH_IF_SUPPORTED(nak.GetIsCrossSite(), ""); + EXPECT_DCHECK_DEATH(nak.GetIsCrossSite()); } url::Origin opaque2;
diff --git a/net/cert/internal/system_trust_store.cc b/net/cert/internal/system_trust_store.cc index ee580831..e3e1780 100644 --- a/net/cert/internal/system_trust_store.cc +++ b/net/cert/internal/system_trust_store.cc
@@ -185,7 +185,7 @@ std::unique_ptr<SystemTrustStore> CreateSslSystemTrustStore() { return std::make_unique<SystemTrustStoreNSS>(std::make_unique<TrustStoreNSS>( - trustSSL, TrustStoreNSS::kUseSystemTrust, + TrustStoreNSS::kUseSystemTrust, TrustStoreNSS::UseTrustFromAllUserSlots())); } @@ -194,7 +194,7 @@ std::unique_ptr<TrustStoreChrome> chrome_root) { return std::make_unique<SystemTrustStoreChrome>( std::move(chrome_root), std::make_unique<TrustStoreNSS>( - trustSSL, TrustStoreNSS::kIgnoreSystemTrust, + TrustStoreNSS::kIgnoreSystemTrust, TrustStoreNSS::UseTrustFromAllUserSlots())); } @@ -203,9 +203,9 @@ std::unique_ptr<TrustStoreChrome> chrome_root, crypto::ScopedPK11Slot user_slot_restriction) { return std::make_unique<SystemTrustStoreChrome>( - std::move(chrome_root), std::make_unique<TrustStoreNSS>( - trustSSL, TrustStoreNSS::kIgnoreSystemTrust, - std::move(user_slot_restriction))); + std::move(chrome_root), + std::make_unique<TrustStoreNSS>(TrustStoreNSS::kIgnoreSystemTrust, + std::move(user_slot_restriction))); } #endif // CHROME_ROOT_STORE_SUPPORTED @@ -213,9 +213,8 @@ std::unique_ptr<SystemTrustStore> CreateSslSystemTrustStoreNSSWithUserSlotRestriction( crypto::ScopedPK11Slot user_slot_restriction) { - return std::make_unique<SystemTrustStoreNSS>( - std::make_unique<TrustStoreNSS>(trustSSL, TrustStoreNSS::kUseSystemTrust, - std::move(user_slot_restriction))); + return std::make_unique<SystemTrustStoreNSS>(std::make_unique<TrustStoreNSS>( + TrustStoreNSS::kUseSystemTrust, std::move(user_slot_restriction))); } #elif BUILDFLAG(IS_MAC)
diff --git a/net/cert/internal/trust_store_nss.cc b/net/cert/internal/trust_store_nss.cc index 6822a21b..bc3470a 100644 --- a/net/cert/internal/trust_store_nss.cc +++ b/net/cert/internal/trust_store_nss.cc
@@ -70,28 +70,11 @@ return r; } -CK_ATTRIBUTE_TYPE SecTrustTypeToAttributeType(SECTrustType trust_type) { - switch (trust_type) { - case trustSSL: - return CKA_TRUST_SERVER_AUTH; - case trustEmail: - return CKA_TRUST_EMAIL_PROTECTION; - case trustObjectSigning: - return CKA_TRUST_CODE_SIGNING; - case trustTypeNone: - NOTREACHED(); - return 0; - } -} - } // namespace -TrustStoreNSS::TrustStoreNSS(SECTrustType trust_type, - SystemTrustSetting system_trust_setting, +TrustStoreNSS::TrustStoreNSS(SystemTrustSetting system_trust_setting, UserSlotTrustSetting user_slot_trust_setting) - : trust_type_(trust_type), - trust_attr_type_(SecTrustTypeToAttributeType(trust_type)), - ignore_system_trust_settings_(system_trust_setting == kIgnoreSystemTrust), + : ignore_system_trust_settings_(system_trust_setting == kIgnoreSystemTrust), user_slot_trust_setting_(std::move(user_slot_trust_setting)) {} TrustStoreNSS::~TrustStoreNSS() = default; @@ -316,7 +299,7 @@ crypto::ScopedSECItem trust_attr(SECITEM_AllocItem(/*arena=*/nullptr, /*item=*/nullptr, /*len=*/0)); - rv = PK11_ReadRawAttribute(PK11_TypeGeneric, obj, trust_attr_type_, + rv = PK11_ReadRawAttribute(PK11_TypeGeneric, obj, CKA_TRUST_SERVER_AUTH, trust_attr.get()); if (rv != SECSuccess) { DVLOG(1) << "trust object for " << base::HexEncode(trust_obj_sha1) @@ -423,7 +406,7 @@ CertificateTrust TrustStoreNSS::GetTrustForNSSTrust( const CERTCertTrust& trust) const { - unsigned int trust_flags = SEC_GET_TRUST_FLAGS(&trust, trust_type_); + unsigned int trust_flags = SEC_GET_TRUST_FLAGS(&trust, trustSSL); // Determine if the certificate is distrusted. if ((trust_flags & (CERTDB_TERMINAL_RECORD | CERTDB_TRUSTED_CA |
diff --git a/net/cert/internal/trust_store_nss.h b/net/cert/internal/trust_store_nss.h index 67d2fc3..d37b482 100644 --- a/net/cert/internal/trust_store_nss.h +++ b/net/cert/internal/trust_store_nss.h
@@ -29,7 +29,7 @@ absl::variant<UseTrustFromAllUserSlots, crypto::ScopedPK11Slot>; // Creates a TrustStoreNSS which will find anchors that are trusted for - // |trust_type|. + // SSL server auth. // // |system_trust_setting| configures the use of trust from the builtin roots. // If |system_trust_setting| is kIgnoreSystemTrust, trust settings from the @@ -39,8 +39,7 @@ // * UseTrustFromAllUserSlots: all user slots will be allowed. // * nullptr: no user slots will be allowed. // * non-null PK11Slot: the specified slot will be allowed. - TrustStoreNSS(SECTrustType trust_type, - SystemTrustSetting system_trust_setting, + TrustStoreNSS(SystemTrustSetting system_trust_setting, UserSlotTrustSetting user_slot_trust_setting); TrustStoreNSS(const TrustStoreNSS&) = delete; @@ -67,9 +66,6 @@ const ParsedCertificate* cert, base::SupportsUserData* debug_data) const; - const SECTrustType trust_type_; - const CK_ATTRIBUTE_TYPE trust_attr_type_; - // |ignore_system_certs_trust_settings_| specifies if the system trust // settings should be considered when determining a cert's trustworthiness. const bool ignore_system_trust_settings_ = false;
diff --git a/net/cert/internal/trust_store_nss_unittest.cc b/net/cert/internal/trust_store_nss_unittest.cc index bb1218c..c2a8133 100644 --- a/net/cert/internal/trust_store_nss_unittest.cc +++ b/net/cert/internal/trust_store_nss_unittest.cc
@@ -487,15 +487,14 @@ switch (slot_filter_type()) { case SlotFilterType::kDontFilter: return std::make_unique<TrustStoreNSS>( - trustSSL, system_trust_setting(), - TrustStoreNSS::UseTrustFromAllUserSlots()); + system_trust_setting(), TrustStoreNSS::UseTrustFromAllUserSlots()); case SlotFilterType::kDoNotAllowUserSlots: return std::make_unique<TrustStoreNSS>( - trustSSL, system_trust_setting(), + system_trust_setting(), /*user_slot_trust_setting=*/nullptr); case SlotFilterType::kAllowSpecifiedUserSlot: return std::make_unique<TrustStoreNSS>( - trustSSL, system_trust_setting(), + system_trust_setting(), crypto::ScopedPK11Slot(PK11_ReferenceSlot(test_nssdb_.slot()))); } } @@ -570,7 +569,7 @@ std::unique_ptr<TrustStoreNSS> CreateTrustStoreNSS() override { return std::make_unique<TrustStoreNSS>( - trustSSL, TrustStoreNSS::kIgnoreSystemTrust, + TrustStoreNSS::kIgnoreSystemTrust, TrustStoreNSS::UseTrustFromAllUserSlots()); } }; @@ -777,7 +776,7 @@ std::unique_ptr<TrustStoreNSS> CreateTrustStoreNSS() override { return std::make_unique<TrustStoreNSS>( - trustSSL, TrustStoreNSS::kUseSystemTrust, + TrustStoreNSS::kUseSystemTrust, TrustStoreNSS::UseTrustFromAllUserSlots()); } }; @@ -915,7 +914,7 @@ } std::unique_ptr<TrustStoreNSS> CreateTrustStoreNSS() override { - return std::make_unique<TrustStoreNSS>(trustSSL, system_trust_setting(), + return std::make_unique<TrustStoreNSS>(system_trust_setting(), /*user_slot_trust_setting=*/nullptr); } }; @@ -982,7 +981,7 @@ std::unique_ptr<TrustStoreNSS> CreateTrustStoreNSS() override { return std::make_unique<TrustStoreNSS>( - trustSSL, system_trust_setting(), + system_trust_setting(), crypto::ScopedPK11Slot(PK11_ReferenceSlot(test_nssdb_.slot()))); } }; @@ -1084,8 +1083,7 @@ class TrustStoreNSSTestDelegate { public: TrustStoreNSSTestDelegate() - : trust_store_nss_(trustSSL, - TrustStoreNSS::kUseSystemTrust, + : trust_store_nss_(TrustStoreNSS::kUseSystemTrust, TrustStoreNSS::UseTrustFromAllUserSlots()) {} void AddCert(std::shared_ptr<const ParsedCertificate> cert) {
diff --git a/net/quic/bidirectional_stream_quic_impl_unittest.cc b/net/quic/bidirectional_stream_quic_impl_unittest.cc index 0804b96d..95a93d7 100644 --- a/net/quic/bidirectional_stream_quic_impl_unittest.cc +++ b/net/quic/bidirectional_stream_quic_impl_unittest.cc
@@ -21,6 +21,7 @@ #include "net/base/load_timing_info.h" #include "net/base/load_timing_info_test_util.h" #include "net/base/net_errors.h" +#include "net/dns/public/host_resolver_results.h" #include "net/dns/public/secure_dns_policy.h" #include "net/http/bidirectional_stream_request_info.h" #include "net/http/transport_security_state.h" @@ -44,6 +45,7 @@ #include "net/quic/test_quic_crypto_client_config_handle.h" #include "net/quic/test_task_runner.h" #include "net/socket/socket_test_util.h" +#include "net/ssl/ssl_config_service_defaults.h" #include "net/test/gtest_util.h" #include "net/test/test_with_task_environment.h" #include "net/third_party/quiche/src/quiche/common/quiche_text_utils.h" @@ -512,7 +514,7 @@ session_ = std::make_unique<QuicChromiumClientSession>( connection_, std::move(socket), /*stream_factory=*/nullptr, &crypto_client_stream_factory_, &clock_, - &transport_security_state_, /*ssl_config_service=*/nullptr, + &transport_security_state_, &ssl_config_service_, base::WrapUnique(static_cast<QuicServerInfo*>(nullptr)), QuicSessionKey(kDefaultServerHostName, kDefaultServerPort, PRIVACY_MODE_DISABLED, SocketTag(), @@ -537,7 +539,8 @@ std::make_unique<quic::QuicClientPushPromiseIndex>(), nullptr, base::DefaultTickClock::GetInstance(), base::SingleThreadTaskRunner::GetCurrentDefault().get(), - /*socket_performance_watcher=*/nullptr, NetLog::Get()); + /*socket_performance_watcher=*/nullptr, HostResolverEndpointResult(), + NetLog::Get()); session_->Initialize(); // Blackhole QPACK decoder stream instead of constructing mock writes. @@ -780,6 +783,7 @@ std::unique_ptr<QuicChromiumConnectionHelper> helper_; std::unique_ptr<QuicChromiumAlarmFactory> alarm_factory_; TransportSecurityState transport_security_state_; + SSLConfigServiceDefaults ssl_config_service_; std::unique_ptr<QuicChromiumClientSession> session_; quic::QuicCryptoClientConfig crypto_config_; HttpRequestHeaders headers_;
diff --git a/net/quic/quic_chromium_client_session.cc b/net/quic/quic_chromium_client_session.cc index b4844da..0a3a15f5 100644 --- a/net/quic/quic_chromium_client_session.cc +++ b/net/quic/quic_chromium_client_session.cc
@@ -35,6 +35,7 @@ #include "net/base/privacy_mode.h" #include "net/base/url_util.h" #include "net/cert/signed_certificate_timestamp_and_status.h" +#include "net/dns/public/host_resolver_results.h" #include "net/http/transport_security_state.h" #include "net/log/net_log_event_type.h" #include "net/log/net_log_source_type.h" @@ -998,6 +999,7 @@ const base::TickClock* tick_clock, base::SequencedTaskRunner* task_runner, std::unique_ptr<SocketPerformanceWatcher> socket_performance_watcher, + const HostResolverEndpointResult& endpoint_result, NetLog* net_log) : quic::QuicSpdyClientSessionBase(connection, /*visitor=*/nullptr, @@ -1040,7 +1042,8 @@ http3_logger_(std::make_unique<QuicHttp3Logger>(net_log_)), push_delegate_(push_delegate), push_promise_index_(std::move(push_promise_index)), - path_validation_writer_delegate_(this, task_runner_) { + path_validation_writer_delegate_(this, task_runner_), + ech_config_list_(endpoint_result.metadata.ech_config_list) { default_network_ = default_network; auto* socket_raw = socket.get(); sockets_.push_back(std::move(socket)); @@ -1440,6 +1443,7 @@ ssl_info->key_exchange_group = crypto_params.key_exchange_group; ssl_info->peer_signature_algorithm = crypto_params.peer_signature_algorithm; + ssl_info->encrypted_client_hello = crypto_params.encrypted_client_hello; return true; } @@ -1653,6 +1657,18 @@ } } +quic::QuicSSLConfig QuicChromiumClientSession::GetSSLConfig() const { + quic::QuicSSLConfig config = quic::QuicSpdyClientSessionBase::GetSSLConfig(); + if (ssl_config_service_->GetSSLContextConfig() + .EncryptedClientHelloEnabled() && + base::FeatureList::IsEnabled(features::kEncryptedClientHelloQuic)) { + config.ech_grease_enabled = true; + config.ech_config_list.assign(ech_config_list_.begin(), + ech_config_list_.end()); + } + return config; +} + void QuicChromiumClientSession::OnConfigNegotiated() { quic::QuicSpdyClientSessionBase::OnConfigNegotiated(); if (!stream_factory_ || !stream_factory_->allow_server_migration()) {
diff --git a/net/quic/quic_chromium_client_session.h b/net/quic/quic_chromium_client_session.h index fac69b4..604b5e3 100644 --- a/net/quic/quic_chromium_client_session.h +++ b/net/quic/quic_chromium_client_session.h
@@ -65,6 +65,7 @@ class CertVerifyResult; class DatagramClientSocket; +struct HostResolverEndpointResult; class NetLog; class QuicCryptoClientStreamFactory; class QuicServerInfo; @@ -623,6 +624,7 @@ const base::TickClock* tick_clock, base::SequencedTaskRunner* task_runner, std::unique_ptr<SocketPerformanceWatcher> socket_performance_watcher, + const HostResolverEndpointResult& endpoint_result, NetLog* net_log); QuicChromiumClientSession(const QuicChromiumClientSession&) = delete; @@ -727,6 +729,7 @@ const quic::CryptoHandshakeMessage& message) override; void OnGoAway(const quic::QuicGoAwayFrame& frame) override; void OnCanCreateNewOutgoingStream(bool unidirectional) override; + quic::QuicSSLConfig GetSSLConfig() const override; // QuicSpdyClientSessionBase methods: void OnConfigNegotiated() override; @@ -1173,6 +1176,8 @@ base::flat_map<url::SchemeHostPort, std::string> accept_ch_entries_received_via_alps_; + std::vector<uint8_t> ech_config_list_; + base::WeakPtrFactory<QuicChromiumClientSession> weak_factory_{this}; };
diff --git a/net/quic/quic_chromium_client_session_test.cc b/net/quic/quic_chromium_client_session_test.cc index 77c17c217..62b1d98 100644 --- a/net/quic/quic_chromium_client_session_test.cc +++ b/net/quic/quic_chromium_client_session_test.cc
@@ -20,6 +20,7 @@ #include "net/base/schemeful_site.h" #include "net/base/test_completion_callback.h" #include "net/cert/cert_verify_result.h" +#include "net/dns/public/host_resolver_results.h" #include "net/dns/public/secure_dns_policy.h" #include "net/http/transport_security_state.h" #include "net/http/transport_security_state_test_util.h" @@ -46,6 +47,7 @@ #include "net/socket/datagram_client_socket.h" #include "net/socket/socket_test_util.h" #include "net/spdy/spdy_test_util_common.h" +#include "net/ssl/ssl_config_service_defaults.h" #include "net/test/cert_test_util.h" #include "net/test/gtest_util.h" #include "net/test/test_data_directory.h" @@ -168,7 +170,7 @@ session_ = std::make_unique<TestingQuicChromiumClientSession>( connection, std::move(socket), /*stream_factory=*/nullptr, &crypto_client_stream_factory_, &clock_, - transport_security_state_.get(), /*ssl_config_service=*/nullptr, + transport_security_state_.get(), &ssl_config_service_, base::WrapUnique(static_cast<QuicServerInfo*>(nullptr)), session_key_, /*require_confirmation=*/false, migrate_session_early_v2_, /*migrate_session_on_network_change_v2=*/false, default_network_, @@ -187,7 +189,8 @@ std::make_unique<quic::QuicClientPushPromiseIndex>(), &test_push_delegate_, base::DefaultTickClock::GetInstance(), base::SingleThreadTaskRunner::GetCurrentDefault().get(), - /*socket_performance_watcher=*/nullptr, NetLog::Get()); + /*socket_performance_watcher=*/nullptr, HostResolverEndpointResult(), + NetLog::Get()); if (connectivity_monitor_) { connectivity_monitor_->SetInitialDefaultNetwork(default_network_); session_->AddConnectivityObserver(connectivity_monitor_.get()); @@ -263,6 +266,7 @@ quic::test::MockAlarmFactory alarm_factory_; std::unique_ptr<TransportSecurityState> transport_security_state_; MockCryptoClientStreamFactory crypto_client_stream_factory_; + SSLConfigServiceDefaults ssl_config_service_; QuicSessionKey session_key_; url::SchemeHostPort destination_; std::unique_ptr<TestingQuicChromiumClientSession> session_;
diff --git a/net/quic/quic_http_stream_test.cc b/net/quic/quic_http_stream_test.cc index 7cc35e4..b6c66a2 100644 --- a/net/quic/quic_http_stream_test.cc +++ b/net/quic/quic_http_stream_test.cc
@@ -29,6 +29,7 @@ #include "net/base/net_errors.h" #include "net/base/test_completion_callback.h" #include "net/base/upload_bytes_element_reader.h" +#include "net/dns/public/host_resolver_results.h" #include "net/dns/public/secure_dns_policy.h" #include "net/http/http_response_headers.h" #include "net/http/transport_security_state.h" @@ -55,6 +56,7 @@ #include "net/socket/socket_performance_watcher.h" #include "net/socket/socket_test_util.h" #include "net/spdy/spdy_http_utils.h" +#include "net/ssl/ssl_config_service_defaults.h" #include "net/test/cert_test_util.h" #include "net/test/gtest_util.h" #include "net/test/test_data_directory.h" @@ -397,7 +399,7 @@ session_ = std::make_unique<QuicChromiumClientSession>( connection_, std::move(socket), /*stream_factory=*/nullptr, &crypto_client_stream_factory_, &clock_, - &transport_security_state_, /*ssl_config_service=*/nullptr, + &transport_security_state_, &ssl_config_service_, base::WrapUnique(static_cast<QuicServerInfo*>(nullptr)), QuicSessionKey(kDefaultServerHostName, kDefaultServerPort, PRIVACY_MODE_DISABLED, SocketTag(), @@ -422,7 +424,8 @@ std::make_unique<quic::QuicClientPushPromiseIndex>(), nullptr, base::DefaultTickClock::GetInstance(), base::SingleThreadTaskRunner::GetCurrentDefault().get(), - /*socket_performance_watcher=*/nullptr, NetLog::Get()); + /*socket_performance_watcher=*/nullptr, HostResolverEndpointResult(), + NetLog::Get()); session_->Initialize(); // Blackhole QPACK decoder stream instead of constructing mock writes. @@ -650,6 +653,7 @@ std::unique_ptr<UploadDataStream> upload_data_stream_; std::unique_ptr<QuicHttpStream> stream_; TransportSecurityState transport_security_state_; + SSLConfigServiceDefaults ssl_config_service_; // Must outlive `send_algorithm_` and `connection_`. std::unique_ptr<QuicChromiumClientSession> session_;
diff --git a/net/quic/quic_proxy_client_socket_unittest.cc b/net/quic/quic_proxy_client_socket_unittest.cc index 4a0759d..d71af46b 100644 --- a/net/quic/quic_proxy_client_socket_unittest.cc +++ b/net/quic/quic_proxy_client_socket_unittest.cc
@@ -21,6 +21,7 @@ #include "net/base/proxy_string_util.h" #include "net/base/test_proxy_delegate.h" #include "net/dns/mock_host_resolver.h" +#include "net/dns/public/host_resolver_results.h" #include "net/dns/public/secure_dns_policy.h" #include "net/http/http_auth_cache.h" #include "net/http/http_auth_handler_factory.h" @@ -46,6 +47,7 @@ #include "net/quic/test_quic_crypto_client_config_handle.h" #include "net/quic/test_task_runner.h" #include "net/socket/socket_test_util.h" +#include "net/ssl/ssl_config_service_defaults.h" #include "net/test/cert_test_util.h" #include "net/test/gtest_util.h" #include "net/test/test_data_directory.h" @@ -233,7 +235,7 @@ session_ = std::make_unique<QuicChromiumClientSession>( connection, std::move(socket), /*stream_factory=*/nullptr, &crypto_client_stream_factory_, &clock_, - &transport_security_state_, /*ssl_config_service=*/nullptr, + &transport_security_state_, &ssl_config_service_, base::WrapUnique(static_cast<QuicServerInfo*>(nullptr)), QuicSessionKey("mail.example.org", 80, PRIVACY_MODE_DISABLED, SocketTag(), NetworkAnonymizationKey(), @@ -258,7 +260,8 @@ std::make_unique<quic::QuicClientPushPromiseIndex>(), nullptr, base::DefaultTickClock::GetInstance(), base::SingleThreadTaskRunner::GetCurrentDefault().get(), - /*socket_performance_watcher=*/nullptr, NetLog::Get()); + /*socket_performance_watcher=*/nullptr, HostResolverEndpointResult(), + NetLog::Get()); writer->set_delegate(session_.get()); @@ -594,6 +597,7 @@ std::unique_ptr<QuicChromiumAlarmFactory> alarm_factory_; testing::StrictMock<quic::test::MockQuicConnectionVisitor> visitor_; TransportSecurityState transport_security_state_; + SSLConfigServiceDefaults ssl_config_service_; quic::QuicCryptoClientConfig crypto_config_; const quic::QuicConnectionId connection_id_;
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc index b6715ef6..a84782cf 100644 --- a/net/quic/quic_stream_factory.cc +++ b/net/quic/quic_stream_factory.cc
@@ -475,6 +475,10 @@ // `endpoint_result` came from A/AAAA records directly, without HTTPS/SVCB // records. If we know the QUIC ALPN to use externally, i.e. via Alt-Svc, // use it. Otherwise, `endpoint_result` is not eligible for QUIC. + // + // TODO(https://crbug.com/1287248): If all routes have ECH configs, and + // ECH is enabled, we should switch to a SVCB-reliant mode. See + // draft-ietf-dnsop-svcb-https-11, section 10.1. return quic_version_; } @@ -2160,7 +2164,7 @@ dns_resolution_end_time, std::make_unique<quic::QuicClientPushPromiseIndex>(), push_delegate_, tick_clock_, task_runner_, std::move(socket_performance_watcher), - net_log.net_log()); + endpoint_result, net_log.net_log()); all_sessions_[*session] = key; // owning pointer writer->set_delegate(*session);
diff --git a/net/quic/quic_stream_factory_test.cc b/net/quic/quic_stream_factory_test.cc index 7fcf74e..d9392191 100644 --- a/net/quic/quic_stream_factory_test.cc +++ b/net/quic/quic_stream_factory_test.cc
@@ -60,7 +60,7 @@ #include "net/socket/socket_test_util.h" #include "net/spdy/spdy_session_test_util.h" #include "net/spdy/spdy_test_util_common.h" -#include "net/ssl/ssl_config_service_defaults.h" +#include "net/ssl/test_ssl_config_service.h" #include "net/test/cert_test_util.h" #include "net/test/gtest_util.h" #include "net/test/test_data_directory.h" @@ -245,12 +245,14 @@ class QuicStreamFactoryTestBase : public WithTaskEnvironment { protected: - QuicStreamFactoryTestBase(quic::ParsedQuicVersion version, - bool enable_quic_priority_incremental_support) + QuicStreamFactoryTestBase( + quic::ParsedQuicVersion version, + bool enable_quic_priority_incremental_support, + std::vector<base::test::FeatureRef> enabled_features = {}, + std::vector<base::test::FeatureRef> disabled_features = {}) : host_resolver_(std::make_unique<MockHostResolver>( /*default_result=*/MockHostResolverBase::RuleResolver:: GetLocalhostResult())), - ssl_config_service_(std::make_unique<SSLConfigServiceDefaults>()), socket_factory_(std::make_unique<MockClientSocketFactory>()), runner_(base::MakeRefCounted<TestTaskRunner>(context_.mock_clock())), version_(version), @@ -281,9 +283,12 @@ &QuicStreamFactoryTestBase::OnFailedOnDefaultNetwork, base::Unretained(this))), quic_params_(context_.params()) { - scoped_feature_list_.InitWithFeatureState( - features::kPriorityIncremental, - enable_quic_priority_incremental_support); + if (enable_quic_priority_incremental_support) { + enabled_features.push_back(features::kPriorityIncremental); + } else { + disabled_features.push_back(features::kPriorityIncremental); + } + scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features); FLAGS_quic_enable_http3_grease_randomness = false; context_.AdvanceTime(quic::QuicTime::Delta::FromSeconds(1)); } @@ -291,7 +296,7 @@ void Initialize() { DCHECK(!factory_); factory_ = std::make_unique<QuicStreamFactory>( - net_log_.net_log(), host_resolver_.get(), ssl_config_service_.get(), + net_log_.net_log(), host_resolver_.get(), &ssl_config_service_, socket_factory_.get(), http_server_properties_.get(), cert_verifier_.get(), &ct_policy_enforcer_, &transport_security_state_, /*sct_auditing_delegate=*/nullptr, @@ -959,7 +964,7 @@ quic::test::QuicFlagSaver flags_; // Save/restore all QUIC flag values. std::unique_ptr<MockHostResolverBase> host_resolver_; - std::unique_ptr<SSLConfigService> ssl_config_service_; + TestSSLConfigService ssl_config_service_{SSLContextConfig()}; std::unique_ptr<MockClientSocketFactory> socket_factory_; MockCryptoClientStreamFactory crypto_client_stream_factory_; MockQuicContext context_; @@ -2425,7 +2430,7 @@ TEST_P(QuicStreamFactoryTest, CloseSessionDuringCreation) { quic_params_->close_sessions_on_ip_change = true; auto factory = MockQuicStreamFactory( - net_log_.net_log(), host_resolver_.get(), ssl_config_service_.get(), + net_log_.net_log(), host_resolver_.get(), &ssl_config_service_, socket_factory_.get(), http_server_properties_.get(), cert_verifier_.get(), &ct_policy_enforcer_, &transport_security_state_, /*sct_auditing_delegate=*/nullptr, @@ -15338,4 +15343,180 @@ EXPECT_EQ(expected_dns_aliases2_, stream2->GetDnsAliases()); } +class QuicStreamFactoryEchTest : public QuicStreamFactoryTestBase, + public ::testing::TestWithParam<TestParams> { + protected: + QuicStreamFactoryEchTest() + : QuicStreamFactoryTestBase( + GetParam().version, + GetParam().enable_quic_priority_incremental_support, + /*enabled_features=*/ + {features::kEncryptedClientHello, + features::kEncryptedClientHelloQuic}) {} +}; + +INSTANTIATE_TEST_SUITE_P(VersionIncludeStreamDependencySequence, + QuicStreamFactoryEchTest, + ::testing::ValuesIn(GetTestParams()), + ::testing::PrintToStringParamName()); + +// Test that, even if DNS does not provide ECH keys, ECH GREASE is enabled. +TEST_P(QuicStreamFactoryEchTest, EchGrease) { + Initialize(); + ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); + crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); + + MockQuicData socket_data(version_); + socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); + socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); + socket_data.AddSocketDataToFactory(socket_factory_.get()); + + QuicStreamRequest request(factory_.get()); + EXPECT_EQ(ERR_IO_PENDING, + request.Request( + scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY, + SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, + /*use_dns_aliases=*/true, /*require_dns_https_alpn=*/false, + /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, + failed_on_default_network_callback_, callback_.callback())); + + EXPECT_THAT(callback_.WaitForResult(), IsOk()); + + QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + ASSERT_TRUE(session); + quic::QuicSSLConfig config = session->GetSSLConfig(); + EXPECT_TRUE(config.ech_grease_enabled); + EXPECT_TRUE(config.ech_config_list.empty()); +} + +// Test that, connections where we discover QUIC from Alt-Svc (as opposed to +// HTTPS-RR), ECH is picked up from DNS. +TEST_P(QuicStreamFactoryEchTest, EchWithQuicFromAltSvc) { + HostResolverEndpointResult endpoint; + endpoint.ip_endpoints = {IPEndPoint(IPAddress::IPv4Localhost(), 0)}; + endpoint.metadata.supported_protocol_alpns = {quic::AlpnForVersion(version_)}; + endpoint.metadata.ech_config_list = {1, 2, 3, 4}; + + host_resolver_ = std::make_unique<MockHostResolver>(); + host_resolver_->rules()->AddRule( + scheme_host_port_.host(), + MockHostResolverBase::RuleResolver::RuleResult({endpoint})); + + Initialize(); + ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); + crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); + + MockQuicData socket_data(version_); + socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); + socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); + socket_data.AddSocketDataToFactory(socket_factory_.get()); + + QuicStreamRequest request(factory_.get()); + EXPECT_EQ(ERR_IO_PENDING, + request.Request( + scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY, + SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, + /*use_dns_aliases=*/true, /*require_dns_https_alpn=*/false, + /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, + failed_on_default_network_callback_, callback_.callback())); + ASSERT_THAT(callback_.WaitForResult(), IsOk()); + + QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + ASSERT_TRUE(session); + quic::QuicSSLConfig config = session->GetSSLConfig(); + EXPECT_EQ(std::string(endpoint.metadata.ech_config_list.begin(), + endpoint.metadata.ech_config_list.end()), + config.ech_config_list); +} + +// Test that, connections where we discover QUIC from HTTPS-RR (as opposed to +// Alt-Svc), ECH is picked up from DNS. +TEST_P(QuicStreamFactoryEchTest, EchWithQuicFromHttpsRecord) { + quic_params_->supported_versions = {version_}; + HostResolverEndpointResult endpoint; + endpoint.ip_endpoints = {IPEndPoint(IPAddress::IPv4Localhost(), 0)}; + endpoint.metadata.supported_protocol_alpns = {quic::AlpnForVersion(version_)}; + endpoint.metadata.ech_config_list = {1, 2, 3, 4}; + + host_resolver_ = std::make_unique<MockHostResolver>(); + host_resolver_->rules()->AddRule( + scheme_host_port_.host(), + MockHostResolverBase::RuleResolver::RuleResult({endpoint})); + + Initialize(); + ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); + crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); + + MockQuicData socket_data(version_); + socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); + socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); + socket_data.AddSocketDataToFactory(socket_factory_.get()); + + QuicStreamRequest request(factory_.get()); + EXPECT_EQ(ERR_IO_PENDING, + request.Request( + scheme_host_port_, quic::ParsedQuicVersion::Unsupported(), + privacy_mode_, DEFAULT_PRIORITY, SocketTag(), + NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, + /*use_dns_aliases=*/true, /*require_dns_https_alpn=*/true, + /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, + failed_on_default_network_callback_, callback_.callback())); + ASSERT_THAT(callback_.WaitForResult(), IsOk()); + + QuicChromiumClientSession* session = + GetActiveSession(scheme_host_port_, NetworkAnonymizationKey(), + /*require_dns_https_alpn=*/true); + ASSERT_TRUE(session); + quic::QuicSSLConfig config = session->GetSSLConfig(); + EXPECT_EQ(std::string(endpoint.metadata.ech_config_list.begin(), + endpoint.metadata.ech_config_list.end()), + config.ech_config_list); +} + +// Test that, when ECH is disabled, neither ECH nor ECH GREASE are configured. +TEST_P(QuicStreamFactoryEchTest, EchDisabled) { + quic_params_->supported_versions = {version_}; + HostResolverEndpointResult endpoint; + endpoint.ip_endpoints = {IPEndPoint(IPAddress::IPv4Localhost(), 0)}; + endpoint.metadata.supported_protocol_alpns = {quic::AlpnForVersion(version_)}; + endpoint.metadata.ech_config_list = {1, 2, 3, 4}; + + host_resolver_ = std::make_unique<MockHostResolver>(); + host_resolver_->rules()->AddRule( + scheme_host_port_.host(), + MockHostResolverBase::RuleResolver::RuleResult({endpoint})); + + SSLContextConfig ssl_config; + ssl_config.ech_enabled = false; + ssl_config_service_.UpdateSSLConfigAndNotify(ssl_config); + + Initialize(); + ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); + crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); + + MockQuicData socket_data(version_); + socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); + socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); + socket_data.AddSocketDataToFactory(socket_factory_.get()); + + QuicStreamRequest request(factory_.get()); + EXPECT_EQ(ERR_IO_PENDING, + request.Request( + scheme_host_port_, quic::ParsedQuicVersion::Unsupported(), + privacy_mode_, DEFAULT_PRIORITY, SocketTag(), + NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, + /*use_dns_aliases=*/true, /*require_dns_https_alpn=*/true, + /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, + failed_on_default_network_callback_, callback_.callback())); + ASSERT_THAT(callback_.WaitForResult(), IsOk()); + + QuicChromiumClientSession* session = + GetActiveSession(scheme_host_port_, NetworkAnonymizationKey(), + /*require_dns_https_alpn=*/true); + ASSERT_TRUE(session); + quic::QuicSSLConfig config = session->GetSSLConfig(); + EXPECT_TRUE(config.ech_config_list.empty()); + EXPECT_FALSE(config.ech_grease_enabled); +} + } // namespace net::test
diff --git a/net/socket/socket_options.cc b/net/socket/socket_options.cc index 4b880c5..409fe5b 100644 --- a/net/socket/socket_options.cc +++ b/net/socket/socket_options.cc
@@ -64,7 +64,9 @@ int os_error = errno; #endif int net_error = (rv == -1) ? MapSystemError(os_error) : OK; - DCHECK(!rv) << "Could not set socket receive buffer size: " << net_error; + if (net_error != OK) { + DLOG(ERROR) << "Could not set socket receive buffer size: " << net_error; + } return net_error; } @@ -77,7 +79,9 @@ int os_error = errno; #endif int net_error = (rv == -1) ? MapSystemError(os_error) : OK; - DCHECK(!rv) << "Could not set socket receive buffer size: " << net_error; + if (net_error != OK) { + DLOG(ERROR) << "Could not set socket send buffer size: " << net_error; + } return net_error; }
diff --git a/net/socket/ssl_client_socket.cc b/net/socket/ssl_client_socket.cc index 057e829..eee2955 100644 --- a/net/socket/ssl_client_socket.cc +++ b/net/socket/ssl_client_socket.cc
@@ -6,10 +6,8 @@ #include <string> -#include "base/feature_list.h" #include "base/logging.h" #include "base/observer_list.h" -#include "net/base/features.h" #include "net/socket/ssl_client_socket_impl.h" #include "net/socket/stream_socket.h" #include "net/ssl/ssl_client_session_cache.h" @@ -78,11 +76,6 @@ CertDatabase::GetInstance()->RemoveObserver(this); } -bool SSLClientContext::EncryptedClientHelloEnabled() const { - return config_.ech_enabled && - base::FeatureList::IsEnabled(features::kEncryptedClientHello); -} - std::unique_ptr<SSLClientSocket> SSLClientContext::CreateSSLClientSocket( std::unique_ptr<StreamSocket> stream_socket, const HostPortPair& host_and_port,
diff --git a/net/socket/ssl_client_socket.h b/net/socket/ssl_client_socket.h index 8aade61a..a7a77a1 100644 --- a/net/socket/ssl_client_socket.h +++ b/net/socket/ssl_client_socket.h
@@ -134,10 +134,6 @@ return sct_auditing_delegate_; } - // Returns whether ECH (Encrypted ClientHello) should be enabled. This - // function checks both config() and feature flags. - bool EncryptedClientHelloEnabled() const; - // Creates a new SSLClientSocket which can then be used to establish an SSL // connection to |host_and_port| over the already-connected |stream_socket|. std::unique_ptr<SSLClientSocket> CreateSSLClientSocket(
diff --git a/net/socket/ssl_client_socket_impl.cc b/net/socket/ssl_client_socket_impl.cc index 2d8c28d..a0af2fcf 100644 --- a/net/socket/ssl_client_socket_impl.cc +++ b/net/socket/ssl_client_socket_impl.cc
@@ -916,11 +916,11 @@ host_and_port_, &client_cert_, &client_private_key_); } - if (context_->EncryptedClientHelloEnabled()) { + if (context_->config().EncryptedClientHelloEnabled()) { SSL_set_enable_ech_grease(ssl_.get(), 1); } if (!ssl_config_.ech_config_list.empty()) { - DCHECK(context_->EncryptedClientHelloEnabled()); + DCHECK(context_->config().EncryptedClientHelloEnabled()); net_log_.AddEvent(NetLogEventType::SSL_ECH_CONFIG_LIST, [&] { base::Value::Dict dict; dict.Set("bytes", NetLogBinaryValue(ssl_config_.ech_config_list));
diff --git a/net/socket/ssl_connect_job.cc b/net/socket/ssl_connect_job.cc index a5fe097..66889dd42 100644 --- a/net/socket/ssl_connect_job.cc +++ b/net/socket/ssl_connect_job.cc
@@ -277,7 +277,7 @@ absl::optional<TransportConnectJob::EndpointResultOverride> endpoint_result_override; if (ech_retry_configs_) { - DCHECK(ssl_client_context()->EncryptedClientHelloEnabled()); + DCHECK(ssl_client_context()->config().EncryptedClientHelloEnabled()); DCHECK(endpoint_result_); endpoint_result_override.emplace(*endpoint_result_, dns_aliases_); } @@ -397,7 +397,7 @@ disable_legacy_crypto_with_fallback_ || !base::FeatureList::IsEnabled(features::kSHA1ServerSignature); - if (ssl_client_context()->EncryptedClientHelloEnabled()) { + if (ssl_client_context()->config().EncryptedClientHelloEnabled()) { if (ech_retry_configs_) { ssl_config.ech_config_list = *ech_retry_configs_; } else if (endpoint_result_) { @@ -451,7 +451,7 @@ endpoint_result_ && !endpoint_result_->metadata.ech_config_list.empty(); if (!ech_retry_configs_ && result == ERR_ECH_NOT_NEGOTIATED && - ssl_client_context()->EncryptedClientHelloEnabled()) { + ssl_client_context()->config().EncryptedClientHelloEnabled()) { // We used ECH, and the server could not decrypt the ClientHello. However, // it was able to handshake with the public name and send authenticated // retry configs. If this is not the first time around, retry the connection
diff --git a/net/ssl/ssl_config_service.cc b/net/ssl/ssl_config_service.cc index c9ea712..97efb28 100644 --- a/net/ssl/ssl_config_service.cc +++ b/net/ssl/ssl_config_service.cc
@@ -6,8 +6,9 @@ #include <tuple> +#include "base/feature_list.h" #include "base/observer_list.h" -#include "net/ssl/ssl_config_service_defaults.h" +#include "net/base/features.h" namespace net { @@ -35,6 +36,11 @@ default; SSLContextConfig& SSLContextConfig::operator=(SSLContextConfig&&) = default; +bool SSLContextConfig::EncryptedClientHelloEnabled() const { + return ech_enabled && + base::FeatureList::IsEnabled(features::kEncryptedClientHello); +} + SSLConfigService::SSLConfigService() : observer_list_(base::ObserverListPolicy::EXISTING_ONLY) {}
diff --git a/net/ssl/ssl_config_service.h b/net/ssl/ssl_config_service.h index 219f8d1..c2f1526 100644 --- a/net/ssl/ssl_config_service.h +++ b/net/ssl/ssl_config_service.h
@@ -21,6 +21,9 @@ SSLContextConfig& operator=(const SSLContextConfig&); SSLContextConfig& operator=(SSLContextConfig&&); + // EncryptedClientHelloEnabled returns whether ECH is enabled. + bool EncryptedClientHelloEnabled() const; + // The minimum and maximum protocol versions that are enabled. // (Use the SSL_PROTOCOL_VERSION_xxx enumerators defined in ssl_config.h.) // SSL 2.0/3.0 and TLS 1.0/1.1 are not supported. If version_max < @@ -42,10 +45,11 @@ bool cecpq2_enabled = true; // If false, disables TLS Encrypted ClientHello (ECH). If true, the feature - // may be enabled or disabled, depending on feature flags. + // may be enabled or disabled, depending on feature flags. If querying whether + // ECH is enabled, use `EncryptedClientHelloEnabled` instead. bool ech_enabled = true; - // ADDING MORE HERE? Don't forget to update |SSLContextConfigsAreEqual|. + // ADDING MORE HERE? Don't forget to update `SSLContextConfigsAreEqual`. }; // The interface for retrieving global SSL configuration. This interface
diff --git a/net/websockets/websocket_basic_stream_adapters_test.cc b/net/websockets/websocket_basic_stream_adapters_test.cc index f91b13f..908e65c4 100644 --- a/net/websockets/websocket_basic_stream_adapters_test.cc +++ b/net/websockets/websocket_basic_stream_adapters_test.cc
@@ -21,6 +21,7 @@ #include "net/base/proxy_server.h" #include "net/base/test_completion_callback.h" #include "net/dns/mock_host_resolver.h" +#include "net/dns/public/host_resolver_results.h" #include "net/dns/public/secure_dns_policy.h" #include "net/http/http_network_session.h" #include "net/log/net_log_with_source.h" @@ -39,13 +40,13 @@ #include "net/socket/connect_job.h" #include "net/socket/socket_tag.h" #include "net/socket/socket_test_util.h" -#include "net/socket/ssl_client_socket.h" #include "net/socket/transport_client_socket_pool.h" #include "net/socket/websocket_endpoint_lock_manager.h" #include "net/spdy/spdy_session.h" #include "net/spdy/spdy_session_key.h" #include "net/spdy/spdy_test_util_common.h" #include "net/ssl/ssl_config.h" +#include "net/ssl/ssl_config_service_defaults.h" #include "net/ssl/ssl_info.h" #include "net/test/cert_test_util.h" #include "net/test/gtest_util.h" @@ -1222,7 +1223,7 @@ session_ = std::make_unique<QuicChromiumClientSession>( connection, std::move(socket), /*stream_factory=*/nullptr, &crypto_client_stream_factory_, &clock_, - &transport_security_state_, /*ssl_config_service=*/nullptr, + &transport_security_state_, &ssl_config_service_, /*server_info=*/nullptr, QuicSessionKey("mail.example.org", 80, PRIVACY_MODE_DISABLED, SocketTag(), NetworkAnonymizationKey(), @@ -1247,7 +1248,8 @@ std::make_unique<quic::QuicClientPushPromiseIndex>(), nullptr, base::DefaultTickClock::GetInstance(), base::SingleThreadTaskRunner::GetCurrentDefault().get(), - /*socket_performance_watcher=*/nullptr, NetLog::Get()); + /*socket_performance_watcher=*/nullptr, HostResolverEndpointResult(), + NetLog::Get()); session_->Initialize(); @@ -1281,6 +1283,7 @@ scoped_refptr<TestTaskRunner> runner_; ProofVerifyDetailsChromium verify_details_; MockCryptoClientStreamFactory crypto_client_stream_factory_; + SSLConfigServiceDefaults ssl_config_service_; quic::test::MockConnectionIdGenerator connection_id_generator_; std::unique_ptr<QuicChromiumConnectionHelper> helper_; std::unique_ptr<QuicChromiumAlarmFactory> alarm_factory_;
diff --git a/net/websockets/websocket_handshake_stream_create_helper_test.cc b/net/websockets/websocket_handshake_stream_create_helper_test.cc index 8587eebb..a3e6f0df 100644 --- a/net/websockets/websocket_handshake_stream_create_helper_test.cc +++ b/net/websockets/websocket_handshake_stream_create_helper_test.cc
@@ -17,6 +17,7 @@ #include "net/base/net_errors.h" #include "net/base/privacy_mode.h" #include "net/base/proxy_server.h" +#include "net/dns/public/host_resolver_results.h" #include "net/dns/public/secure_dns_policy.h" #include "net/http/http_network_session.h" #include "net/http/http_request_headers.h" @@ -37,13 +38,11 @@ #include "net/socket/connect_job.h" #include "net/socket/socket_tag.h" #include "net/socket/socket_test_util.h" -#include "net/socket/ssl_client_socket.h" #include "net/socket/websocket_endpoint_lock_manager.h" #include "net/spdy/spdy_session.h" #include "net/spdy/spdy_session_key.h" #include "net/spdy/spdy_test_util_common.h" -#include "net/ssl/ssl_config.h" -#include "net/ssl/ssl_info.h" +#include "net/ssl/ssl_config_service_defaults.h" #include "net/test/cert_test_util.h" #include "net/test/gtest_util.h" #include "net/test/test_data_directory.h" @@ -346,6 +345,7 @@ ProofVerifyDetailsChromium verify_details; MockCryptoClientStreamFactory crypto_client_stream_factory; TransportSecurityState transport_security_state; + SSLConfigServiceDefaults ssl_config_service; FLAGS_quic_enable_http3_grease_randomness = false; clock_.AdvanceTime(quic::QuicTime::Delta::FromMilliseconds(20)); @@ -425,7 +425,7 @@ session_ = std::make_unique<QuicChromiumClientSession>( connection, std::move(socket), /*stream_factory=*/nullptr, &crypto_client_stream_factory, &clock_, - &transport_security_state, /*ssl_config_service=*/nullptr, + &transport_security_state, &ssl_config_service, /*server_info=*/nullptr, QuicSessionKey("mail.example.org", 80, PRIVACY_MODE_DISABLED, SocketTag(), NetworkAnonymizationKey(), @@ -450,7 +450,8 @@ std::make_unique<quic::QuicClientPushPromiseIndex>(), nullptr, base::DefaultTickClock::GetInstance(), base::SingleThreadTaskRunner::GetCurrentDefault().get(), - /*socket_performance_watcher=*/nullptr, NetLog::Get()); + /*socket_performance_watcher=*/nullptr, + HostResolverEndpointResult(), NetLog::Get()); session_->Initialize();
diff --git a/remoting/test/it2me_cli_host.cc b/remoting/test/it2me_cli_host.cc index 3eff8505..bf71356b 100644 --- a/remoting/test/it2me_cli_host.cc +++ b/remoting/test/it2me_cli_host.cc
@@ -96,48 +96,45 @@ return; } - auto* type_value = - message_value->FindKeyOfType(kMessageType, base::Value::Type::STRING); - if (!type_value) { + base::Value::Dict& message_dict = message_value->GetDict(); + std::string* type = message_dict.FindString(kMessageType); + if (!type) { OnProtocolBroken("Message without type"); return; } - std::string type = type_value->GetString(); - if (type == kHelloResponse) { + if (*type == kHelloResponse) { OnHelloResponse(); - } else if (type == kConnectResponse) { + } else if (*type == kConnectResponse) { // Ok, just ignore. - } else if (type == kDisconnectResponse) { + } else if (*type == kDisconnectResponse) { OnDisconnectResponse(); - } else if (type == kHostStateChangedMessage) { + } else if (*type == kHostStateChangedMessage) { // Handle CRD host state changes - auto* state_value = - message_value->FindKeyOfType(kState, base::Value::Type::STRING); - if (!state_value) { + std::string* state = message_dict.FindString(kState); + if (!state) { OnProtocolBroken("No state in message"); return; } - std::string state = state_value->GetString(); - if (state == kHostStateReceivedAccessCode) { - OnStateReceivedAccessCode(*message_value); - } else if (state == kHostStateConnected) { - OnStateRemoteConnected(*message_value); - } else if (state == kHostStateDisconnected) { + if (*state == kHostStateReceivedAccessCode) { + OnStateReceivedAccessCode(message_dict); + } else if (*state == kHostStateConnected) { + OnStateRemoteConnected(message_dict); + } else if (*state == kHostStateDisconnected) { OnStateRemoteDisconnected(); - } else if (state == kHostStateError || state == kHostStateDomainError) { - OnStateError(state, *message_value); - } else if (state == kHostStateStarting || - state == kHostStateRequestedAccessCode) { + } else if (*state == kHostStateError || *state == kHostStateDomainError) { + OnStateError(*state, message_dict); + } else if (*state == kHostStateStarting || + *state == kHostStateRequestedAccessCode) { // Just ignore these states. } else { - LOG(WARNING) << "Unhandled state: " << state; + LOG(WARNING) << "Unhandled state: " << *state; } - } else if (type == kCRDDebugLog) { + } else if (*type == kCRDDebugLog) { // The It2Me host already prints the log to stdout/stderr. } else { - LOG(WARNING) << "Unknown message type: " << type; + LOG(WARNING) << "Unknown message type: " << *type; } } @@ -226,15 +223,14 @@ } void It2MeCliHost::OnStateError(const std::string& error_state, - const base::Value& message) { + const base::Value::Dict& message) { std::string error_message; if (error_state == kHostStateDomainError) { error_message = "CRD Error : Invalid domain"; } else { - auto* error_code_value = - message.FindKeyOfType(kErrorMessageCode, base::Value::Type::STRING); - if (error_code_value) { - error_message = error_code_value->GetString(); + const std::string* error_code = message.FindString(kErrorMessageCode); + if (error_code) { + error_message = *error_code; } else { error_message = "Unknown CRD Error"; } @@ -248,12 +244,11 @@ ShutdownHost(); } -void It2MeCliHost::OnStateRemoteConnected(const base::Value& message) { +void It2MeCliHost::OnStateRemoteConnected(const base::Value::Dict& message) { remote_connected_ = true; - auto* client_value = - message.FindKeyOfType(kClient, base::Value::Type::STRING); - if (client_value) { - HOST_LOG << "Remote connection by " << client_value->GetString(); + const std::string* client = message.FindString(kClient); + if (client) { + HOST_LOG << "Remote connection by " << *client; } } @@ -270,7 +265,7 @@ SendMessageToHost(kDisconnectMessage, std::move(params)); } -void It2MeCliHost::OnStateReceivedAccessCode(const base::Value& message) { +void It2MeCliHost::OnStateReceivedAccessCode(const base::Value::Dict& message) { if (!command_awaiting_crd_access_code_) { if (!remote_connected_) { // We have already sent the access code back to the server which initiated @@ -283,19 +278,18 @@ return; } - auto* code_value = - message.FindKeyOfType(kAccessCode, base::Value::Type::STRING); - auto* code_lifetime_value = - message.FindKeyOfType(kAccessCodeLifetime, base::Value::Type::INTEGER); - if (!code_value || !code_lifetime_value) { + const std::string* code = message.FindString(kAccessCode); + const absl::optional<int> code_lifetime = + message.FindInt(kAccessCodeLifetime); + if (!code || !code_lifetime) { OnProtocolBroken("Can not obtain access code"); return; } command_awaiting_crd_access_code_ = false; // Prints the access code. - base::TimeDelta expires_in = base::Seconds(code_lifetime_value->GetInt()); - HOST_LOG << "It2Me access code is generated: " << code_value->GetString(); + base::TimeDelta expires_in = base::Seconds(*code_lifetime); + HOST_LOG << "It2Me access code is generated: " << *code; HOST_LOG << "Expires at: " << (base::Time::Now() + expires_in); }
diff --git a/remoting/test/it2me_cli_host.h b/remoting/test/it2me_cli_host.h index 05502b5..733e934 100644 --- a/remoting/test/it2me_cli_host.h +++ b/remoting/test/it2me_cli_host.h
@@ -62,10 +62,11 @@ void OnHelloResponse(); void OnDisconnectResponse(); - void OnStateError(const std::string& error_state, const base::Value& message); - void OnStateRemoteConnected(const base::Value& message); + void OnStateError(const std::string& error_state, + const base::Value::Dict& message); + void OnStateRemoteConnected(const base::Value::Dict& message); void OnStateRemoteDisconnected(); - void OnStateReceivedAccessCode(const base::Value& message); + void OnStateReceivedAccessCode(const base::Value::Dict& message); std::unique_ptr<test::TestTokenStorage> storage_; std::unique_ptr<test::TestOAuthTokenGetter> token_getter_;
diff --git a/sandbox/mac/seatbelt_extension_unittest.cc b/sandbox/mac/seatbelt_extension_unittest.cc index 6e11c74..e0923130 100644 --- a/sandbox/mac/seatbelt_extension_unittest.cc +++ b/sandbox/mac/seatbelt_extension_unittest.cc
@@ -31,8 +31,6 @@ )"; const char kTestData[] = "hello world"; -constexpr int kTestDataLen = std::size(kTestData); - const char kSwitchFile[] = "test-file"; const char kSwitchExtension[] = "test-extension"; @@ -42,8 +40,7 @@ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); file_path_ = temp_dir_.GetPath().AppendASCII("sbox.test"); - ASSERT_EQ(kTestDataLen, - base::WriteFile(file_path_, kTestData, kTestDataLen)); + ASSERT_TRUE(base::WriteFile(file_path_, kTestData)); } base::FilePath file_path() { return file_path_; }
diff --git a/services/device/geolocation/win/location_provider_winrt.cc b/services/device/geolocation/win/location_provider_winrt.cc index 86752d8..81dff79 100644 --- a/services/device/geolocation/win/location_provider_winrt.cc +++ b/services/device/geolocation/win/location_provider_winrt.cc
@@ -208,10 +208,6 @@ event = WindowsRTLocationRequestEvent:: WINDOWS_RT_LOCATION_CALLBACK_EVENT_POSITION_UNAVAILABLE; break; - case mojom::Geoposition::ErrorCode::TIMEOUT: - event = WindowsRTLocationRequestEvent:: - WINDOWS_RT_LOCATION_CALLBACK_EVENT_TIMEOUT; - break; default: event = WindowsRTLocationRequestEvent:: WINDOWS_RT_LOCATION_CALLBACK_EVENT_UNKNOWN_ERROR_CONDITION;
diff --git a/services/device/public/mojom/geoposition.mojom b/services/device/public/mojom/geoposition.mojom index be6f9c3..fcfbd39 100644 --- a/services/device/public/mojom/geoposition.mojom +++ b/services/device/public/mojom/geoposition.mojom
@@ -25,8 +25,7 @@ NONE = 0, // Chrome addition. PERMISSION_DENIED = 1, POSITION_UNAVAILABLE = 2, - TIMEOUT = 3, - LAST = TIMEOUT + LAST = POSITION_UNAVAILABLE }; // Whether this geoposition is valid.
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json index e8ec68a..0938ee0 100644 --- a/testing/buildbot/chromium.chromiumos.json +++ b/testing/buildbot/chromium.chromiumos.json
@@ -5818,9 +5818,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v113.0.5620.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v113.0.5621.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 113.0.5620.0", + "description": "Run with ash-chrome version 113.0.5621.0", "isolate_profile_data": true, "merge": { "args": [], @@ -5832,8 +5832,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v113.0.5620.0", - "revision": "version:113.0.5620.0" + "location": "lacros_version_skew_tests_v113.0.5621.0", + "revision": "version:113.0.5621.0" } ], "dimension_sets": [ @@ -5989,9 +5989,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v113.0.5620.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v113.0.5621.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 113.0.5620.0", + "description": "Run with ash-chrome version 113.0.5621.0", "isolate_profile_data": true, "merge": { "args": [], @@ -6003,8 +6003,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v113.0.5620.0", - "revision": "version:113.0.5620.0" + "location": "lacros_version_skew_tests_v113.0.5621.0", + "revision": "version:113.0.5621.0" } ], "dimension_sets": [ @@ -6141,9 +6141,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v113.0.5620.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v113.0.5621.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 113.0.5620.0", + "description": "Run with ash-chrome version 113.0.5621.0", "isolate_profile_data": true, "merge": { "args": [], @@ -6155,8 +6155,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v113.0.5620.0", - "revision": "version:113.0.5620.0" + "location": "lacros_version_skew_tests_v113.0.5621.0", + "revision": "version:113.0.5621.0" } ], "dimension_sets": [
diff --git a/testing/buildbot/chromium.coverage.json b/testing/buildbot/chromium.coverage.json index 11a6ea5..9c137e2 100644 --- a/testing/buildbot/chromium.coverage.json +++ b/testing/buildbot/chromium.coverage.json
@@ -19408,7 +19408,8 @@ }, { "args": [ - "--extra-browser-args=--enable-crashpad" + "--extra-browser-args=--enable-crashpad", + "--xvfb" ], "isolate_name": "telemetry_perf_unittests", "isolate_profile_data": true, @@ -20486,9 +20487,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v113.0.5620.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v113.0.5621.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 113.0.5620.0", + "description": "Run with ash-chrome version 113.0.5621.0", "isolate_profile_data": true, "merge": { "args": [], @@ -20500,8 +20501,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v113.0.5620.0", - "revision": "version:113.0.5620.0" + "location": "lacros_version_skew_tests_v113.0.5621.0", + "revision": "version:113.0.5621.0" } ], "dimension_sets": [ @@ -20657,9 +20658,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v113.0.5620.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v113.0.5621.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 113.0.5620.0", + "description": "Run with ash-chrome version 113.0.5621.0", "isolate_profile_data": true, "merge": { "args": [], @@ -20671,8 +20672,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v113.0.5620.0", - "revision": "version:113.0.5620.0" + "location": "lacros_version_skew_tests_v113.0.5621.0", + "revision": "version:113.0.5621.0" } ], "dimension_sets": [ @@ -20809,9 +20810,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v113.0.5620.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v113.0.5621.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 113.0.5620.0", + "description": "Run with ash-chrome version 113.0.5621.0", "isolate_profile_data": true, "merge": { "args": [], @@ -20823,8 +20824,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v113.0.5620.0", - "revision": "version:113.0.5620.0" + "location": "lacros_version_skew_tests_v113.0.5621.0", + "revision": "version:113.0.5621.0" } ], "dimension_sets": [
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index d672332..d636da7f 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -408,7 +408,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 10 + "shards": 20 }, "test": "browser_tests", "test_id_prefix": "ninja://chrome/test:browser_tests/" @@ -48776,9 +48776,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v113.0.5620.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v113.0.5621.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 113.0.5620.0", + "description": "Run with ash-chrome version 113.0.5621.0", "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -48789,8 +48789,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v113.0.5620.0", - "revision": "version:113.0.5620.0" + "location": "lacros_version_skew_tests_v113.0.5621.0", + "revision": "version:113.0.5621.0" } ], "dimension_sets": [ @@ -48947,9 +48947,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v113.0.5620.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v113.0.5621.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 113.0.5620.0", + "description": "Run with ash-chrome version 113.0.5621.0", "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -48960,8 +48960,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v113.0.5620.0", - "revision": "version:113.0.5620.0" + "location": "lacros_version_skew_tests_v113.0.5621.0", + "revision": "version:113.0.5621.0" } ], "dimension_sets": [ @@ -49099,9 +49099,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v113.0.5620.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v113.0.5621.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 113.0.5620.0", + "description": "Run with ash-chrome version 113.0.5621.0", "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -49112,8 +49112,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v113.0.5620.0", - "revision": "version:113.0.5620.0" + "location": "lacros_version_skew_tests_v113.0.5621.0", + "revision": "version:113.0.5621.0" } ], "dimension_sets": [ @@ -50637,9 +50637,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v113.0.5620.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v113.0.5621.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 113.0.5620.0", + "description": "Run with ash-chrome version 113.0.5621.0", "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -50650,8 +50650,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v113.0.5620.0", - "revision": "version:113.0.5620.0" + "location": "lacros_version_skew_tests_v113.0.5621.0", + "revision": "version:113.0.5621.0" } ], "dimension_sets": [ @@ -50808,9 +50808,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v113.0.5620.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v113.0.5621.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 113.0.5620.0", + "description": "Run with ash-chrome version 113.0.5621.0", "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -50821,8 +50821,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v113.0.5620.0", - "revision": "version:113.0.5620.0" + "location": "lacros_version_skew_tests_v113.0.5621.0", + "revision": "version:113.0.5621.0" } ], "dimension_sets": [ @@ -50960,9 +50960,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v113.0.5620.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v113.0.5621.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 113.0.5620.0", + "description": "Run with ash-chrome version 113.0.5621.0", "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -50973,8 +50973,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v113.0.5620.0", - "revision": "version:113.0.5620.0" + "location": "lacros_version_skew_tests_v113.0.5621.0", + "revision": "version:113.0.5621.0" } ], "dimension_sets": [ @@ -51746,9 +51746,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v113.0.5620.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v113.0.5621.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 113.0.5620.0", + "description": "Run with ash-chrome version 113.0.5621.0", "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -51759,8 +51759,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v113.0.5620.0", - "revision": "version:113.0.5620.0" + "location": "lacros_version_skew_tests_v113.0.5621.0", + "revision": "version:113.0.5621.0" } ], "dimension_sets": [
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json index 97c072d..b9f43a0 100644 --- a/testing/buildbot/chromium.memory.json +++ b/testing/buildbot/chromium.memory.json
@@ -18533,12 +18533,12 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v113.0.5620.0/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v113.0.5621.0/test_ash_chrome", "--test-launcher-print-test-stdio=always", "--combine-ash-logs-on-bots", "--asan-symbolize-output" ], - "description": "Run with ash-chrome version 113.0.5620.0", + "description": "Run with ash-chrome version 113.0.5621.0", "isolate_profile_data": true, "merge": { "args": [], @@ -18550,8 +18550,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v113.0.5620.0", - "revision": "version:113.0.5620.0" + "location": "lacros_version_skew_tests_v113.0.5621.0", + "revision": "version:113.0.5621.0" } ], "dimension_sets": [ @@ -18724,12 +18724,12 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v113.0.5620.0/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v113.0.5621.0/test_ash_chrome", "--test-launcher-print-test-stdio=always", "--combine-ash-logs-on-bots", "--asan-symbolize-output" ], - "description": "Run with ash-chrome version 113.0.5620.0", + "description": "Run with ash-chrome version 113.0.5621.0", "isolate_profile_data": true, "merge": { "args": [], @@ -18741,8 +18741,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v113.0.5620.0", - "revision": "version:113.0.5620.0" + "location": "lacros_version_skew_tests_v113.0.5621.0", + "revision": "version:113.0.5621.0" } ], "dimension_sets": [ @@ -18891,12 +18891,12 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v113.0.5620.0/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v113.0.5621.0/test_ash_chrome", "--test-launcher-print-test-stdio=always", "--combine-ash-logs-on-bots", "--asan-symbolize-output" ], - "description": "Run with ash-chrome version 113.0.5620.0", + "description": "Run with ash-chrome version 113.0.5621.0", "isolate_profile_data": true, "merge": { "args": [], @@ -18908,8 +18908,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v113.0.5620.0", - "revision": "version:113.0.5620.0" + "location": "lacros_version_skew_tests_v113.0.5621.0", + "revision": "version:113.0.5621.0" } ], "dimension_sets": [
diff --git a/testing/buildbot/filters/chromeos.msan.browser_tests.oobe_negative.filter b/testing/buildbot/filters/chromeos.msan.browser_tests.oobe_negative.filter index 0e993393..76a0296 100644 --- a/testing/buildbot/filters/chromeos.msan.browser_tests.oobe_negative.filter +++ b/testing/buildbot/filters/chromeos.msan.browser_tests.oobe_negative.filter
@@ -23,11 +23,13 @@ -All/SAMLDeviceAttestationEnrolledTest.* -All/SAMLDeviceAttestationTest.* -All/SAMLEnrollmentTest.* +-All/SAMLLocalesTest.* -All/SAMLPasswordAttributesTest.* -All/SAMLPolicyTest.* -All/SamlTestWithFeatures.* -All/SmartPrivacyProtectionScreenTest.* -All/SshWarningTest.* +-All/SsoProfileTest.* -All/SyncConsentPolicyDisabledTest.* -All/SyncConsentTestWithModesParams.* -All/SyncConsentTestWithParams.*
diff --git a/testing/buildbot/filters/chromeos.msan.browser_tests.oobe_positive.filter b/testing/buildbot/filters/chromeos.msan.browser_tests.oobe_positive.filter index 8d73510..a4d862c 100644 --- a/testing/buildbot/filters/chromeos.msan.browser_tests.oobe_positive.filter +++ b/testing/buildbot/filters/chromeos.msan.browser_tests.oobe_positive.filter
@@ -23,11 +23,13 @@ All/SAMLDeviceAttestationEnrolledTest.* All/SAMLDeviceAttestationTest.* All/SAMLEnrollmentTest.* +All/SAMLLocalesTest.* All/SAMLPasswordAttributesTest.* All/SAMLPolicyTest.* All/SamlTestWithFeatures.* All/SmartPrivacyProtectionScreenTest.* All/SshWarningTest.* +All/SsoProfileTest.* All/SyncConsentPolicyDisabledTest.* All/SyncConsentTestWithModesParams.* All/SyncConsentTestWithParams.*
diff --git a/testing/buildbot/filters/pixel_tests.filter b/testing/buildbot/filters/pixel_tests.filter index 3ad131fd..0975865b 100644 --- a/testing/buildbot/filters/pixel_tests.filter +++ b/testing/buildbot/filters/pixel_tests.filter
@@ -87,7 +87,4 @@ # # TODO(crbug.com/xxx): Fix xyz and re-enable. # -MyTestSuite.InvokeUi_MyTestCase -# This test uses random network port and shows it on ui. --ContentSettingBubbleDialogTest.InvokeUi_popups - -OutdatedUpgradeBubbleTest.InvokeUi_Critical
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index 4cf9442..c049de43 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -1039,6 +1039,11 @@ ], 'experiment_percentage': 100, # https://crbug.com/1251657 }, + 'Mac Builder Next': { + 'swarming': { + 'shards': 20, # crbug.com/1419045 + }, + }, 'Mac10.15 Tests': { # crbug.com/1042757 'swarming': {
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index 02b06d5..090e12ba 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -5026,6 +5026,23 @@ }, }, + 'telemetry_perf_unittests_isolated_scripts_xvfb': { + 'telemetry_perf_unittests': { + 'args': [ + # TODO(crbug.com/1077284): Remove this once Crashpad is the default. + '--extra-browser-args=--enable-crashpad', + '--xvfb', + ], + 'swarming': { + 'idempotent': False, # https://crbug.com/549140 + 'shards': 12, + }, + 'resultdb': { + 'enable': True, + }, + }, + }, + 'test_buildbucket_api_gpu_use_cases': { 'test_buildbucket_api_gpu_use_cases': {}, }, @@ -5957,7 +5974,7 @@ 'linux_specific_chromium_isolated_scripts', 'mojo_python_unittests_isolated_scripts', 'pytype_tests', - 'telemetry_perf_unittests_isolated_scripts', + 'telemetry_perf_unittests_isolated_scripts_xvfb', 'vulkan_swiftshader_isolated_scripts', 'chromium_web_tests_high_dpi_isolated_scripts', 'gpu_dawn_webgpu_blink_web_tests',
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl index 0eeccd5..c2d3374 100644 --- a/testing/buildbot/variants.pyl +++ b/testing/buildbot/variants.pyl
@@ -22,16 +22,16 @@ }, 'LACROS_VERSION_SKEW_CANARY': { 'args': [ - '--ash-chrome-path-override=../../lacros_version_skew_tests_v113.0.5620.0/test_ash_chrome', + '--ash-chrome-path-override=../../lacros_version_skew_tests_v113.0.5621.0/test_ash_chrome', ], - 'description': 'Run with ash-chrome version 113.0.5620.0', + 'description': 'Run with ash-chrome version 113.0.5621.0', 'identifier': 'Lacros version skew testing ash canary', 'swarming': { 'cipd_packages': [ { 'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip', - 'location': 'lacros_version_skew_tests_v113.0.5620.0', - 'revision': 'version:113.0.5620.0', + 'location': 'lacros_version_skew_tests_v113.0.5621.0', + 'revision': 'version:113.0.5621.0', }, ], },
diff --git a/testing/libfuzzer/BUILD.gn b/testing/libfuzzer/BUILD.gn index 669ea45..6f0c482 100644 --- a/testing/libfuzzer/BUILD.gn +++ b/testing/libfuzzer/BUILD.gn
@@ -43,7 +43,15 @@ # The currently selected fuzzing engine, providing a main() function. # Fuzzers should depend upon this. group("fuzzing_engine_main") { - deps = [ ":libfuzzer_main" ] + deps = [ + ":fuzzing_engine", + ":libfuzzer_main", + ] +} + +# Any fuzzer using any fuzzing engine. This will be used by infra scripts +# to identify fuzzers which should be built and made available to ClusterFuzz. +group("fuzzing_engine") { } # A config used by all fuzzer_tests.
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 15b140c..c015389a 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -132,27 +132,6 @@ ] } ], - "AnchorElementInteractionPreloader": [ - { - "platforms": [ - "android", - "chromeos", - "chromeos_lacros", - "fuchsia", - "linux", - "mac", - "windows" - ], - "experiments": [ - { - "name": "Enabled_20220428", - "enable_features": [ - "AnchorElementInteraction" - ] - } - ] - } - ], "AndroidBackPressRefactor": [ { "platforms": [ @@ -1038,6 +1017,27 @@ ] } ], + "AutofillAlwaysParsePlaceholders": [ + { + "platforms": [ + "android", + "android_webview", + "chromeos", + "chromeos_lacros", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "AutofillAlwaysParsePlaceholders" + ] + } + ] + } + ], "AutofillEnableLabelPrecedenceForTurkishAddresses": [ { "platforms": [ @@ -5263,35 +5263,6 @@ ] } ], - "FullscreenPromosManager": [ - { - "platforms": [ - "ios" - ], - "experiments": [ - { - "name": "Enabled (Fullscreen)", - "params": { - "ios-new-post-restore-experience": "false" - }, - "enable_features": [ - "FullscreenPromosManager", - "IOSNewPostRestoreExperience" - ] - }, - { - "name": "Enabled (Alert)", - "params": { - "ios-new-post-restore-experience": "true" - }, - "enable_features": [ - "FullscreenPromosManager", - "IOSNewPostRestoreExperience" - ] - } - ] - } - ], "GMSCoreEmoji": [ { "platforms": [ @@ -7366,6 +7337,21 @@ ] } ], + "MacSetDefaultTaskRole": [ + { + "platforms": [ + "mac" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "MacSetDefaultTaskRole" + ] + } + ] + } + ], "MacWebContentsOcclusion": [ { "platforms": [ @@ -7402,6 +7388,7 @@ "chromeos", "chromeos_lacros", "fuchsia", + "ios", "linux", "mac", "windows" @@ -11590,6 +11577,7 @@ { "name": "Enabled", "enable_features": [ + "DeferNotifyInMotion", "SuppressToolbarCaptures", "UpdateBrowserControlsWithoutProxy" ]
diff --git a/third_party/android_deps/buildSrc/src/main/groovy/BuildConfigGenerator.groovy b/third_party/android_deps/buildSrc/src/main/groovy/BuildConfigGenerator.groovy index 2934bcd..cb72f99 100644 --- a/third_party/android_deps/buildSrc/src/main/groovy/BuildConfigGenerator.groovy +++ b/third_party/android_deps/buildSrc/src/main/groovy/BuildConfigGenerator.groovy
@@ -639,6 +639,10 @@ sb.append(' # https://crbug.com/989505\n') sb.append(' jar_excluded_patterns = ["META-INF/proguard/*"]\n') break + case 'androidx_benchmark_benchmark_macro': + // Manually add dep onto DISALLOWED_DEP androidx.profileinstaller. + sb.append(' deps += [ ":androidx_profileinstaller_profileinstaller_java" ]\n') + break case 'androidx_core_core': sb.with { append('\n')
diff --git a/third_party/android_deps/buildSrc/src/main/groovy/ChromiumDepGraph.groovy b/third_party/android_deps/buildSrc/src/main/groovy/ChromiumDepGraph.groovy index 2c343ed..2c44b49 100644 --- a/third_party/android_deps/buildSrc/src/main/groovy/ChromiumDepGraph.groovy +++ b/third_party/android_deps/buildSrc/src/main/groovy/ChromiumDepGraph.groovy
@@ -299,6 +299,7 @@ // Bill of materials (BOM) deps are used to specify versions for other dependencies and don't have children or // artifacts of their own. Add other such empty deps here when we encounter them. 'org_jetbrains_kotlinx_kotlinx_coroutines_bom', + 'com_squareup_okio_okio_bom', ] as Set // Local text versions of HTML licenses. This cannot replace PROPERTY_OVERRIDES because some libraries refer to
diff --git a/third_party/androidx/build.gradle.template b/third_party/androidx/build.gradle.template index be3b73b..01c5de1 100644 --- a/third_party/androidx/build.gradle.template +++ b/third_party/androidx/build.gradle.template
@@ -94,11 +94,13 @@ compile 'androidx.legacy:legacy-support-v4:1.0.0' // testCompile targets have test_only = true. + androidTestCompile 'androidx.benchmark:benchmark-macro-junit4:{{androidx_dependency_version}}' + androidTestCompile 'androidx.benchmark:benchmark-junit4:{{androidx_dependency_version}}' androidTestCompile 'androidx.fragment:fragment-testing:{{androidx_dependency_version}}' androidTestCompile 'androidx.test:core:1.4.0-rc01' androidTestCompile 'androidx.test:monitor:1.4.0-rc01' androidTestCompile 'androidx.test:rules:1.2.0' - androidTestCompile 'androidx.test:runner:1.2.0' + androidTestCompile 'androidx.test:runner:1.4.0' androidTestCompile 'androidx.test.espresso:espresso-contrib:3.2.0' androidTestCompile 'androidx.test.espresso:espresso-core:3.2.0' androidTestCompile 'androidx.test.espresso:espresso-intents:3.2.0'
diff --git a/third_party/blink/common/interest_group/interest_group_mojom_traits.cc b/third_party/blink/common/interest_group/interest_group_mojom_traits.cc index deb96d8..73cfd88 100644 --- a/third_party/blink/common/interest_group/interest_group_mojom_traits.cc +++ b/third_party/blink/common/interest_group/interest_group_mojom_traits.cc
@@ -34,13 +34,13 @@ } bool StructTraits<blink::mojom::SellerCapabilitiesDataView, - blink::InterestGroup::SellerCapabilitiesType>:: + blink::SellerCapabilitiesType>:: Read(blink::mojom::SellerCapabilitiesDataView data, - blink::InterestGroup::SellerCapabilitiesType* out) { + blink::SellerCapabilitiesType* out) { if (data.allows_interest_group_counts()) - out->Put(blink::InterestGroup::SellerCapabilities::kInterestGroupCounts); + out->Put(blink::SellerCapabilities::kInterestGroupCounts); if (data.allows_latency_stats()) - out->Put(blink::InterestGroup::SellerCapabilities::kLatencyStats); + out->Put(blink::SellerCapabilities::kLatencyStats); return true; }
diff --git a/third_party/blink/common/interest_group/interest_group_mojom_traits_test.cc b/third_party/blink/common/interest_group/interest_group_mojom_traits_test.cc index 461ff31..5f214e10 100644 --- a/third_party/blink/common/interest_group/interest_group_mojom_traits_test.cc +++ b/third_party/blink/common/interest_group/interest_group_mojom_traits_test.cc
@@ -134,17 +134,17 @@ InterestGroup interest_group = CreateInterestGroup(); interest_group.all_sellers_capabilities.Put( - InterestGroup::SellerCapabilities::kInterestGroupCounts); + SellerCapabilities::kInterestGroupCounts); SerializeAndDeserializeAndCompare(interest_group); interest_group.all_sellers_capabilities.Put( - InterestGroup::SellerCapabilities::kLatencyStats); + SellerCapabilities::kLatencyStats); SerializeAndDeserializeAndCompare(interest_group); interest_group.all_sellers_capabilities.Put( - InterestGroup::SellerCapabilities::kInterestGroupCounts); + SellerCapabilities::kInterestGroupCounts); interest_group.all_sellers_capabilities.Put( - InterestGroup::SellerCapabilities::kLatencyStats); + SellerCapabilities::kLatencyStats); SerializeAndDeserializeAndCompare(interest_group); }
diff --git a/third_party/blink/common/interest_group/test_interest_group_builder.cc b/third_party/blink/common/interest_group/test_interest_group_builder.cc index 0f6a64b..38178e0 100644 --- a/third_party/blink/common/interest_group/test_interest_group_builder.cc +++ b/third_party/blink/common/interest_group/test_interest_group_builder.cc
@@ -86,15 +86,14 @@ } TestInterestGroupBuilder& TestInterestGroupBuilder::SetSellerCapabilities( - absl::optional< - base::flat_map<url::Origin, InterestGroup::SellerCapabilitiesType>> + absl::optional<base::flat_map<url::Origin, SellerCapabilitiesType>> seller_capabilities) { interest_group_.seller_capabilities = std::move(seller_capabilities); return *this; } TestInterestGroupBuilder& TestInterestGroupBuilder::SetAllSellerCapabilities( - InterestGroup::SellerCapabilitiesType all_sellers_capabilities) { + SellerCapabilitiesType all_sellers_capabilities) { interest_group_.all_sellers_capabilities = std::move(all_sellers_capabilities); return *this;
diff --git a/third_party/blink/common/storage_key/storage_key.cc b/third_party/blink/common/storage_key/storage_key.cc index 141dda6f..964476f 100644 --- a/third_party/blink/common/storage_key/storage_key.cc +++ b/third_party/blink/common/storage_key/storage_key.cc
@@ -140,7 +140,8 @@ } return StorageKey(key_origin, key_top_level_site, nullptr, - blink::mojom::AncestorChainBit::kSameSite); + blink::mojom::AncestorChainBit::kSameSite, + /*third_party_partitioning_allowed=*/false); } if (!ValidSeparatorWithData(in, pos_first_caret)) @@ -199,8 +200,15 @@ // The ancestor chain bit must be CrossSite as that's an invariant // when the origin and top level site don't match. + // TODO(crbug.com/1199077): Deserialize should always be able to make 3p + // keys and shouldn't depend on the state of partitioning (because we + // don't want to inadvertently turn two 3p keys into the same 1p key). + // Unfortunately, some tests (and potentially code) depend on this. Here, + // and below, should be changed to true and the dependencies on this + // behavior should be removed. return StorageKey(key_origin, key_top_level_site, nullptr, - blink::mojom::AncestorChainBit::kCrossSite); + blink::mojom::AncestorChainBit::kCrossSite, + IsThirdPartyStoragePartitioningEnabled()); } case EncodedAttribute::kAncestorChainBit: { // Same-Origin kCrossSite keys cannot be read if partitioning is off. @@ -248,7 +256,8 @@ // This format indicates the top level site matches the origin. return StorageKey(key_origin, net::SchemefulSite(key_origin), nullptr, - ancestor_chain_bit); + ancestor_chain_bit, + IsThirdPartyStoragePartitioningEnabled()); } case EncodedAttribute::kNonceHigh: { // A nonce is serialized and has only two encoded attributes. @@ -296,6 +305,12 @@ if (!base::StringToUint64(low_digits, &nonce_low)) return absl::nullopt; + // The key is corrupted if there are extra 0s in front of the nonce. + if (base::NumberToString(nonce_high) != high_digits || + base::NumberToString(nonce_low) != low_digits) { + return absl::nullopt; + } + nonce = base::UnguessableToken::Deserialize(nonce_high, nonce_low); if (!nonce.has_value()) { @@ -304,9 +319,12 @@ // This constructor makes a copy of the nonce, so getting the raw pointer // is safe. + // Note: The partitioning allowed value is irrelevant with a nonce, + // `false` was chosen arbitrarily. return StorageKey(key_origin, net::SchemefulSite(key_origin), &nonce.value(), - blink::mojom::AncestorChainBit::kCrossSite); + blink::mojom::AncestorChainBit::kCrossSite, + /*third_party_partitioning_allowed=*/false); } case EncodedAttribute::kTopLevelSiteOpaqueNonceHigh: { // An opaque `top_level_site` is serialized. @@ -363,6 +381,12 @@ return absl::nullopt; } + // The key is corrupted if there are extra 0s in front of the nonce. + if (base::NumberToString(nonce_high) != high_digits || + base::NumberToString(nonce_low) != low_digits) { + return absl::nullopt; + } + const absl::optional<base::UnguessableToken> site_nonce = base::UnguessableToken::Deserialize(nonce_high, nonce_low); @@ -405,7 +429,8 @@ key_origin, net::SchemefulSite(url::Origin(url::Origin::Nonce(site_nonce.value()), tuple_precursor)), - nullptr, blink::mojom::AncestorChainBit::kCrossSite); + nullptr, blink::mojom::AncestorChainBit::kCrossSite, + IsThirdPartyStoragePartitioningEnabled()); } default: { // Malformed input case. We saw a separator that we don't understand @@ -424,7 +449,8 @@ if (!maybe_origin.opaque()) { if (maybe_origin.Serialize() == in) { return StorageKey(maybe_origin, net::SchemefulSite(maybe_origin), nullptr, - blink::mojom::AncestorChainBit::kSameSite); + blink::mojom::AncestorChainBit::kSameSite, + /*third_party_partitioning_allowed=*/false); } else if (maybe_origin.GetURL().spec() == in) { // This first party key was passed in with a trailing slash. This is // required in Deserialize() but improper for DeserializeForLocalStorage() @@ -479,9 +505,9 @@ // static StorageKey StorageKey::CreateFirstParty(const url::Origin& origin) { return StorageKey(origin, net::SchemefulSite(origin), nullptr, - origin.opaque() - ? blink::mojom::AncestorChainBit::kCrossSite - : blink::mojom::AncestorChainBit::kSameSite); + origin.opaque() ? blink::mojom::AncestorChainBit::kCrossSite + : blink::mojom::AncestorChainBit::kSameSite, + /*third_party_partitioning_allowed=*/false); } // static @@ -489,16 +515,20 @@ const base::UnguessableToken& nonce) { // The AncestorChainBit is not applicable to StorageKeys with a non-empty // nonce, so they are initialized to be kCrossSite. + // Note: The partitioning allowed value is irrelevant with a nonce, `false` + // was chosen arbitrarily. return StorageKey(origin, net::SchemefulSite(origin), &nonce, - blink::mojom::AncestorChainBit::kCrossSite); + blink::mojom::AncestorChainBit::kCrossSite, + /*third_party_partitioning_allowed=*/false); } // static -StorageKey StorageKey::Create( - const url::Origin& origin, - const net::SchemefulSite& top_level_site, - blink::mojom::AncestorChainBit ancestor_chain_bit) { - return StorageKey(origin, top_level_site, nullptr, ancestor_chain_bit); +StorageKey StorageKey::Create(const url::Origin& origin, + const net::SchemefulSite& top_level_site, + blink::mojom::AncestorChainBit ancestor_chain_bit, + bool third_party_partitioning_allowed) { + return StorageKey(origin, top_level_site, nullptr, ancestor_chain_bit, + third_party_partitioning_allowed); } // static @@ -522,7 +552,8 @@ !isolation_info.site_for_cookies().IsNull()) { ancestor_chain_bit = blink::mojom::AncestorChainBit::kSameSite; } - return Create(origin, top_level_site, ancestor_chain_bit); + return Create(origin, top_level_site, ancestor_chain_bit, + IsThirdPartyStoragePartitioningEnabled()); } StorageKey StorageKey::WithOrigin(const url::Origin& origin) const { @@ -576,15 +607,15 @@ StorageKey::StorageKey(const url::Origin& origin, const net::SchemefulSite& top_level_site, const base::UnguessableToken* nonce, - blink::mojom::AncestorChainBit ancestor_chain_bit) + blink::mojom::AncestorChainBit ancestor_chain_bit, + bool third_party_partitioning_allowed) : origin_(origin), - top_level_site_(IsThirdPartyStoragePartitioningEnabled() + top_level_site_(third_party_partitioning_allowed ? top_level_site : net::SchemefulSite(origin)), top_level_site_if_third_party_enabled_(top_level_site), nonce_(base::OptionalFromPtr(nonce)), - ancestor_chain_bit_(IsThirdPartyStoragePartitioningEnabled() - ? ancestor_chain_bit + ancestor_chain_bit_(third_party_partitioning_allowed ? ancestor_chain_bit : (nonce || origin.opaque()) ? blink::mojom::AncestorChainBit::kCrossSite : blink::mojom::AncestorChainBit::kSameSite),
diff --git a/third_party/blink/common/storage_key/storage_key_unittest.cc b/third_party/blink/common/storage_key/storage_key_unittest.cc index f96f6db..46c843d 100644 --- a/third_party/blink/common/storage_key/storage_key_unittest.cc +++ b/third_party/blink/common/storage_key/storage_key_unittest.cc
@@ -606,6 +606,11 @@ false, }, { + "https://example.com/^401^50^6", + absl::nullopt, + false, + }, + { "https://example.com/^40^51^6", blink::StorageKey::Create( url::Origin::Create(GURL("https://example.com/")), @@ -614,6 +619,11 @@ false, }, { + "https://example.com/^400^51^6", + absl::nullopt, + false, + }, + { "https://example.com/^41^51^6", blink::StorageKey::Create( url::Origin::Create(GURL("https://example.com/")), @@ -622,6 +632,11 @@ false, }, { + "https://example.com/^41^501^6", + absl::nullopt, + false, + }, + { "https://example.com/^10^20", absl::nullopt, false, @@ -634,6 +649,11 @@ true, }, { + "https://example.com/^101^20", + absl::nullopt, + true, + }, + { "https://example.com/^10^21", blink::StorageKey::CreateWithNonce( url::Origin::Create(GURL("https://example.com/")), @@ -641,12 +661,22 @@ true, }, { + "https://example.com/^100^21", + absl::nullopt, + true, + }, + { "https://example.com/^11^21", blink::StorageKey::CreateWithNonce( url::Origin::Create(GURL("https://example.com/")), base::UnguessableToken::CreateForTesting(1ULL, 1ULL)), true, }, + { + "https://example.com/^11^201", + absl::nullopt, + true, + }, }; for (const auto& test : kTestCases) {
diff --git a/third_party/blink/public/common/BUILD.gn b/third_party/blink/public/common/BUILD.gn index b872bc96..f90ce7f9 100644 --- a/third_party/blink/public/common/BUILD.gn +++ b/third_party/blink/public/common/BUILD.gn
@@ -204,6 +204,7 @@ "interest_group/interest_group.h", "interest_group/interest_group_mojom_traits.h", "interest_group/interest_group_utils.h", + "interest_group/seller_capabilities.h", "link_to_text/link_to_text_mojom_traits.h", "loader/http_body_element_type.h", "loader/inter_process_time_ticks_converter.h",
diff --git a/third_party/blink/public/common/interest_group/interest_group.h b/third_party/blink/public/common/interest_group/interest_group.h index 0dd6c754..e1363da 100644 --- a/third_party/blink/public/common/interest_group/interest_group.h +++ b/third_party/blink/public/common/interest_group/interest_group.h
@@ -11,11 +11,11 @@ #include <string> #include <vector> -#include "base/containers/enum_set.h" #include "base/containers/flat_map.h" #include "base/time/time.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/public/common/common_export.h" +#include "third_party/blink/public/common/interest_group/seller_capabilities.h" #include "third_party/blink/public/mojom/interest_group/interest_group_types.mojom-shared.h" #include "url/gurl.h" #include "url/origin.h" @@ -76,17 +76,6 @@ bool operator==(const Size& other) const; }; - enum class SellerCapabilities : uint32_t { - kInterestGroupCounts, - kLatencyStats, - - kMaxValue = kLatencyStats - }; - using SellerCapabilitiesType = - base::EnumSet<SellerCapabilities, - SellerCapabilities::kInterestGroupCounts, - SellerCapabilities::kMaxValue>; - InterestGroup(); // Constructor takes arguments by value. They're unlikely to be independently @@ -154,7 +143,7 @@ absl::optional<base::flat_map<std::string, std::vector<std::string>>> size_groups; - static_assert(__LINE__ == 157, R"( + static_assert(__LINE__ == 146, R"( If modifying InterestGroup fields, make sure to also modify: * IsValid(), EstimateSize(), and IsEqualForTesting() in this class
diff --git a/third_party/blink/public/common/interest_group/interest_group_mojom_traits.h b/third_party/blink/public/common/interest_group/interest_group_mojom_traits.h index 4aad93a..1b004c9 100644 --- a/third_party/blink/public/common/interest_group/interest_group_mojom_traits.h +++ b/third_party/blink/public/common/interest_group/interest_group_mojom_traits.h
@@ -64,21 +64,19 @@ template <> struct BLINK_COMMON_EXPORT StructTraits<blink::mojom::SellerCapabilitiesDataView, - blink::InterestGroup::SellerCapabilitiesType> { + blink::SellerCapabilitiesType> { static bool allows_interest_group_counts( - const blink::InterestGroup::SellerCapabilitiesType& capabilities) { - return capabilities.Has( - blink::InterestGroup::SellerCapabilities::kInterestGroupCounts); + const blink::SellerCapabilitiesType& capabilities) { + return capabilities.Has(blink::SellerCapabilities::kInterestGroupCounts); } static bool allows_latency_stats( - const blink::InterestGroup::SellerCapabilitiesType& capabilities) { - return capabilities.Has( - blink::InterestGroup::SellerCapabilities::kLatencyStats); + const blink::SellerCapabilitiesType& capabilities) { + return capabilities.Has(blink::SellerCapabilities::kLatencyStats); } static bool Read(blink::mojom::SellerCapabilitiesDataView data, - blink::InterestGroup::SellerCapabilitiesType* out); + blink::SellerCapabilitiesType* out); }; template <> @@ -116,13 +114,12 @@ } static const absl::optional< - base::flat_map<url::Origin, - blink::InterestGroup::SellerCapabilitiesType>>& + base::flat_map<url::Origin, blink::SellerCapabilitiesType>>& seller_capabilities(const blink::InterestGroup& interest_group) { return interest_group.seller_capabilities; } - static blink::InterestGroup::SellerCapabilitiesType all_sellers_capabilities( + static blink::SellerCapabilitiesType all_sellers_capabilities( const blink::InterestGroup& interest_group) { return interest_group.all_sellers_capabilities; }
diff --git a/third_party/blink/public/common/interest_group/seller_capabilities.h b/third_party/blink/public/common/interest_group/seller_capabilities.h new file mode 100644 index 0000000..b677d406 --- /dev/null +++ b/third_party/blink/public/common/interest_group/seller_capabilities.h
@@ -0,0 +1,26 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_INTEREST_GROUP_SELLER_CAPABILITIES_H_ +#define THIRD_PARTY_BLINK_PUBLIC_COMMON_INTEREST_GROUP_SELLER_CAPABILITIES_H_ + +#include "base/containers/enum_set.h" + +namespace blink { + +enum class SellerCapabilities : uint32_t { + kInterestGroupCounts, + kLatencyStats, + + kMaxValue = kLatencyStats +}; + +using SellerCapabilitiesType = + base::EnumSet<SellerCapabilities, + SellerCapabilities::kInterestGroupCounts, + SellerCapabilities::kMaxValue>; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_INTEREST_GROUP_SELLER_CAPABILITIES_H_
diff --git a/third_party/blink/public/common/interest_group/test_interest_group_builder.h b/third_party/blink/public/common/interest_group/test_interest_group_builder.h index 20c100c..2b5b357 100644 --- a/third_party/blink/public/common/interest_group/test_interest_group_builder.h +++ b/third_party/blink/public/common/interest_group/test_interest_group_builder.h
@@ -42,11 +42,10 @@ absl::optional<base::flat_map<std::string, double>> priority_signals_overrides); TestInterestGroupBuilder& SetSellerCapabilities( - absl::optional< - base::flat_map<url::Origin, InterestGroup::SellerCapabilitiesType>> + absl::optional<base::flat_map<url::Origin, SellerCapabilitiesType>> seller_capabilities); TestInterestGroupBuilder& SetAllSellerCapabilities( - InterestGroup::SellerCapabilitiesType all_sellers_capabilities); + SellerCapabilitiesType all_sellers_capabilities); TestInterestGroupBuilder& SetExecutionMode( InterestGroup::ExecutionMode execution_mode); TestInterestGroupBuilder& SetBiddingUrl(absl::optional<GURL> bidding_url);
diff --git a/third_party/blink/public/common/storage_key/storage_key.h b/third_party/blink/public/common/storage_key/storage_key.h index cb0a27f..7c452e6 100644 --- a/third_party/blink/public/common/storage_key/storage_key.h +++ b/third_party/blink/public/common/storage_key/storage_key.h
@@ -91,9 +91,13 @@ // (1D) Construct for a specific first or third party context. // This is a common entry point when constructing a context, and callsites // generally must branch and call CreateWithNonce() if a nonce is set. + // TODO(crbug.com/1199077): The default argument here is so tests don't need + // to be aware of it. Find a solution that removes this default arg. static StorageKey Create(const url::Origin& origin, const net::SchemefulSite& top_level_site, - blink::mojom::AncestorChainBit ancestor_chain_bit); + blink::mojom::AncestorChainBit ancestor_chain_bit, + bool third_party_partitioning_allowed = + IsThirdPartyStoragePartitioningEnabled()); // (1E) Construct for the provided isolation_info. // TODO(crbug.com/1346450): This does not account for extension URLs. @@ -267,7 +271,8 @@ StorageKey(const url::Origin& origin, const net::SchemefulSite& top_level_site, const base::UnguessableToken* nonce, - blink::mojom::AncestorChainBit ancestor_chain_bit); + blink::mojom::AncestorChainBit ancestor_chain_bit, + bool third_party_partitioning_allowed); // (7B) Operators. // Note that not all must be friends, but all are to consolidate the header.
diff --git a/third_party/blink/public/mojom/frame/frame.mojom b/third_party/blink/public/mojom/frame/frame.mojom index 57f4dcef..bbd52a7 100644 --- a/third_party/blink/public/mojom/frame/frame.mojom +++ b/third_party/blink/public/mojom/frame/frame.mojom
@@ -13,7 +13,10 @@ import "services/network/public/mojom/content_security_policy.mojom"; import "services/network/public/mojom/cross_origin_opener_policy.mojom"; import "services/network/public/mojom/fetch_api.mojom"; +import "services/network/public/mojom/load_timing_info.mojom"; +import "services/network/public/mojom/network_types.mojom"; import "services/network/public/mojom/source_location.mojom"; +import "services/network/public/mojom/url_loader_completion_status.mojom"; import "skia/public/mojom/skcolor.mojom"; import "third_party/blink/public/mojom/blob/blob.mojom"; import "third_party/blink/public/mojom/blob/blob_url_store.mojom"; @@ -685,22 +688,6 @@ => (mojo_base.mojom.String16 content, uint32 start_offset, uint32 end_offset); - // Report ResourceTiming information about cancelled navigation in iframe - // initiated from this document. This is required to prevent revealing - // information about the status codes to the parent frame. (See crbug.com/1346924) - // - // Example of cancelled navigations: - // - 204 - No Content - // - 205 - Reset Content - // - Extension blocking navigation (e.g. Ad blocker) - // - etc - // - // |parent_frame_element_type| is used on the blink side to determine the - // 'initiator_type' of the entry. - AddResourceTimingEntryFromNonNavigatedFrame( - ResourceTimingInfo timing, - blink.mojom.FrameOwnerElementType parent_frame_element_type); - // Creates an intervention report in the frame with contents |id| and // |message|, returns once the report has been queued. |id| identifies the // intervention that occurred. |message| is a human-readable string that @@ -782,13 +769,6 @@ // network error. RenderFallbackContent(); - // Sent to this frame in parent frame's process to render fallback contents. - // This is only used for <object> elements that failed a navigation with an - // HTTP error. - RenderFallbackContentWithResourceTiming( - ResourceTimingInfo timing, - string server_timing_value); - // Instructs the frame to invoke the beforeunload event handler. // // The closure callback is invoked to acknowledge the browser that @@ -983,6 +963,27 @@ // See https://drafts.csswg.org/css-view-transitions-1/ for details. SnapshotDocumentForViewTransition() => ( blink.mojom.ViewTransitionState view_transition_state); + + // Allows the browser to add a resource timing entry for a subframe + // navigation that has failed before committing - a non-ok object navigation + // or a no-content response (204/205). + AddResourceTimingEntryForFailedSubframeNavigation( + blink.mojom.FrameToken subframe_token, + url.mojom.Url initial_url, + mojo_base.mojom.TimeTicks start_time, + mojo_base.mojom.TimeTicks redirect_time, + mojo_base.mojom.TimeTicks request_start, + mojo_base.mojom.TimeTicks response_start, + uint32 response_code, + string mime_type, + network.mojom.LoadTimingInfo load_timing_info, + network.mojom.ConnectionInfo connection_info, + string alpn_negotiated_protocol, + bool is_secure_transport, + bool is_validated, + string normalized_server_timing, + network.mojom.URLLoaderCompletionStatus completion_status + ); }; // Also implemented in Blink, this interface defines frame-specific methods
diff --git a/third_party/blink/public/mojom/frame/remote_frame.mojom b/third_party/blink/public/mojom/frame/remote_frame.mojom index c6d96107..dcea8cc 100644 --- a/third_party/blink/public/mojom/frame/remote_frame.mojom +++ b/third_party/blink/public/mojom/frame/remote_frame.mojom
@@ -120,6 +120,12 @@ // The navigation initiator's user activation and ad status. blink.mojom.NavigationInitiatorActivationAndAdStatus initiator_activation_and_ad_status; + + // Whether this navigation was container initiated (e.g. iframe changed src). + // Only container-initiated navigations report a resource-timing entry. + // Note: when relying on this in the browser process, also make sure to check + // that this comes from the renderer process of the parent frame. + bool is_container_initiated = false; }; // Implemented in Browser, this interface defines frame-specific methods that @@ -325,13 +331,6 @@ // network error). RenderFallbackContent(); - // Sent to this frame in parent frame's process to render fallback contents. - // This is only used for <object> elements that failed a navigation with an - // HTTP error. - RenderFallbackContentWithResourceTiming( - ResourceTimingInfo timing, - string server_timing_value); - // Sent to the remote frame placeholder in the parent process so that // resource timing information can be added to the parent frame. AddResourceTimingFromChild(ResourceTimingInfo timing);
diff --git a/third_party/blink/public/mojom/navigation/navigation_params.mojom b/third_party/blink/public/mojom/navigation/navigation_params.mojom index f8cf8ce..f81865be 100644 --- a/third_party/blink/public/mojom/navigation/navigation_params.mojom +++ b/third_party/blink/public/mojom/navigation/navigation_params.mojom
@@ -157,6 +157,16 @@ // The navigation initiator's user activation and ad status. blink.mojom.NavigationInitiatorActivationAndAdStatus initiator_activation_and_ad_status; + + // Whether this navigation was container initiated (e.g. iframe changed src). + // This is currently partially specified in + // https://html.spec.whatwg.org/#create-navigation-params-by-fetching + // "If sourceSnapshotParams's fetch client is navigable's container document's + // relevant settings object, then set request's initiator type to navigable's + // container's local name." This means that only container initiated + // navigations should create a resource timing entry. + // TODO(https://github.com/whatwg/html/issues/8846): clarify this further. + bool is_container_initiated = false; }; // Provided by the browser or the renderer ------------------------------------- @@ -272,6 +282,21 @@ // Provided by the browser ----------------------------------------------------- +// Only container-initiated navigations report resource timing to the parent. +// See https://github.com/whatwg/fetch/pull/1579 +enum ParentResourceTimingAccess { + kDoNotReport, + + // See https://fetch.spec.whatwg.org/#response-has-cross-origin-redirects + // Whether response info (status code, content-type) can be exposed to + // resource timing. True for CORS same-origin subresource responses and for + // same-origin navigations without cross-origin redirects. + // TODO(https://github.com/whatwg/fetch/issues/1602) clarify the spec around + // this. + kReportWithoutResponseDetails, + kReportWithResponseDetails +}; + // Timings collected in the browser during navigation for the // Navigation Timing API. Sent to Blink in CommitNavigationParams when // the navigation is ready to be committed. @@ -279,6 +304,8 @@ mojo_base.mojom.TimeTicks redirect_start; mojo_base.mojom.TimeTicks redirect_end; mojo_base.mojom.TimeTicks fetch_start; + + ParentResourceTimingAccess parent_resource_timing_access = ParentResourceTimingAccess.kDoNotReport; }; // Sent with CommitNavigationParams and should only be set for main-frame
diff --git a/third_party/blink/public/mojom/page/page.mojom b/third_party/blink/public/mojom/page/page.mojom index 4f543309..d18c661 100644 --- a/third_party/blink/public/mojom/page/page.mojom +++ b/third_party/blink/public/mojom/page/page.mojom
@@ -74,6 +74,14 @@ // PerformanceNavigationTiming. It is 0 if this blink::WebViewImpl does not // host the main frame, to avoid sending the data cross-origin. mojo_base.mojom.TimeTicks activation_start; + + // Holds texture references (stored in the GPU process) and geometry state for + // the previous Document displayed by this frame. This is used to support + // transitions when navigating between same-origin Documents. + // See https://drafts.csswg.org/css-view-transitions-1/ for details. + // This is analogous to CommitNavigationParams field but for prerender + // activations. + blink.mojom.ViewTransitionState? view_transition_state; }; // Used for broadcast messages from browser to renderer for messages that need
diff --git a/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom b/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom index e79be3b5..f6923df 100644 --- a/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom +++ b/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom
@@ -3818,6 +3818,7 @@ kFencedFrameConfigAttribute = 4477, kURLSearchParams_Has_Delete_MultipleArguments = 4478, kPaymentHandlerMinimalHeaderUX = 4479, + kPopoverTypeHint = 4480, // Add new features immediately above this line. Don't change assigned // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/blink/public/web/web_navigation_params.h b/third_party/blink/public/web/web_navigation_params.h index 4dfaca0..87b97a7 100644 --- a/third_party/blink/public/web/web_navigation_params.h +++ b/third_party/blink/public/web/web_navigation_params.h
@@ -191,6 +191,10 @@ // The initiator frame's LocalDOMWindow's has_storage_access state. bool has_storage_access = false; + // Whether this navigation was initiated by the container, e.g. iframe changed + // src. Only container-initiated navigation report resource timing to the + // parent. + bool is_container_initiated = false; }; // This structure holds all information provided by the embedder that is @@ -534,6 +538,10 @@ // Whether the document should be loaded with the has_storage_access bit set. bool has_storage_access = false; + // Whether this navigation should report resource timing to the parent, + // and if so, whether it should expose/hide response details. + mojom::ParentResourceTimingAccess parent_resource_timing_access = + mojom::ParentResourceTimingAccess::kDoNotReport; }; } // namespace blink
diff --git a/third_party/blink/public/web/web_navigation_timings.h b/third_party/blink/public/web/web_navigation_timings.h index 6f0a079..dc713ca 100644 --- a/third_party/blink/public/web/web_navigation_timings.h +++ b/third_party/blink/public/web/web_navigation_timings.h
@@ -6,6 +6,7 @@ #define THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_NAVIGATION_TIMINGS_H_ #include "base/time/time.h" +#include "third_party/blink/public/mojom/navigation/navigation_params.mojom-shared.h" namespace blink { @@ -15,6 +16,7 @@ base::TimeTicks redirect_start; base::TimeTicks redirect_end; base::TimeTicks fetch_start; + blink::mojom::ParentResourceTimingAccess parent_resource_timing_access; }; } // namespace blink
diff --git a/third_party/blink/renderer/build/scripts/templates/runtime_feature_state_context.cc.tmpl b/third_party/blink/renderer/build/scripts/templates/runtime_feature_state_context.cc.tmpl index 80a9a1a2..7e2ca3b 100644 --- a/third_party/blink/renderer/build/scripts/templates/runtime_feature_state_context.cc.tmpl +++ b/third_party/blink/renderer/build/scripts/templates/runtime_feature_state_context.cc.tmpl
@@ -8,6 +8,7 @@ #include "base/containers/flat_map.h" #include "third_party/blink/public/mojom/runtime_feature_state/runtime_feature_state.mojom-shared.h" #include "third_party/blink/public/common/runtime_feature_state/runtime_feature_state_read_context.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" namespace blink { @@ -16,11 +17,16 @@ initial_values_.reserve({{browser_read_access_features|length()}}); {% for feature in browser_read_access_features %} - // TODO(crbug.com/1377000): fetch current value. initial_values_.insert( {blink::mojom::RuntimeFeatureState::k{{feature.name}}, false}); {% endfor %} + + // TODO(crbug.com/1377000): Specifying each starting value this way is rigid. + // Find a more flexible way to do so. + initial_values_ + [blink::mojom::RuntimeFeatureState::kThirdPartyStoragePartitioning] = + StorageKey::IsThirdPartyStoragePartitioningEnabled(); } } // namespace blink \ No newline at end of file
diff --git a/third_party/blink/renderer/build/scripts/templates/runtime_feature_state_read_context.h.tmpl b/third_party/blink/renderer/build/scripts/templates/runtime_feature_state_read_context.h.tmpl index a147d63..5f0b69b 100644 --- a/third_party/blink/renderer/build/scripts/templates/runtime_feature_state_read_context.h.tmpl +++ b/third_party/blink/renderer/build/scripts/templates/runtime_feature_state_read_context.h.tmpl
@@ -35,7 +35,7 @@ } {% for feature in browser_read_access_features %} - bool Is{{feature.name}}Enabled() { + bool Is{{feature.name}}Enabled() const { return IsEnabled( blink::mojom::RuntimeFeatureState::k{{feature.name}}); }
diff --git a/third_party/blink/renderer/core/DEPS b/third_party/blink/renderer/core/DEPS index 586ef27..c8ea315e 100644 --- a/third_party/blink/renderer/core/DEPS +++ b/third_party/blink/renderer/core/DEPS
@@ -76,6 +76,7 @@ "+services/network/public/cpp/request_destination.h", "+services/network/public/cpp/request_mode.h", "+services/network/public/cpp/resource_request.h", + "+services/network/public/cpp/url_loader_completion_status.h", "+services/network/public/cpp/web_sandbox_flags.h", "+services/service_manager/public", "+skia/public/mojom",
diff --git a/third_party/blink/renderer/core/css/build.gni b/third_party/blink/renderer/core/css/build.gni index d368e53d..bdfb88e 100644 --- a/third_party/blink/renderer/core/css/build.gni +++ b/third_party/blink/renderer/core/css/build.gni
@@ -147,6 +147,8 @@ "css_identifier_value.h", "css_image_generator_value.cc", "css_image_generator_value.h", + "css_image_set_option_value.cc", + "css_image_set_option_value.h", "css_image_set_value.cc", "css_image_set_value.h", "css_image_value.cc",
diff --git a/third_party/blink/renderer/core/css/css_image_set_option_value.cc b/third_party/blink/renderer/core/css/css_image_set_option_value.cc new file mode 100644 index 0000000..4e5d509a --- /dev/null +++ b/third_party/blink/renderer/core/css/css_image_set_option_value.cc
@@ -0,0 +1,123 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/core/css/css_image_set_option_value.h" + +#include "third_party/blink/renderer/core/css/css_gradient_value.h" +#include "third_party/blink/renderer/core/css/css_image_value.h" +#include "third_party/blink/renderer/core/style/style_generated_image.h" +#include "third_party/blink/renderer/platform/wtf/text/string_builder.h" + +namespace blink { + +namespace { + +const CSSValue* ComputeImage(const CSSValue* value, + const ComputedStyle& style, + const bool allow_visited_style) { + if (auto* image = DynamicTo<CSSImageValue>(value)) { + return image->ComputedCSSValue(); + } + + if (!RuntimeEnabledFeatures::CSSImageSetEnabled()) { + return value; + } + + if (auto* gradient = DynamicTo<cssvalue::CSSGradientValue>(value)) { + return gradient->ComputedCSSValue(style, allow_visited_style); + } + + NOTREACHED(); + + return value; +} + +const CSSNumericLiteralValue* ComputeResolution( + const CSSNumericLiteralValue* resolution) { + if (RuntimeEnabledFeatures::CSSImageSetEnabled() && resolution && + resolution->IsResolution() && + resolution->GetType() != CSSPrimitiveValue::UnitType::kDotsPerPixel) { + return CSSNumericLiteralValue::Create( + resolution->ComputeDotsPerPixel(), + CSSPrimitiveValue::UnitType::kDotsPerPixel); + } + + return resolution; +} + +} // namespace + +CSSImageSetOptionValue::CSSImageSetOptionValue( + const CSSValue* image, + const CSSNumericLiteralValue* resolution) + : CSSValue(kImageSetOptionClass), image_(image), resolution_(resolution) { + DCHECK(image); + + if (!resolution_) { + resolution_ = + CSSNumericLiteralValue::Create(1.0, CSSPrimitiveValue::UnitType::kX); + } +} + +CSSImageSetOptionValue::~CSSImageSetOptionValue() = default; + +StyleImage* CSSImageSetOptionValue::CacheImage( + const Document& document, + const FetchParameters::ImageRequestBehavior image_request_behavior, + const CrossOriginAttributeValue cross_origin, + const CSSToLengthConversionData::ContainerSizes& container_sizes) const { + if (auto* image = + const_cast<CSSImageValue*>(DynamicTo<CSSImageValue>(image_.Get()))) { + return image->CacheImage(document, image_request_behavior, cross_origin, + ComputedResolution()); + } + + if (!RuntimeEnabledFeatures::CSSImageSetEnabled()) { + return nullptr; + } + + if (auto* gradient = DynamicTo<cssvalue::CSSGradientValue>(image_.Get())) { + return MakeGarbageCollected<StyleGeneratedImage>(*gradient, + container_sizes); + } + + NOTREACHED(); + + return nullptr; +} + +double CSSImageSetOptionValue::ComputedResolution() const { + return resolution_->ComputeDotsPerPixel(); +} + +String CSSImageSetOptionValue::CustomCSSText() const { + StringBuilder result; + + result.Append(image_->CssText()); + result.Append(' '); + result.Append(resolution_->CssText()); + + return result.ReleaseString(); +} + +bool CSSImageSetOptionValue::Equals(const CSSImageSetOptionValue& other) const { + return *image_ == *other.image_ && *resolution_ == *other.resolution_; +} + +CSSImageSetOptionValue* CSSImageSetOptionValue::ComputedCSSValue( + const ComputedStyle& style, + const bool allow_visited_style) const { + return MakeGarbageCollected<CSSImageSetOptionValue>( + ComputeImage(image_, style, allow_visited_style), + ComputeResolution(resolution_)); +} + +void CSSImageSetOptionValue::TraceAfterDispatch(blink::Visitor* visitor) const { + visitor->Trace(image_); + visitor->Trace(resolution_); + + CSSValue::TraceAfterDispatch(visitor); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/css/css_image_set_option_value.h b/third_party/blink/renderer/core/css/css_image_set_option_value.h new file mode 100644 index 0000000..b650b75 --- /dev/null +++ b/third_party/blink/renderer/core/css/css_image_set_option_value.h
@@ -0,0 +1,67 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_IMAGE_SET_OPTION_VALUE_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_IMAGE_SET_OPTION_VALUE_H_ + +#include "third_party/blink/renderer/core/css/css_numeric_literal_value.h" +#include "third_party/blink/renderer/core/css/css_to_length_conversion_data.h" +#include "third_party/blink/renderer/core/css/css_value.h" +#include "third_party/blink/renderer/core/dom/document.h" +#include "third_party/blink/renderer/core/style/computed_style.h" +#include "third_party/blink/renderer/core/style/style_image.h" +#include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h" +#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" + +namespace blink { + +// This class represents an image-set-option as specified in: +// https://w3c.github.io/csswg-drafts/css-images-4/#typedef-image-set-option +// <image-set-option> = [ <image> | <string> ] [<resolution> || type(<string>)] +class CSSImageSetOptionValue : public CSSValue { + public: + explicit CSSImageSetOptionValue( + const CSSValue* image, + const CSSNumericLiteralValue* resolution = nullptr); + + // It is expected that CSSImageSetOptionValue objects should always have + // non-null image and resolution values. + CSSImageSetOptionValue() = delete; + + ~CSSImageSetOptionValue(); + + StyleImage* CacheImage( + const Document& document, + const FetchParameters::ImageRequestBehavior image_request_behavior, + const CrossOriginAttributeValue cross_origin, + const CSSToLengthConversionData::ContainerSizes& container_sizes) const; + + // Gets the resolution value in Dots Per Pixel + double ComputedResolution() const; + + String CustomCSSText() const; + + bool Equals(const CSSImageSetOptionValue& other) const; + + CSSImageSetOptionValue* ComputedCSSValue( + const ComputedStyle& style, + const bool allow_visited_style) const; + + void TraceAfterDispatch(blink::Visitor* visitor) const; + + private: + Member<const CSSValue> image_; + Member<const CSSNumericLiteralValue> resolution_; +}; + +template <> +struct DowncastTraits<CSSImageSetOptionValue> { + static bool AllowFrom(const CSSValue& value) { + return value.IsImageSetOptionValue(); + } +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_IMAGE_SET_OPTION_VALUE_H_
diff --git a/third_party/blink/renderer/core/css/css_image_set_value.cc b/third_party/blink/renderer/core/css/css_image_set_value.cc index 8439b55..72f2532b 100644 --- a/third_party/blink/renderer/core/css/css_image_set_value.cc +++ b/third_party/blink/renderer/core/css/css_image_set_value.cc
@@ -27,22 +27,8 @@ #include <algorithm> -#include "third_party/blink/public/common/loader/referrer_utils.h" -#include "third_party/blink/renderer/core/css/css_gradient_value.h" -#include "third_party/blink/renderer/core/css/css_image_value.h" -#include "third_party/blink/renderer/core/css/css_numeric_literal_value.h" -#include "third_party/blink/renderer/core/css/css_primitive_value.h" -#include "third_party/blink/renderer/core/dom/document.h" -#include "third_party/blink/renderer/core/execution_context/execution_context.h" #include "third_party/blink/renderer/core/loader/resource/image_resource_content.h" -#include "third_party/blink/renderer/core/style/style_generated_image.h" #include "third_party/blink/renderer/core/style/style_image_set.h" -#include "third_party/blink/renderer/platform/loader/fetch/fetch_initiator_type_names.h" -#include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h" -#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h" -#include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h" -#include "third_party/blink/renderer/platform/weborigin/kurl.h" -#include "third_party/blink/renderer/platform/weborigin/referrer.h" #include "third_party/blink/renderer/platform/wtf/text/string_builder.h" namespace blink { @@ -52,7 +38,7 @@ CSSImageSetValue::~CSSImageSetValue() = default; -const CSSImageSetValue::ImageSetOption& CSSImageSetValue::GetBestOption( +const CSSImageSetOptionValue* CSSImageSetValue::GetBestOption( const float device_scale_factor) { // This method is implementing the selection logic described in the // "CSS Images Module Level 4" spec: @@ -75,26 +61,21 @@ // <image-set-option>." if (options_.empty()) { - for (wtf_size_t i = 0, length = this->length(); i < length; ++i) { - auto image_index = i; - - ++i; - SECURITY_DCHECK(i < length); - float resolution = To<CSSPrimitiveValue>(Item(i)).ComputeDotsPerPixel(); - - options_.push_back(ImageSetOption{image_index, resolution}); + for (const auto& i : *this) { + options_.push_back(To<CSSImageSetOptionValue>(i.Get())); } - std::stable_sort( - options_.begin(), options_.end(), - [](const ImageSetOption& left, const ImageSetOption& right) { - return left.resolution < right.resolution; - }); + std::stable_sort(options_.begin(), options_.end(), + [](const CSSImageSetOptionValue* left, + const CSSImageSetOptionValue* right) { + return left->ComputedResolution() < + right->ComputedResolution(); + }); } - for (const auto& image : options_) { - if (image.resolution >= device_scale_factor) { - return image; + for (const auto& option : options_) { + if (option->ComputedResolution() >= device_scale_factor) { + return option; } } @@ -121,9 +102,11 @@ const CrossOriginAttributeValue cross_origin, const CSSToLengthConversionData::ContainerSizes& container_sizes) { if (IsCachePending(device_scale_factor)) { - StyleImage* style_image = - GetImageToCache(device_scale_factor, document, image_request_behavior, - cross_origin, container_sizes); + const CSSImageSetOptionValue* best_option = + GetBestOption(device_scale_factor); + + StyleImage* style_image = best_option->CacheImage( + document, image_request_behavior, cross_origin, container_sizes); cached_image_ = MakeGarbageCollected<StyleImageSet>(style_image, this); @@ -133,34 +116,6 @@ return cached_image_.Get(); } -StyleImage* CSSImageSetValue::GetImageToCache( - const float device_scale_factor, - const Document& document, - const FetchParameters::ImageRequestBehavior image_request_behavior, - const CrossOriginAttributeValue cross_origin, - const CSSToLengthConversionData::ContainerSizes& container_sizes) { - const ImageSetOption& best_option = GetBestOption(device_scale_factor); - - const CSSValue& image_value = Item(best_option.index); - - if (auto* image = - const_cast<CSSImageValue*>(DynamicTo<CSSImageValue>(image_value))) { - return image->CacheImage(document, image_request_behavior, cross_origin, - best_option.resolution); - } - - if (!RuntimeEnabledFeatures::CSSImageSetEnabled()) { - return nullptr; - } - - if (auto* gradient = DynamicTo<cssvalue::CSSGradientValue>(image_value)) { - return MakeGarbageCollected<StyleGeneratedImage>(*gradient, - container_sizes); - } - - return nullptr; -} - String CSSImageSetValue::CustomCSSText() const { StringBuilder result; @@ -175,17 +130,11 @@ result.Append(", "); } - const CSSValue& image_value = Item(i); - result.Append(image_value.CssText()); - result.Append(' '); - - ++i; - SECURITY_DCHECK(i < length); - const CSSValue& resolution_value = Item(i); - result.Append(resolution_value.CssText()); + result.Append(Item(i).CssText()); } result.Append(')'); + return result.ReleaseString(); } @@ -193,14 +142,17 @@ if (!cached_image_) { return false; } + if (ImageResourceContent* cached_content = cached_image_->CachedImage()) { return cached_content->LoadFailedOrCanceled(); } + return true; } void CSSImageSetValue::TraceAfterDispatch(blink::Visitor* visitor) const { visitor->Trace(cached_image_); + visitor->Trace(options_); CSSValueList::TraceAfterDispatch(visitor); } @@ -209,34 +161,9 @@ const bool allow_visited_style) const { auto* value = MakeGarbageCollected<CSSImageSetValue>(); - for (auto& item : *this) { - value->Append( - *ComputedCSSValueForOption(item.Get(), style, allow_visited_style)); - } - - return value; -} - -const CSSValue* CSSImageSetValue::ComputedCSSValueForOption( - const CSSValue* value, - const ComputedStyle& style, - const bool allow_visited_style) const { - if (auto* image = DynamicTo<CSSImageValue>(value)) { - return image->ComputedCSSValue(); - } - - if (RuntimeEnabledFeatures::CSSImageSetEnabled()) { - if (auto* resolution = DynamicTo<CSSNumericLiteralValue>(value); - resolution && resolution->IsResolution() && - resolution->GetType() != CSSPrimitiveValue::UnitType::kDotsPerPixel) { - return CSSNumericLiteralValue::Create( - resolution->ComputeDotsPerPixel(), - CSSPrimitiveValue::UnitType::kDotsPerPixel); - } - - if (auto* gradient = DynamicTo<cssvalue::CSSGradientValue>(value)) { - return gradient->ComputedCSSValue(style, allow_visited_style); - } + for (const auto& i : *this) { + value->Append(*To<CSSImageSetOptionValue>(i.Get())->ComputedCSSValue( + style, allow_visited_style)); } return value;
diff --git a/third_party/blink/renderer/core/css/css_image_set_value.h b/third_party/blink/renderer/core/css/css_image_set_value.h index 54787e9..172865bb 100644 --- a/third_party/blink/renderer/core/css/css_image_set_value.h +++ b/third_party/blink/renderer/core/css/css_image_set_value.h
@@ -26,8 +26,11 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_IMAGE_SET_VALUE_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_IMAGE_SET_VALUE_H_ +#include "third_party/blink/renderer/core/css/css_image_set_option_value.h" #include "third_party/blink/renderer/core/css/css_to_length_conversion_data.h" #include "third_party/blink/renderer/core/css/css_value_list.h" +#include "third_party/blink/renderer/core/style/style_image.h" +#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h" #include "third_party/blink/renderer/platform/loader/fetch/cross_origin_attribute_value.h" #include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h" #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" @@ -63,30 +66,12 @@ void TraceAfterDispatch(blink::Visitor*) const; private: - struct ImageSetOption { - wtf_size_t index{}; - float resolution{}; - }; - - const ImageSetOption& GetBestOption(const float device_scale_factor); - - StyleImage* GetImageToCache( - const float device_scale_factor, - const Document& document, - const FetchParameters::ImageRequestBehavior image_request_behavior, - const CrossOriginAttributeValue cross_origin, - const CSSToLengthConversionData::ContainerSizes& container_sizes); - - // Gets the computed CSS value of image-set-option components. - const CSSValue* ComputedCSSValueForOption( - const CSSValue* value, - const ComputedStyle& style, - const bool allow_visited_style) const; + const CSSImageSetOptionValue* GetBestOption(const float device_scale_factor); Member<StyleImage> cached_image_; float cached_device_scale_factor_{1.0f}; - Vector<ImageSetOption> options_; + HeapVector<Member<const CSSImageSetOptionValue>> options_; }; template <>
diff --git a/third_party/blink/renderer/core/css/css_value.cc b/third_party/blink/renderer/core/css/css_value.cc index 4ea8d905..a86e8d6 100644 --- a/third_party/blink/renderer/core/css/css_value.cc +++ b/third_party/blink/renderer/core/css/css_value.cc
@@ -51,6 +51,7 @@ #include "third_party/blink/renderer/core/css/css_grid_integer_repeat_value.h" #include "third_party/blink/renderer/core/css/css_grid_template_areas_value.h" #include "third_party/blink/renderer/core/css/css_identifier_value.h" +#include "third_party/blink/renderer/core/css/css_image_set_option_value.h" #include "third_party/blink/renderer/core/css/css_image_set_value.h" #include "third_party/blink/renderer/core/css/css_image_value.h" #include "third_party/blink/renderer/core/css/css_inherited_value.h" @@ -290,6 +291,8 @@ return CompareCSSValues<CSSValueList>(*this, other); case kValuePairClass: return CompareCSSValues<CSSValuePair>(*this, other); + case kImageSetOptionClass: + return CompareCSSValues<CSSImageSetOptionValue>(*this, other); case kImageSetClass: return CompareCSSValues<CSSImageSetValue>(*this, other); case kCSSContentDistributionClass: @@ -435,6 +438,8 @@ return To<CSSValuePair>(this)->CustomCSSText(); case kValueListClass: return To<CSSValueList>(this)->CustomCSSText(); + case kImageSetOptionClass: + return To<CSSImageSetOptionValue>(this)->CustomCSSText(); case kImageSetClass: return To<CSSImageSetValue>(this)->CustomCSSText(); case kCSSContentDistributionClass: @@ -653,6 +658,9 @@ case kValuePairClass: To<CSSValuePair>(this)->TraceAfterDispatch(visitor); return; + case kImageSetOptionClass: + To<CSSImageSetOptionValue>(this)->TraceAfterDispatch(visitor); + return; case kImageSetClass: To<CSSImageSetValue>(this)->TraceAfterDispatch(visitor); return;
diff --git a/third_party/blink/renderer/core/css/css_value.h b/third_party/blink/renderer/core/css/css_value.h index 0beb748..4deb0b0 100644 --- a/third_party/blink/renderer/core/css/css_value.h +++ b/third_party/blink/renderer/core/css/css_value.h
@@ -103,6 +103,9 @@ return class_type_ >= kLinearGradientClass && class_type_ <= kConicGradientClass; } + bool IsImageSetOptionValue() const { + return class_type_ == kImageSetOptionClass; + } bool IsImageSetValue() const { return class_type_ == kImageSetClass; } bool IsImageValue() const { return class_type_ == kImageClass; } bool IsInheritedValue() const { return class_type_ == kInheritedClass; } @@ -289,6 +292,8 @@ kKeyframeShorthandClass, kInitialColorValueClass, + kImageSetOptionClass, + // List class types must appear after ValueListClass. kValueListClass, kFunctionClass,
diff --git a/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc b/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc index 90787c0..e582f9a 100644 --- a/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc +++ b/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc
@@ -26,6 +26,7 @@ #include "third_party/blink/renderer/core/css/css_grid_integer_repeat_value.h" #include "third_party/blink/renderer/core/css/css_grid_template_areas_value.h" #include "third_party/blink/renderer/core/css/css_identifier_value.h" +#include "third_party/blink/renderer/core/css/css_image_set_option_value.h" #include "third_party/blink/renderer/core/css/css_image_set_value.h" #include "third_party/blink/renderer/core/css/css_image_value.h" #include "third_party/blink/renderer/core/css/css_inherited_value.h" @@ -1463,7 +1464,7 @@ return nullptr; } -CSSPrimitiveValue* ConsumeResolution(CSSParserTokenRange& range) { +CSSNumericLiteralValue* ConsumeResolution(CSSParserTokenRange& range) { const CSSParserToken& token = range.Peek(); // Unlike the other types, calc() does not work with <resolution>. @@ -3491,45 +3492,46 @@ ConsumeGeneratedImagePolicy::kAllow) { CSSParserTokenRange range_copy = range; CSSParserTokenRange args = ConsumeFunction(range_copy); + auto* image_set = MakeGarbageCollected<CSSImageSetValue>(); + do { + CSSValue* image = nullptr; + AtomicString url_value = (RuntimeEnabledFeatures::CSSImageSetEnabled() ? ConsumeUrlOrStringAsStringView(args, context) : ConsumeUrlAsStringView(args, context)) .ToAtomicString(); if (!url_value.IsNull()) { - image_set->Append(*CreateCSSImageValueWithReferrer(url_value, context)); + image = CreateCSSImageValueWithReferrer(url_value, context); } else { if (!RuntimeEnabledFeatures::CSSImageSetEnabled()) { return nullptr; } - CSSValue* gen_image = ConsumeGeneratedImage(args, context); - if (gen_image == nullptr) { + image = ConsumeGeneratedImage(args, context); + if (image == nullptr) { return nullptr; } - - image_set->Append(*gen_image); } - if (args.Peek().GetType() != kDimensionToken && - RuntimeEnabledFeatures::CSSImageSetEnabled()) { - image_set->Append(*CSSNumericLiteralValue::Create( - 1.0, CSSPrimitiveValue::UnitType::kX)); - } else { + CSSNumericLiteralValue* resolution = nullptr; + if (args.Peek().GetType() == kDimensionToken || + !RuntimeEnabledFeatures::CSSImageSetEnabled()) { if (args.Peek().GetUnitType() != CSSPrimitiveValue::UnitType::kX && !RuntimeEnabledFeatures::CSSImageSetEnabled()) { return nullptr; } - const CSSPrimitiveValue* resolution = ConsumeResolution(args); + resolution = ConsumeResolution(args); if (resolution == nullptr || resolution->GetDoubleValue() <= 0.0) { return nullptr; } - - image_set->Append(*resolution); } + + image_set->Append( + *MakeGarbageCollected<CSSImageSetOptionValue>(image, resolution)); } while (ConsumeCommaIncludingWhitespace(args)); if (!args.AtEnd()) {
diff --git a/third_party/blink/renderer/core/css/properties/css_parsing_utils.h b/third_party/blink/renderer/core/css/properties/css_parsing_utils.h index 30ab4c82..65bb101 100644 --- a/third_party/blink/renderer/core/css/properties/css_parsing_utils.h +++ b/third_party/blink/renderer/core/css/properties/css_parsing_utils.h
@@ -142,7 +142,7 @@ CSSPrimitiveValue* ConsumeTime(CSSParserTokenRange&, const CSSParserContext&, CSSPrimitiveValue::ValueRange); -CSSPrimitiveValue* ConsumeResolution(CSSParserTokenRange&); +CSSNumericLiteralValue* ConsumeResolution(CSSParserTokenRange&); CSSValue* ConsumeRatio(CSSParserTokenRange&, const CSSParserContext&); CSSIdentifierValue* ConsumeIdent(CSSParserTokenRange&); CSSIdentifierValue* ConsumeIdentRange(CSSParserTokenRange&,
diff --git a/third_party/blink/renderer/core/css/resolver/matched_properties_cache_test.cc b/third_party/blink/renderer/core/css/resolver/matched_properties_cache_test.cc index 0b42f6f..d0bfc91 100644 --- a/third_party/blink/renderer/core/css/resolver/matched_properties_cache_test.cc +++ b/third_party/blink/renderer/core/css/resolver/matched_properties_cache_test.cc
@@ -60,8 +60,7 @@ void Add(const TestKey& key, const ComputedStyle& style, const ComputedStyle& parent_style) { - cache_.Add(key.InnerKey(), ComputedStyle::Clone(style), - ComputedStyle::Clone(parent_style)); + cache_.Add(key.InnerKey(), &style, &parent_style); } const CachedMatchedProperties* Find(const TestKey& key,
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver.cc b/third_party/blink/renderer/core/css/resolver/style_resolver.cc index 0eb13b8..a690190 100644 --- a/third_party/blink/renderer/core/css/resolver/style_resolver.cc +++ b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
@@ -2117,7 +2117,7 @@ matched_property_cache_added, 1); matched_properties_cache_.Add(cache_success.key, state.StyleBuilder().CloneStyle(), - ComputedStyle::Clone(*state.ParentStyle())); + state.ParentStyle()); } }
diff --git a/third_party/blink/renderer/core/css/style_engine.cc b/third_party/blink/renderer/core/css/style_engine.cc index 49933db..c387c06 100644 --- a/third_party/blink/renderer/core/css/style_engine.cc +++ b/third_party/blink/renderer/core/css/style_engine.cc
@@ -3314,7 +3314,8 @@ // // This update is also necessary if the first body element changes because // another body element is inserted or removed. - layout_object->SetStyle(ComputedStyle::Clone(*layout_object->Style())); + layout_object->SetStyle( + ComputedStyleBuilder(*layout_object->Style()).TakeStyle()); } }
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc index 9c29a03..269e291 100644 --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc
@@ -7919,7 +7919,17 @@ return nullptr; } -HTMLElement* Document::TopmostPopover() const { +void Document::SetPopoverHintShowing(HTMLElement* element) { + DCHECK(!element || element->HasPopoverAttribute()); + DCHECK(RuntimeEnabledFeatures::HTMLPopoverHintEnabled()); + popover_hint_showing_ = element; +} + +HTMLElement* Document::TopmostPopoverOrHint() const { + if (PopoverHintShowing()) { + DCHECK(RuntimeEnabledFeatures::HTMLPopoverHintEnabled()); + return PopoverHintShowing(); + } if (PopoverStack().empty()) return nullptr; return PopoverStack().back(); @@ -8677,6 +8687,7 @@ visitor->Trace(top_layer_elements_); visitor->Trace(top_layer_elements_pending_removal_); visitor->Trace(popover_stack_); + visitor->Trace(popover_hint_showing_); visitor->Trace(popover_pointerdown_target_); visitor->Trace(popovers_waiting_to_hide_); visitor->Trace(elements_with_css_toggles_);
diff --git a/third_party/blink/renderer/core/dom/document.h b/third_party/blink/renderer/core/dom/document.h index f8316015..0b5ec66 100644 --- a/third_party/blink/renderer/core/dom/document.h +++ b/third_party/blink/renderer/core/dom/document.h
@@ -1545,12 +1545,14 @@ HTMLDialogElement* ActiveModalDialog() const; + HTMLElement* PopoverHintShowing() const { return popover_hint_showing_; } + void SetPopoverHintShowing(HTMLElement* element); HeapVector<Member<HTMLElement>>& PopoverStack() { return popover_stack_; } const HeapVector<Member<HTMLElement>>& PopoverStack() const { return popover_stack_; } bool PopoverAutoShowing() const { return !popover_stack_.empty(); } - HTMLElement* TopmostPopover() const; + HTMLElement* TopmostPopoverOrHint() const; HeapHashSet<Member<HTMLElement>>& PopoversWaitingToHide() { return popovers_waiting_to_hide_; } @@ -2425,6 +2427,8 @@ // The stack of currently-displayed `popover=auto` elements. Elements in the // stack go from earliest (bottom-most) to latest (top-most). HeapVector<Member<HTMLElement>> popover_stack_; + // The `popover=hint` that is currently showing, if any. + Member<HTMLElement> popover_hint_showing_; // The popover (if any) that received the most recent pointerdown event. Member<const HTMLElement> popover_pointerdown_target_; // A set of popovers for which hidePopover() has been called, but animations
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.cc b/third_party/blink/renderer/core/exported/web_view_impl.cc index 3ed58a8..12f001d 100644 --- a/third_party/blink/renderer/core/exported/web_view_impl.cc +++ b/third_party/blink/renderer/core/exported/web_view_impl.cc
@@ -3369,24 +3369,41 @@ // prerenderchange event and post-prerendering activation steps on each // document, which could mutate the frame tree and make iteration over it // complicated. - HeapVector<Member<Document>> documents; + HeapVector<Member<Document>> child_frame_documents; + Member<Document> main_frame_document; + if (auto* local_frame = DynamicTo<LocalFrame>(GetPage()->MainFrame())) { + main_frame_document = local_frame->GetDocument(); + } + for (Frame* frame = GetPage()->MainFrame(); frame; frame = frame->Tree().TraverseNext()) { - if (auto* local_frame = DynamicTo<LocalFrame>(frame)) - documents.push_back(local_frame->GetDocument()); + if (auto* local_frame = DynamicTo<LocalFrame>(frame)) { + if (local_frame->GetDocument() != main_frame_document) { + child_frame_documents.push_back(local_frame->GetDocument()); + } + } } // A null `activation_start` is sent to the WebViewImpl that does not host the // main frame, in which case we expect that it does not have any documents // since cross-origin documents are not loaded during prerendering. - DCHECK(documents.size() == 0 || + DCHECK((!main_frame_document && child_frame_documents.size() == 0) || !prerender_page_activation_params->activation_start.is_null()); + // We also only send view_transition_state to the main frame. + DCHECK(main_frame_document || + !prerender_page_activation_params->view_transition_state); + + if (main_frame_document) { + main_frame_document->ActivateForPrerendering( + *prerender_page_activation_params); + prerender_page_activation_params->view_transition_state.reset(); + } // While the spec says to post a task on the networking task source for each // document, we don't post a task here for simplicity. This allows dispatching // the event on all documents without a chance for other IPCs from the browser // to arrive in the intervening time, resulting in an unclear state. - for (auto& document : documents) { + for (auto& document : child_frame_documents) { document->ActivateForPrerendering(*prerender_page_activation_params); }
diff --git a/third_party/blink/renderer/core/frame/frame.cc b/third_party/blink/renderer/core/frame/frame.cc index b211523..22bf66c 100644 --- a/third_party/blink/renderer/core/frame/frame.cc +++ b/third_party/blink/renderer/core/frame/frame.cc
@@ -342,17 +342,6 @@ HTMLObjectElement::ErrorEventPolicy::kDispatch); } -void Frame::RenderFallbackContentWithResourceTiming( - mojom::blink::ResourceTimingInfoPtr timing, - const String& server_timing_value) { - auto* local_dom_window = To<LocalDOMWindow>(Parent()->DomWindow()); - DOMWindowPerformance::performance(*local_dom_window) - ->AddResourceTimingWithUnparsedServerTiming( - std::move(timing), server_timing_value, - html_names::kObjectTag.LocalName()); - RenderFallbackContent(); -} - bool Frame::IsInFencedFrameTree() const { DCHECK(!IsDetached()); if (!features::IsFencedFramesEnabled())
diff --git a/third_party/blink/renderer/core/frame/frame.h b/third_party/blink/renderer/core/frame/frame.h index df85fa1..5cfb8cd 100644 --- a/third_party/blink/renderer/core/frame/frame.h +++ b/third_party/blink/renderer/core/frame/frame.h
@@ -481,9 +481,6 @@ void ClearUserActivationInFrameTree(); void RenderFallbackContent(); - void RenderFallbackContentWithResourceTiming( - mojom::blink::ResourceTimingInfoPtr timing, - const String& server_timing_values); // Only implemented for LocalFrames. virtual void ActivateHistoryUserActivationState() {}
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc index d3a43f5..e26eebb 100644 --- a/third_party/blink/renderer/core/frame/local_frame.cc +++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -229,28 +229,6 @@ namespace { -const AtomicString& ConvertElementTypeToInitiatorType( - blink::FrameOwnerElementType frame_owner_elem_type) { - switch (frame_owner_elem_type) { - case blink::FrameOwnerElementType::kFrame: - return blink::html_names::kFrameTag.LocalName(); - case blink::FrameOwnerElementType::kIframe: - return blink::html_names::kIFrameTag.LocalName(); - case blink::FrameOwnerElementType::kObject: - return blink::html_names::kObjectTag.LocalName(); - case blink::FrameOwnerElementType::kFencedframe: - return blink::html_names::kFencedframeTag.LocalName(); - case blink::FrameOwnerElementType::kEmbed: - return blink::html_names::kEmbedTag.LocalName(); - case blink::FrameOwnerElementType::kPortal: - return blink::html_names::kPortalTag.LocalName(); - case blink::FrameOwnerElementType::kNone: - NOTREACHED(); - } - NOTREACHED(); - return blink::html_names::kFrameTag.LocalName(); -} - // Maintain a global (statically-allocated) hash map indexed by the the result // of hashing the |frame_token| passed on creation of a LocalFrame object. using LocalFramesByTokenMap = HeapHashMap<uint64_t, WeakMember<LocalFrame>>; @@ -749,15 +727,6 @@ return local_root.clip_path_paint_image_generator_.Get(); } -void LocalFrame::AddResourceTimingEntryFromNonNavigatedFrame( - mojom::blink::ResourceTimingInfoPtr timing, - blink::FrameOwnerElementType initiator_type) { - auto* local_dom_window = DomWindow(); - DOMWindowPerformance::performance(*local_dom_window) - ->AddResourceTiming(std::move(timing), - ConvertElementTypeToInitiatorType(initiator_type)); -} - const SecurityContext* LocalFrame::GetSecurityContext() const { return DomWindow() ? &DomWindow()->GetSecurityContext() : nullptr; }
diff --git a/third_party/blink/renderer/core/frame/local_frame.h b/third_party/blink/renderer/core/frame/local_frame.h index 4d4a5aa..bd10cad9 100644 --- a/third_party/blink/renderer/core/frame/local_frame.h +++ b/third_party/blink/renderer/core/frame/local_frame.h
@@ -293,10 +293,6 @@ BoxShadowPaintImageGenerator* GetBoxShadowPaintImageGenerator(); ClipPathPaintImageGenerator* GetClipPathPaintImageGenerator(); - void AddResourceTimingEntryFromNonNavigatedFrame( - mojom::blink::ResourceTimingInfoPtr timing, - blink::FrameOwnerElementType initiator_type); - // A local root is the root of a connected subtree that contains only // LocalFrames. The local root is responsible for coordinating input, layout, // et cetera for that subtree of frames.
diff --git a/third_party/blink/renderer/core/frame/local_frame_client.h b/third_party/blink/renderer/core/frame/local_frame_client.h index 553afb5..2e876bb 100644 --- a/third_party/blink/renderer/core/frame/local_frame_client.h +++ b/third_party/blink/renderer/core/frame/local_frame_client.h
@@ -187,7 +187,8 @@ const LocalFrameToken* initiator_frame_token, std::unique_ptr<SourceLocation> source_location, mojo::PendingRemote<mojom::blink::PolicyContainerHostKeepAliveHandle> - initiator_policy_container_handle) = 0; + initiator_policy_container_handle, + bool is_container_initiated) = 0; virtual void DispatchWillSendSubmitEvent(HTMLFormElement*) = 0;
diff --git a/third_party/blink/renderer/core/frame/local_frame_client_impl.cc b/third_party/blink/renderer/core/frame/local_frame_client_impl.cc index c4a59332..3e43e9d7 100644 --- a/third_party/blink/renderer/core/frame/local_frame_client_impl.cc +++ b/third_party/blink/renderer/core/frame/local_frame_client_impl.cc
@@ -526,7 +526,8 @@ const LocalFrameToken* initiator_frame_token, std::unique_ptr<SourceLocation> source_location, mojo::PendingRemote<mojom::blink::PolicyContainerHostKeepAliveHandle> - initiator_policy_container_keep_alive_handle) { + initiator_policy_container_keep_alive_handle, + bool is_container_initiated) { if (!web_frame_->Client()) return; @@ -685,6 +686,7 @@ .GetSandboxFlags(); navigation_info->href_translate = href_translate; + navigation_info->is_container_initiated = is_container_initiated; web_frame_->Client()->BeginNavigation(std::move(navigation_info)); }
diff --git a/third_party/blink/renderer/core/frame/local_frame_client_impl.h b/third_party/blink/renderer/core/frame/local_frame_client_impl.h index 5d2c642..fc56200 100644 --- a/third_party/blink/renderer/core/frame/local_frame_client_impl.h +++ b/third_party/blink/renderer/core/frame/local_frame_client_impl.h
@@ -138,7 +138,8 @@ const LocalFrameToken* initiator_frame_token, std::unique_ptr<SourceLocation> source_location, mojo::PendingRemote<mojom::blink::PolicyContainerHostKeepAliveHandle> - initiator_policy_container_keep_alive_handle) override; + initiator_policy_container_keep_alive_handle, + bool is_container_initiated) override; void DispatchWillSendSubmitEvent(HTMLFormElement*) override; void DidStartLoading() override; void DidStopLoading() override;
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 index 238edb9c5..fe43461 100644 --- a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc +++ b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
@@ -10,6 +10,8 @@ #include "build/build_config.h" #include "components/power_scheduler/power_mode.h" #include "components/power_scheduler/power_mode_arbiter.h" +#include "services/network/public/cpp/url_loader_completion_status.h" +#include "services/network/public/mojom/url_response_head.mojom.h" #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" #include "third_party/blink/public/common/browser_interface_broker_proxy.h" #include "third_party/blink/public/common/chrome_debug_urls.h" @@ -67,6 +69,7 @@ #include "third_party/blink/renderer/core/script/classic_script.h" #include "third_party/blink/renderer/core/timing/dom_window_performance.h" #include "third_party/blink/renderer/core/view_transition/view_transition_supplement.h" +#include "third_party/blink/renderer/platform/loader/fetch/resource_timing_utils.h" #include "third_party/blink/renderer/platform/widget/frame_widget.h" #if BUILDFLAG(IS_MAC) @@ -667,20 +670,6 @@ frame_->RenderFallbackContent(); } -void LocalFrameMojoHandler::RenderFallbackContentWithResourceTiming( - mojom::blink::ResourceTimingInfoPtr timing, - const String& server_timing_value) { - frame_->RenderFallbackContentWithResourceTiming(std::move(timing), - server_timing_value); -} - -void LocalFrameMojoHandler::AddResourceTimingEntryFromNonNavigatedFrame( - mojom::blink::ResourceTimingInfoPtr timing, - blink::FrameOwnerElementType parent_frame_owner_element_type) { - frame_->AddResourceTimingEntryFromNonNavigatedFrame( - std::move(timing), parent_frame_owner_element_type); -} - void LocalFrameMojoHandler::BeforeUnload(bool is_reload, BeforeUnloadCallback callback) { base::TimeTicks before_unload_start_time = base::TimeTicks::Now(); @@ -1356,6 +1345,51 @@ BeforeUnload(is_reload, std::move(callback)); } +void LocalFrameMojoHandler::AddResourceTimingEntryForFailedSubframeNavigation( + const FrameToken& subframe_token, + const KURL& initial_url, + base::TimeTicks start_time, + base::TimeTicks redirect_time, + base::TimeTicks request_start, + base::TimeTicks response_start, + uint32_t response_code, + const WTF::String& mime_type, + network::mojom::blink::LoadTimingInfoPtr load_timing_info, + net::HttpResponseInfo::ConnectionInfo connection_info, + const WTF::String& alpn_negotiated_protocol, + bool is_secure_transport, + bool is_validated, + const WTF::String& normalized_server_timing, + const network::URLLoaderCompletionStatus& completion_status) { + Frame* subframe = Frame::ResolveFrame(subframe_token); + if (!subframe || !subframe->Owner()) { + return; + } + + ResourceResponse response; + response.SetAlpnNegotiatedProtocol(AtomicString(alpn_negotiated_protocol)); + response.SetConnectionInfo(connection_info); + response.SetConnectionReused(load_timing_info->socket_reused); + response.SetTimingAllowPassed(true); + response.SetIsValidated(is_validated); + response.SetDecodedBodyLength(completion_status.decoded_body_length); + response.SetEncodedBodyLength(completion_status.encoded_body_length); + response.SetEncodedDataLength(completion_status.encoded_data_length); + response.SetHttpStatusCode(response_code); + if (!normalized_server_timing.empty()) { + response.SetHttpHeaderField("Server-Timing", + AtomicString(normalized_server_timing)); + } + + mojom::blink::ResourceTimingInfoPtr info = + CreateResourceTimingInfo(start_time, initial_url, &response); + info->response_end = completion_status.completion_time; + info->last_redirect_end_time = redirect_time; + info->is_secure_transport = is_secure_transport; + info->timing = std::move(load_timing_info); + subframe->Owner()->AddResourceTiming(std::move(info)); +} + void LocalFrameMojoHandler::RequestFullscreenVideoElement() { // Find the first video element of the frame. for (auto* child = frame_->GetDocument()->documentElement(); child;
diff --git a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.h b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.h index 9e4185a5..a31557c9 100644 --- a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.h +++ b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.h
@@ -19,6 +19,7 @@ #include "third_party/blink/renderer/platform/mojo/heap_mojo_associated_remote.h" #include "third_party/blink/renderer/platform/mojo/heap_mojo_receiver.h" #include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h" +#include "third_party/blink/renderer/platform/weborigin/kurl.h" #if BUILDFLAG(IS_MAC) #include "third_party/blink/public/mojom/input/text_input_host.mojom-blink.h" @@ -118,12 +119,6 @@ void SaveImageAt(const gfx::Point& window_point) final; void ReportBlinkFeatureUsage(const Vector<mojom::blink::WebFeature>&) final; void RenderFallbackContent() final; - void RenderFallbackContentWithResourceTiming( - mojom::blink::ResourceTimingInfoPtr timing, - const String& server_timing_values) final; - void AddResourceTimingEntryFromNonNavigatedFrame( - mojom::blink::ResourceTimingInfoPtr timing, - blink::FrameOwnerElementType parent_frame_owner_element_type) final; void BeforeUnload(bool is_reload, BeforeUnloadCallback callback) final; void MediaPlayerActionAt( const gfx::Point& window_point, @@ -207,6 +202,23 @@ void SnapshotDocumentForViewTransition( SnapshotDocumentForViewTransitionCallback callback) final; + void AddResourceTimingEntryForFailedSubframeNavigation( + const FrameToken& subframe_token, + const KURL& initial_url, + base::TimeTicks start_time, + base::TimeTicks redirect_time, + base::TimeTicks request_start, + base::TimeTicks response_start, + uint32_t response_code, + const WTF::String& mime_type, + network::mojom::blink::LoadTimingInfoPtr load_timing_info, + net::HttpResponseInfo::ConnectionInfo connection_info, + const WTF::String& alpn_negotiated_protocol, + bool is_secure_transport, + bool is_validated, + const WTF::String& normalized_server_timing, + const ::network::URLLoaderCompletionStatus& completion_status) final; + // blink::mojom::LocalMainFrame overrides: void AnimateDoubleTapZoom(const gfx::Point& point, const gfx::Rect& rect) override;
diff --git a/third_party/blink/renderer/core/frame/remote_frame.cc b/third_party/blink/renderer/core/frame/remote_frame.cc index a5c5ed7..b8546a7a 100644 --- a/third_party/blink/renderer/core/frame/remote_frame.cc +++ b/third_party/blink/renderer/core/frame/remote_frame.cc
@@ -304,6 +304,7 @@ GetNavigationInitiatorActivationAndAdStatus(request.HasUserGesture(), is_ad_script_in_stack); + params->is_container_initiated = frame_request.IsContainerInitiated(); GetRemoteFrameHostRemote().OpenURL(std::move(params)); } @@ -409,25 +410,11 @@ Frame::RenderFallbackContent(); } -void RemoteFrame::RenderFallbackContentWithResourceTiming( - mojom::blink::ResourceTimingInfoPtr timing, - const String& server_timing_value) { - Frame::RenderFallbackContentWithResourceTiming(std::move(timing), - server_timing_value); -} - void RemoteFrame::AddResourceTimingFromChild( mojom::blink::ResourceTimingInfoPtr timing) { HTMLFrameOwnerElement* owner_element = To<HTMLFrameOwnerElement>(Owner()); DCHECK(owner_element); - - if (!owner_element->HasPendingFallbackTimingInfo()) { - return; - } - - DOMWindowPerformance::performance(*owner_element->GetDocument().domWindow()) - ->AddResourceTiming(std::move(timing), owner_element->localName()); - owner_element->DidReportResourceTiming(); + owner_element->AddResourceTiming(std::move(timing)); } void RemoteFrame::DidStartLoading() {
diff --git a/third_party/blink/renderer/core/frame/remote_frame.h b/third_party/blink/renderer/core/frame/remote_frame.h index 6c1aaec..eedd7f6 100644 --- a/third_party/blink/renderer/core/frame/remote_frame.h +++ b/third_party/blink/renderer/core/frame/remote_frame.h
@@ -182,9 +182,6 @@ const base::UnguessableToken& embedding_token) override; void SetPageFocus(bool is_focused) override; void RenderFallbackContent() override; - void RenderFallbackContentWithResourceTiming( - mojom::blink::ResourceTimingInfoPtr timing, - const String& server_timing_values) final; void ScrollRectToVisible( const gfx::RectF& rect_to_scroll, mojom::blink::ScrollIntoViewParamsPtr params) override;
diff --git a/third_party/blink/renderer/core/fullscreen/fullscreen.cc b/third_party/blink/renderer/core/fullscreen/fullscreen.cc index 862d9ac3..8c639c1 100644 --- a/third_party/blink/renderer/core/fullscreen/fullscreen.cc +++ b/third_party/blink/renderer/core/fullscreen/fullscreen.cc
@@ -210,7 +210,8 @@ document.GetExecutionContext())) { HTMLElement::HideAllPopoversUntil( nullptr, document, HidePopoverFocusBehavior::kNone, - HidePopoverTransitionBehavior::kFireEventsAndWaitForTransitions); + HidePopoverTransitionBehavior::kFireEventsAndWaitForTransitions, + HidePopoverIndependence::kHideUnrelated); } // To fullscreen an |element| within a |document|, set the |element|'s
diff --git a/third_party/blink/renderer/core/html/forms/base_button_input_type.cc b/third_party/blink/renderer/core/html/forms/base_button_input_type.cc index 417394a16..5933067e 100644 --- a/third_party/blink/renderer/core/html/forms/base_button_input_type.cc +++ b/third_party/blink/renderer/core/html/forms/base_button_input_type.cc
@@ -65,7 +65,7 @@ } void BaseButtonInputType::ValueAttributeChanged() { - To<Text>(GetElement().UserAgentShadowRoot()->firstChild()) + To<Text>(GetElement().EnsureShadowSubtree()->firstChild()) ->setData(GetElement().ValueOrDefaultLabel()); }
diff --git a/third_party/blink/renderer/core/html/forms/chooser_only_temporal_input_type_view.cc b/third_party/blink/renderer/core/html/forms/chooser_only_temporal_input_type_view.cc index 8dbfdeb..d75b73da 100644 --- a/third_party/blink/renderer/core/html/forms/chooser_only_temporal_input_type_view.cc +++ b/third_party/blink/renderer/core/html/forms/chooser_only_temporal_input_type_view.cc
@@ -102,7 +102,7 @@ } void ChooserOnlyTemporalInputTypeView::UpdateView() { - Node* node = GetElement().UserAgentShadowRoot()->firstChild(); + Node* node = GetElement().EnsureShadowSubtree()->firstChild(); auto* html_element = DynamicTo<HTMLElement>(node); if (!html_element) return;
diff --git a/third_party/blink/renderer/core/html/forms/file_input_type.cc b/third_party/blink/renderer/core/html/forms/file_input_type.cc index e698265..a20cd839 100644 --- a/third_party/blink/renderer/core/html/forms/file_input_type.cc +++ b/third_party/blink/renderer/core/html/forms/file_input_type.cc
@@ -363,14 +363,14 @@ } HTMLInputElement* FileInputType::UploadButton() const { - Element* element = GetElement().UserAgentShadowRoot()->getElementById( + Element* element = GetElement().EnsureShadowSubtree()->getElementById( shadow_element_names::kIdFileUploadButton); CHECK(!element || IsA<HTMLInputElement>(element)); return To<HTMLInputElement>(element); } Node* FileInputType::FileStatusElement() const { - return GetElement().UserAgentShadowRoot()->lastChild(); + return GetElement().EnsureShadowSubtree()->lastChild(); } void FileInputType::DisabledAttributeChanged() {
diff --git a/third_party/blink/renderer/core/html/forms/file_input_type_test.cc b/third_party/blink/renderer/core/html/forms/file_input_type_test.cc index 5e2ad55..981372a 100644 --- a/third_party/blink/renderer/core/html/forms/file_input_type_test.cc +++ b/third_party/blink/renderer/core/html/forms/file_input_type_test.cc
@@ -243,7 +243,7 @@ // Receiving a FileChooser response should not alter a shadow tree // for another type. EXPECT_TRUE(IsA<HTMLElement>( - input.UserAgentShadowRoot()->firstChild()->firstChild())); + input.EnsureShadowSubtree()->firstChild()->firstChild())); } // Tests selecting same file twice should fire cancel event second time.
diff --git a/third_party/blink/renderer/core/html/forms/html_input_element.cc b/third_party/blink/renderer/core/html/forms/html_input_element.cc index 3fa23d3..06f6d61 100644 --- a/third_party/blink/renderer/core/html/forms/html_input_element.cc +++ b/third_party/blink/renderer/core/html/forms/html_input_element.cc
@@ -44,6 +44,7 @@ #include "third_party/blink/renderer/core/css/style_change_reason.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/dom_token_list.h" +#include "third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.h" #include "third_party/blink/renderer/core/dom/events/scoped_event_queue.h" #include "third_party/blink/renderer/core/dom/events/simulated_click_options.h" #include "third_party/blink/renderer/core/dom/id_target_observer.h" @@ -148,12 +149,6 @@ : MakeGarbageCollected<TextInputType>(*this)), input_type_view_(input_type_ ? input_type_->CreateView() : nullptr) { SetHasCustomStyleCallbacks(); - - if (!flags.IsCreatedByParser()) { - DCHECK(input_type_view_->NeedsShadowSubtree()); - CreateUserAgentShadowRoot(); - CreateShadowSubtree(); - } } void HTMLInputElement::Trace(Visitor* visitor) const { @@ -383,6 +378,7 @@ } void HTMLInputElement::setType(const AtomicString& type) { + EnsureShadowSubtree(); setAttribute(html_names::kTypeAttr, type); } @@ -400,11 +396,6 @@ non_attribute_value_ = SanitizeValue(default_value); has_been_password_field_ |= new_type_name == input_type_names::kPassword; - if (input_type_view_->NeedsShadowSubtree()) { - CreateUserAgentShadowRoot(); - CreateShadowSubtree(); - } - UpdateWillValidateCache(); if (!default_value.IsNull()) @@ -477,10 +468,8 @@ input_type_view_->WillBeDestroyed(); input_type_ = new_type; input_type_view_ = input_type_->CreateView(); - if (input_type_view_->NeedsShadowSubtree()) { - EnsureUserAgentShadowRoot(); - CreateShadowSubtree(); - } + + input_type_view_->CreateShadowSubtreeIfNeeded(); UpdateWillValidateCache(); @@ -1512,8 +1501,9 @@ TextControlElement::DefaultEventHandler(evt); } -void HTMLInputElement::CreateShadowSubtree() { - input_type_view_->CreateShadowSubtree(); +ShadowRoot* HTMLInputElement::EnsureShadowSubtree() { + input_type_view_->CreateShadowSubtreeIfNeeded(); + return UserAgentShadowRoot(); } bool HTMLInputElement::HasActivationBehavior() const { @@ -1720,6 +1710,10 @@ ResetListAttributeTargetObserver(); LogAddElementIfIsolatedWorldAndInDocument("input", html_names::kTypeAttr, html_names::kFormactionAttr); + { + EventDispatchForbiddenScope::AllowUserAgentEvents allow_events; + input_type_view_->CreateShadowSubtreeIfNeeded(); + } return kInsertionShouldCallDidNotifySubtreeInsertions; } @@ -1966,6 +1960,11 @@ return input_type_->SupportsPlaceholder(); } +TextControlInnerEditorElement* HTMLInputElement::EnsureInnerEditorElement() + const { + return input_type_view_->EnsureInnerEditorElement(); +} + void HTMLInputElement::UpdatePlaceholderText() { return input_type_view_->UpdatePlaceholderText(!SuggestedValue().empty()); }
diff --git a/third_party/blink/renderer/core/html/forms/html_input_element.h b/third_party/blink/renderer/core/html/forms/html_input_element.h index 513daa0..fa8a8b76 100644 --- a/third_party/blink/renderer/core/html/forms/html_input_element.h +++ b/third_party/blink/renderer/core/html/forms/html_input_element.h
@@ -370,9 +370,10 @@ bool isMutable(); void showPicker(ExceptionState&); + ShadowRoot* EnsureShadowSubtree(); + protected: void DefaultEventHandler(Event&) override; - void CreateShadowSubtree(); private: enum AutoCompleteSetting { kUninitialized, kOn, kOff }; @@ -439,6 +440,7 @@ bool TooLong(const String&, NeedsToCheckDirtyFlag) const; bool TooShort(const String&, NeedsToCheckDirtyFlag) const; + TextControlInnerEditorElement* EnsureInnerEditorElement() const final; void UpdatePlaceholderText() final; bool IsEmptyValue() const final { return InnerEditorValue().empty(); } void HandleBlurEvent() final;
diff --git a/third_party/blink/renderer/core/html/forms/html_input_element_test.cc b/third_party/blink/renderer/core/html/forms/html_input_element_test.cc index 6fa1dd6..7aa8d08 100644 --- a/third_party/blink/renderer/core/html/forms/html_input_element_test.cc +++ b/third_party/blink/renderer/core/html/forms/html_input_element_test.cc
@@ -150,7 +150,7 @@ TEST_F(HTMLInputElementTest, create) { auto* input = MakeGarbageCollected<HTMLInputElement>( GetDocument(), CreateElementFlags::ByCreateElement()); - EXPECT_NE(nullptr, input->UserAgentShadowRoot()); + EXPECT_EQ(nullptr, input->UserAgentShadowRoot()); input = MakeGarbageCollected<HTMLInputElement>( GetDocument(), CreateElementFlags::ByParser(&GetDocument()));
diff --git a/third_party/blink/renderer/core/html/forms/html_text_area_element.cc b/third_party/blink/renderer/core/html/forms/html_text_area_element.cc index f87fd80e..e2e8c75 100644 --- a/third_party/blink/renderer/core/html/forms/html_text_area_element.cc +++ b/third_party/blink/renderer/core/html/forms/html_text_area_element.cc
@@ -682,6 +682,11 @@ is_placeholder_visible_ = visible; } +TextControlInnerEditorElement* HTMLTextAreaElement::EnsureInnerEditorElement() + const { + return InnerEditorElement(); +} + void HTMLTextAreaElement::UpdatePlaceholderText() { HTMLElement* placeholder = PlaceholderElement(); const String placeholder_text = GetPlaceholderValue();
diff --git a/third_party/blink/renderer/core/html/forms/html_text_area_element.h b/third_party/blink/renderer/core/html/forms/html_text_area_element.h index 69813f0..6b06d31 100644 --- a/third_party/blink/renderer/core/html/forms/html_text_area_element.h +++ b/third_party/blink/renderer/core/html/forms/html_text_area_element.h
@@ -97,6 +97,7 @@ String GetPlaceholderValue() const final; void UpdatePlaceholderText() override; bool IsEmptyValue() const override { return Value().empty(); } + TextControlInnerEditorElement* EnsureInnerEditorElement() const final; bool IsOptionalFormControl() const override { return !IsRequiredFormControl();
diff --git a/third_party/blink/renderer/core/html/forms/input_type_view.cc b/third_party/blink/renderer/core/html/forms/input_type_view.cc index ea94f0c4..c5560ce6 100644 --- a/third_party/blink/renderer/core/html/forms/input_type_view.cc +++ b/third_party/blink/renderer/core/html/forms/input_type_view.cc
@@ -130,8 +130,22 @@ return true; } +TextControlInnerEditorElement* InputTypeView::EnsureInnerEditorElement() { + CreateShadowSubtreeIfNeeded(); + return GetElement().InnerEditorElement(); +} + void InputTypeView::CreateShadowSubtree() {} +void InputTypeView::CreateShadowSubtreeIfNeeded() { + if (has_created_shadow_subtree_ || !NeedsShadowSubtree()) { + return; + } + GetElement().EnsureUserAgentShadowRoot(); + has_created_shadow_subtree_ = true; + CreateShadowSubtree(); +} + void InputTypeView::DestroyShadowSubtree() { if (ShadowRoot* root = GetElement().UserAgentShadowRoot()) root->RemoveChildren();
diff --git a/third_party/blink/renderer/core/html/forms/input_type_view.h b/third_party/blink/renderer/core/html/forms/input_type_view.h index bff1971..f8d8d57 100644 --- a/third_party/blink/renderer/core/html/forms/input_type_view.h +++ b/third_party/blink/renderer/core/html/forms/input_type_view.h
@@ -59,6 +59,7 @@ class LayoutObject; enum class LegacyLayout; class MouseEvent; +class TextControlInnerEditorElement; class ClickHandlingState final : public EventDispatchHandlingState { public: @@ -119,6 +120,9 @@ // Functions for shadow trees + TextControlInnerEditorElement* EnsureInnerEditorElement(); + bool HasCreatedShadowSubtree() const { return has_created_shadow_subtree_; } + void CreateShadowSubtreeIfNeeded(); virtual bool NeedsShadowSubtree() const; virtual void CreateShadowSubtree(); virtual void DestroyShadowSubtree(); @@ -161,6 +165,7 @@ bool will_be_destroyed_ = false; private: + bool has_created_shadow_subtree_ = false; Member<HTMLInputElement> element_; };
diff --git a/third_party/blink/renderer/core/html/forms/multiple_fields_temporal_input_type_view.cc b/third_party/blink/renderer/core/html/forms/multiple_fields_temporal_input_type_view.cc index b7b9ef34..ecbfc9eb 100644 --- a/third_party/blink/renderer/core/html/forms/multiple_fields_temporal_input_type_view.cc +++ b/third_party/blink/renderer/core/html/forms/multiple_fields_temporal_input_type_view.cc
@@ -142,7 +142,7 @@ DateTimeEditElement* MultipleFieldsTemporalInputTypeView::GetDateTimeEditElement() const { - auto* element = GetElement().UserAgentShadowRoot()->getElementById( + auto* element = GetElement().EnsureShadowSubtree()->getElementById( shadow_element_names::kIdDateTimeEdit); CHECK(!element || IsA<DateTimeEditElement>(element)); return To<DateTimeEditElement>(element); @@ -150,7 +150,7 @@ SpinButtonElement* MultipleFieldsTemporalInputTypeView::GetSpinButtonElement() const { - auto* element = GetElement().UserAgentShadowRoot()->getElementById( + auto* element = GetElement().EnsureShadowSubtree()->getElementById( shadow_element_names::kIdSpinButton); CHECK(!element || IsA<SpinButtonElement>(element)); return To<SpinButtonElement>(element); @@ -158,7 +158,7 @@ ClearButtonElement* MultipleFieldsTemporalInputTypeView::GetClearButtonElement() const { - auto* element = GetElement().UserAgentShadowRoot()->getElementById( + auto* element = GetElement().EnsureShadowSubtree()->getElementById( shadow_element_names::kIdClearButton); CHECK(!element || IsA<ClearButtonElement>(element)); return To<ClearButtonElement>(element); @@ -166,7 +166,7 @@ PickerIndicatorElement* MultipleFieldsTemporalInputTypeView::GetPickerIndicatorElement() const { - auto* element = GetElement().UserAgentShadowRoot()->getElementById( + auto* element = GetElement().EnsureShadowSubtree()->getElementById( shadow_element_names::kIdPickerIndicator); CHECK(!element || IsA<PickerIndicatorElement>(element)); return To<PickerIndicatorElement>(element); @@ -174,7 +174,7 @@ inline bool MultipleFieldsTemporalInputTypeView::ContainsFocusedShadowElement() const { - return GetElement().UserAgentShadowRoot()->contains( + return GetElement().EnsureShadowSubtree()->contains( GetElement().GetDocument().FocusedElement()); }
diff --git a/third_party/blink/renderer/core/html/forms/password_input_type.cc b/third_party/blink/renderer/core/html/forms/password_input_type.cc index 394a0da..a5a3c6dc 100644 --- a/third_party/blink/renderer/core/html/forms/password_input_type.cc +++ b/third_party/blink/renderer/core/html/forms/password_input_type.cc
@@ -152,7 +152,7 @@ } void PasswordInputType::UpdatePasswordRevealButton() { - Element* button = GetElement().UserAgentShadowRoot()->getElementById( + Element* button = GetElement().EnsureShadowSubtree()->getElementById( shadow_element_names::kIdPasswordRevealButton); // Update the glyph.
diff --git a/third_party/blink/renderer/core/html/forms/range_input_type.cc b/third_party/blink/renderer/core/html/forms/range_input_type.cc index 0b197552..2cd86c9 100644 --- a/third_party/blink/renderer/core/html/forms/range_input_type.cc +++ b/third_party/blink/renderer/core/html/forms/range_input_type.cc
@@ -152,6 +152,10 @@ } void RangeInputType::HandleMouseDownEvent(MouseEvent& event) { + if (!HasCreatedShadowSubtree()) { + return; + } + if (GetElement().IsDisabledFormControl()) return; @@ -299,7 +303,9 @@ } void RangeInputType::UpdateView() { - GetSliderThumbElement()->SetPositionFromValue(); + if (HasCreatedShadowSubtree()) { + GetSliderThumbElement()->SetPositionFromValue(); + } } String RangeInputType::SanitizeValue(const String& proposed_value) const { @@ -317,6 +323,9 @@ } void RangeInputType::DisabledAttributeChanged() { + if (!HasCreatedShadowSubtree()) { + return; + } if (GetElement().IsDisabledFormControl()) GetSliderThumbElement()->StopDragging(); } @@ -332,6 +341,10 @@ } inline Element* RangeInputType::SliderTrackElement() const { + if (!HasCreatedShadowSubtree()) { + return nullptr; + } + return GetElement().UserAgentShadowRoot()->getElementById( shadow_element_names::kIdSliderTrack); } @@ -341,7 +354,7 @@ if (auto* object = GetElement().GetLayoutObject()) object->SetSubtreeShouldDoFullPaintInvalidation(); Element* slider_track_element = SliderTrackElement(); - if (slider_track_element->GetLayoutObject()) { + if (slider_track_element && slider_track_element->GetLayoutObject()) { slider_track_element->GetLayoutObject()->SetNeedsLayout( layout_invalidation_reason::kAttributeChanged); }
diff --git a/third_party/blink/renderer/core/html/forms/search_input_type.cc b/third_party/blink/renderer/core/html/forms/search_input_type.cc index 34ab3adf..4e3e822 100644 --- a/third_party/blink/renderer/core/html/forms/search_input_type.cc +++ b/third_party/blink/renderer/core/html/forms/search_input_type.cc
@@ -147,7 +147,7 @@ } void SearchInputType::UpdateCancelButtonVisibility() { - Element* button = GetElement().UserAgentShadowRoot()->getElementById( + Element* button = GetElement().EnsureShadowSubtree()->getElementById( shadow_element_names::kIdSearchClearButton); if (!button) return;
diff --git a/third_party/blink/renderer/core/html/forms/slider_thumb_element.cc b/third_party/blink/renderer/core/html/forms/slider_thumb_element.cc index 9c7f28d..265ed91 100644 --- a/third_party/blink/renderer/core/html/forms/slider_thumb_element.cc +++ b/third_party/blink/renderer/core/html/forms/slider_thumb_element.cc
@@ -95,7 +95,7 @@ void SliderThumbElement::SetPositionFromPoint(const LayoutPoint& point) { HTMLInputElement* input(HostInput()); - Element* track_element = input->UserAgentShadowRoot()->getElementById( + Element* track_element = input->EnsureShadowSubtree()->getElementById( shadow_element_names::kIdSliderTrack); const LayoutObject* input_object = input->GetLayoutObject(); @@ -329,8 +329,10 @@ void SliderContainerElement::HandleTouchEvent(TouchEvent* event) { HTMLInputElement* input = HostInput(); - if (!input || input->IsDisabledFormControl() || !event) + if (!input || !input->UserAgentShadowRoot() || + input->IsDisabledFormControl() || !event) { return; + } if (event->type() == event_type_names::kTouchend) { // TODO: Also do this for touchcancel?
diff --git a/third_party/blink/renderer/core/html/forms/text_control_element.cc b/third_party/blink/renderer/core/html/forms/text_control_element.cc index 6c92c005..e9e6dcd 100644 --- a/third_party/blink/renderer/core/html/forms/text_control_element.cc +++ b/third_party/blink/renderer/core/html/forms/text_control_element.cc
@@ -157,7 +157,9 @@ if (event.type() == event_type_names::kBlur || event.type() == event_type_names::kFocus) return; - InnerEditorElement()->DefaultEventHandler(event); + if (auto* inner_editor = InnerEditorElement()) { + inner_editor->DefaultEventHandler(event); + } } String TextControlElement::StrippedPlaceholder() const { @@ -197,11 +199,13 @@ } HTMLElement* TextControlElement::PlaceholderElement() const { + ShadowRoot* root = UserAgentShadowRoot(); + if (!root) { + return nullptr; + } if (!SupportsPlaceholder()) return nullptr; - DCHECK(UserAgentShadowRoot()); - auto* element = UserAgentShadowRoot()->getElementById( - shadow_element_names::kIdPlaceholder); + auto* element = root->getElementById(shadow_element_names::kIdPlaceholder); CHECK(!element || IsA<HTMLElement>(element)); return To<HTMLElement>(element); } @@ -481,7 +485,7 @@ if (ShouldApplySelectionCache() || !isConnected()) return did_change; - HTMLElement* inner_editor = InnerEditorElement(); + HTMLElement* inner_editor = EnsureInnerEditorElement(); if (!frame || !inner_editor) return did_change; @@ -848,10 +852,8 @@ if (!IsTextControl() || OpenShadowRoot()) return; - DCHECK(InnerEditorElement()); - bool text_is_changed = value != InnerEditorValue(); - HTMLElement* inner_editor = InnerEditorElement(); + HTMLElement* inner_editor = EnsureInnerEditorElement(); if (!text_is_changed && inner_editor->HasChildren()) return;
diff --git a/third_party/blink/renderer/core/html/forms/text_control_element.h b/third_party/blink/renderer/core/html/forms/text_control_element.h index 8ac4c3f..2d6dc7cb 100644 --- a/third_party/blink/renderer/core/html/forms/text_control_element.h +++ b/third_party/blink/renderer/core/html/forms/text_control_element.h
@@ -136,6 +136,7 @@ TextControlInnerEditorElement* InnerEditorElement() const { return inner_editor_; } + virtual TextControlInnerEditorElement* EnsureInnerEditorElement() const = 0; HTMLElement* CreateInnerEditorElement(); void DropInnerEditorElement() { inner_editor_ = nullptr; }
diff --git a/third_party/blink/renderer/core/html/forms/text_field_input_type.cc b/third_party/blink/renderer/core/html/forms/text_field_input_type.cc index 81c74c1..d5e522b 100644 --- a/third_party/blink/renderer/core/html/forms/text_field_input_type.cc +++ b/third_party/blink/renderer/core/html/forms/text_field_input_type.cc
@@ -127,6 +127,9 @@ } SpinButtonElement* TextFieldInputType::GetSpinButtonElement() const { + if (!HasCreatedShadowSubtree()) { + return nullptr; + } auto* element = GetElement().UserAgentShadowRoot()->getElementById( shadow_element_names::kIdSpinButton); CHECK(!element || IsA<SpinButtonElement>(element)); @@ -353,7 +356,7 @@ } Element* TextFieldInputType::ContainerElement() const { - return GetElement().UserAgentShadowRoot()->getElementById( + return GetElement().EnsureShadowSubtree()->getElementById( shadow_element_names::kIdTextFieldContainer); } @@ -364,6 +367,9 @@ } void TextFieldInputType::ListAttributeTargetChanged() { + if (!HasCreatedShadowSubtree()) { + return; + } if (ChromeClient* chrome_client = GetChromeClient()) chrome_client->TextFieldDataListChanged(GetElement()); Element* picker = GetElement().UserAgentShadowRoot()->getElementById( @@ -417,10 +423,16 @@ } void TextFieldInputType::DisabledAttributeChanged() { + if (!HasCreatedShadowSubtree()) { + return; + } DisabledOrReadonlyAttributeChanged(); } void TextFieldInputType::ReadonlyAttributeChanged() { + if (!HasCreatedShadowSubtree()) { + return; + } DisabledOrReadonlyAttributeChanged(); } @@ -519,6 +531,9 @@ } void TextFieldInputType::UpdatePlaceholderText(bool is_suggested_value) { + if (!HasCreatedShadowSubtree()) { + return; + } if (!SupportsPlaceholder()) return; HTMLElement* placeholder = GetElement().PlaceholderElement();
diff --git a/third_party/blink/renderer/core/html/html_dialog_element.cc b/third_party/blink/renderer/core/html/html_dialog_element.cc index f6b03a2..e1c14129 100644 --- a/third_party/blink/renderer/core/html/html_dialog_element.cc +++ b/third_party/blink/renderer/core/html/html_dialog_element.cc
@@ -39,6 +39,7 @@ #include "third_party/blink/renderer/core/frame/web_feature.h" #include "third_party/blink/renderer/core/fullscreen/fullscreen.h" #include "third_party/blink/renderer/core/html/forms/html_form_control_element.h" +#include "third_party/blink/renderer/core/html/html_element.h" #include "third_party/blink/renderer/core/html/html_frame_owner_element.h" #include "third_party/blink/renderer/core/style/computed_style.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" @@ -61,7 +62,8 @@ document.GetExecutionContext())) { HTMLElement::HideAllPopoversUntil( nullptr, document, HidePopoverFocusBehavior::kNone, - HidePopoverTransitionBehavior::kFireEventsAndWaitForTransitions); + HidePopoverTransitionBehavior::kFireEventsAndWaitForTransitions, + HidePopoverIndependence::kHideUnrelated); } dialog->previously_focused_element_ = document.FocusedElement(); @@ -357,7 +359,8 @@ GetDocument().GetExecutionContext())) { HTMLElement::HideAllPopoversUntil( nullptr, GetDocument(), HidePopoverFocusBehavior::kNone, - HidePopoverTransitionBehavior::kFireEventsAndWaitForTransitions); + HidePopoverTransitionBehavior::kFireEventsAndWaitForTransitions, + HidePopoverIndependence::kHideUnrelated); } Element* control = GetFocusDelegate(/*autofocus_only=*/false);
diff --git a/third_party/blink/renderer/core/html/html_element.cc b/third_party/blink/renderer/core/html/html_element.cc index 5745a1e..241080981 100644 --- a/third_party/blink/renderer/core/html/html_element.cc +++ b/third_party/blink/renderer/core/html/html_element.cc
@@ -100,6 +100,7 @@ #include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" #include "third_party/blink/renderer/platform/instrumentation/use_counter.h" +#include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "third_party/blink/renderer/platform/scheduler/public/post_cancellable_task.h" #include "third_party/blink/renderer/platform/text/bidi_resolver.h" #include "third_party/blink/renderer/platform/text/bidi_text_run.h" @@ -1161,6 +1162,9 @@ if (EqualIgnoringASCIICase(value, kPopoverTypeValueAuto) || (!value.IsNull() && value.empty())) { return PopoverValueType::kAuto; + } else if (EqualIgnoringASCIICase(value, kPopoverTypeValueHint) && + RuntimeEnabledFeatures::HTMLPopoverHintEnabled()) { + return PopoverValueType::kHint; } else if (EqualIgnoringASCIICase(value, kPopoverTypeValueManual)) { return PopoverValueType::kManual; } else if (!value.IsNull()) { @@ -1238,6 +1242,9 @@ case PopoverValueType::kAuto: UseCounter::Count(GetDocument(), WebFeature::kPopoverTypeAuto); break; + case PopoverValueType::kHint: + UseCounter::Count(GetDocument(), WebFeature::kPopoverTypeHint); + break; case PopoverValueType::kManual: UseCounter::Count(GetDocument(), WebFeature::kPopoverTypeManual); break; @@ -1254,6 +1261,27 @@ return GetPopoverData(); } +AtomicString HTMLElement::popover() const { + auto attribute_value = + FastGetAttribute(html_names::kPopoverAttr).LowerASCII(); + if (attribute_value.IsNull()) { + return attribute_value; // Nullable + } else if (attribute_value.empty()) { + return kPopoverTypeValueAuto; // ReflectEmpty = "auto" + } else if (attribute_value == kPopoverTypeValueAuto || + attribute_value == kPopoverTypeValueManual) { + return attribute_value; // ReflectOnly + } else if (attribute_value == kPopoverTypeValueHint && + RuntimeEnabledFeatures::HTMLPopoverHintEnabled()) { + return attribute_value; // ReflectOnly (with HTMLPopoverHint enabled) + } else { + return kPopoverTypeValueManual; // ReflectInvalid = "manual" + } +} +void HTMLElement::setPopover(const AtomicString& value) { + setAttribute(html_names::kPopoverAttr, value); +} + PopoverValueType HTMLElement::PopoverType() const { return GetPopoverData() ? GetPopoverData()->type() : PopoverValueType::kNone; } @@ -1398,13 +1426,33 @@ bool should_restore_focus = false; auto& document = GetDocument(); auto original_type = PopoverType(); - if (original_type == PopoverValueType::kAuto) { - // If the new popover is a popover=auto, hide any popover above this in the - // stack, if any. - const auto* auto_ancestor = FindTopmostPopoverAncestor(*this); - HideAllPopoversUntil( - auto_ancestor, document, HidePopoverFocusBehavior::kNone, - HidePopoverTransitionBehavior::kFireEventsAndWaitForTransitions); + if (original_type == PopoverValueType::kAuto || + original_type == PopoverValueType::kHint) { + const auto* ancestor = FindTopmostPopoverAncestor(*this); + if (original_type == PopoverValueType::kHint) { + DCHECK(RuntimeEnabledFeatures::HTMLPopoverHintEnabled()); + // If the new popover is popover=hint, hide other hints first. + if (document.PopoverHintShowing()) { + document.PopoverHintShowing()->HidePopoverInternal( + HidePopoverFocusBehavior::kNone, + HidePopoverTransitionBehavior::kFireEventsAndWaitForTransitions, + exception_state); + } + // Then hide open popovers that aren't ancestors of this hint. + if (ancestor) { + HideAllPopoversUntil( + ancestor, document, HidePopoverFocusBehavior::kNone, + HidePopoverTransitionBehavior::kFireEventsAndWaitForTransitions, + HidePopoverIndependence::kHideUnrelated); + } + } else { + // If the new popover is a popover=auto, hide any popover above this in + // the stack, if any. + HideAllPopoversUntil( + ancestor, document, HidePopoverFocusBehavior::kNone, + HidePopoverTransitionBehavior::kFireEventsAndWaitForTransitions, + HidePopoverIndependence::kHideUnrelated); + } // The 'beforetoggle' event handlers could have changed this popover, e.g. // by changing its type, removing it from the document, or calling @@ -1423,13 +1471,19 @@ return; } - // We only restore focus for popover=auto, and only for the first popover in - // the stack. If there's nothing showing, restore focus. - should_restore_focus = !document.TopmostPopover(); + // We only restore focus for popover=auto/hint, and only for the first + // popover in the stack. If there's nothing showing, restore focus. + should_restore_focus = !document.TopmostPopoverOrHint(); + // Add this popover to the popover stack. - auto& stack = document.PopoverStack(); - DCHECK(!stack.Contains(this)); - stack.push_back(this); + if (original_type == PopoverValueType::kAuto) { + auto& stack = document.PopoverStack(); + DCHECK(!stack.Contains(this)); + stack.push_back(this); + } else { + DCHECK(RuntimeEnabledFeatures::HTMLPopoverHintEnabled()); + document.SetPopoverHintShowing(this); + } } GetPopoverData()->setPreviouslyFocusedElement(nullptr); @@ -1485,51 +1539,98 @@ } // static -// All popovers up to, but not including, |endpoint|, will be hidden. +// All popovers up to, but not including, |endpoint|, will be hidden. If there +// are "unrelated" popovers open, such as a stack of popover=auto popovers and +// |endpoint| is a popover=hint, then the popover_independence argument controls +// whether those unrelated popover=auto popovers are hidden. void HTMLElement::HideAllPopoversUntil( const HTMLElement* endpoint, Document& document, HidePopoverFocusBehavior focus_behavior, - HidePopoverTransitionBehavior transition_behavior) { + HidePopoverTransitionBehavior transition_behavior, + HidePopoverIndependence popover_independence) { DCHECK(RuntimeEnabledFeatures::HTMLPopoverAttributeEnabled( document.GetExecutionContext())); DCHECK(!endpoint || endpoint->HasPopoverAttribute()); - + DCHECK(endpoint || + popover_independence == HidePopoverIndependence::kHideUnrelated); + // We never throw exceptions from HideAllPopoversUntil, since it is always + // used to close other popovers that are already showing. + ExceptionState* exception_state = nullptr; auto close_all_open_popovers = [&document, &focus_behavior, - &transition_behavior]() { - while (auto* popover = document.TopmostPopover()) { - // We never throw exceptions from HideAllPopoversUntil, since it is always - // used to close other popovers that are already showing. + &transition_behavior, &exception_state]() { + while (auto* popover = document.TopmostPopoverOrHint()) { popover->HidePopoverInternal(focus_behavior, transition_behavior, - /*exception_state=*/nullptr); + exception_state); } }; if (!endpoint) return close_all_open_popovers(); - DCHECK_EQ(endpoint->PopoverType(), PopoverValueType::kAuto); - // Then hide everything in the popover=auto stack until the last_to_hide - // popover is closed, or the stack is empty. - const HTMLElement* last_to_hide = nullptr; - bool found_endpoint = false; - for (auto popover : document.PopoverStack()) { - if (popover == endpoint) { - found_endpoint = true; - } else if (found_endpoint) { - last_to_hide = popover; - break; + if (endpoint->PopoverType() == PopoverValueType::kHint) { + DCHECK(RuntimeEnabledFeatures::HTMLPopoverHintEnabled()); + if (popover_independence == HidePopoverIndependence::kHideUnrelated) { + if (document.PopoverHintShowing() && + document.PopoverHintShowing() != endpoint) { + document.PopoverHintShowing()->HidePopoverInternal( + focus_behavior, transition_behavior, exception_state); + } + // Close all auto popovers. + for (auto popover : document.PopoverStack()) { + popover->HidePopoverInternal(focus_behavior, transition_behavior, + exception_state); + } } - } - if (!found_endpoint) - return close_all_open_popovers(); - while (last_to_hide && last_to_hide->popoverOpen() && - !document.PopoverStack().empty()) { - // We never throw exceptions from HideAllPopoversUntil, since it is always - // used to close other popovers that are already showing. - document.PopoverStack().back()->HidePopoverInternal( - focus_behavior, transition_behavior, - /*exception_state=*/nullptr); + } else { + DCHECK_EQ(endpoint->PopoverType(), PopoverValueType::kAuto); + const Element* hint_ancestor = nullptr; + if (document.PopoverHintShowing()) { + // If there is a popover=hint showing that is a descendant of something on + // the popover=auto stack, then the hint should be hidden before that + // ancestor is hidden, regardless of popover_independence. + hint_ancestor = + FindTopmostPopoverAncestor(*document.PopoverHintShowing()); + if (!hint_ancestor && + popover_independence == HidePopoverIndependence::kHideUnrelated) { + document.PopoverHintShowing()->HidePopoverInternal( + focus_behavior, transition_behavior, exception_state); + } + } + // Then hide everything in the popover=auto stack until the last_to_hide + // popover is closed, or the stack is empty. + const HTMLElement* last_to_hide = nullptr; + bool found_endpoint = false; + for (auto popover : document.PopoverStack()) { + if (popover == endpoint) { + found_endpoint = true; + } else if (found_endpoint) { + last_to_hide = popover; + break; + } + } + if (!found_endpoint) { + return close_all_open_popovers(); + } + if (!last_to_hide && document.PopoverHintShowing() && + hint_ancestor == endpoint) { + DCHECK(RuntimeEnabledFeatures::HTMLPopoverHintEnabled()); + // endpoint is the top of the popover stack, and there's a nested hint. + document.PopoverHintShowing()->HidePopoverInternal( + focus_behavior, transition_behavior, exception_state); + } + while (last_to_hide && last_to_hide->popoverOpen() && + !document.PopoverStack().empty()) { + // We never throw exceptions from HideAllPopoversUntil, since it is always + // used to close other popovers that are already showing. + if (document.PopoverStack().back() == hint_ancestor) { + DCHECK(RuntimeEnabledFeatures::HTMLPopoverHintEnabled()); + document.PopoverHintShowing()->HidePopoverInternal( + focus_behavior, transition_behavior, exception_state); + } + document.PopoverStack().back()->HidePopoverInternal( + focus_behavior, transition_behavior, exception_state); + } } } @@ -1568,15 +1669,16 @@ } auto& document = GetDocument(); - if (PopoverType() == PopoverValueType::kAuto) { + if (PopoverType() == PopoverValueType::kAuto || + PopoverType() == PopoverValueType::kHint) { // Hide any popovers above us in the stack. - HideAllPopoversUntil(this, document, focus_behavior, transition_behavior); - + HideAllPopoversUntil(this, document, focus_behavior, transition_behavior, + HidePopoverIndependence::kLeaveUnrelated); // The 'beforetoggle' event handlers could have changed this popover, e.g. // by changing its type, removing it from the document, or calling // hidePopover(). auto& stack = document.PopoverStack(); - if (!stack.Contains(this)) { + if (!stack.Contains(this) && this != document.PopoverHintShowing()) { if (exception_state) { exception_state->ThrowDOMException( DOMExceptionCode::kInvalidStateError, @@ -1587,9 +1689,15 @@ } // Then remove this popover from the stack. - DCHECK(!stack.empty()); - DCHECK_EQ(stack.back(), this); - stack.pop_back(); + if (PopoverType() == PopoverValueType::kAuto) { + DCHECK(!stack.empty()); + DCHECK_EQ(stack.back(), this); + stack.pop_back(); + } else { + DCHECK(RuntimeEnabledFeatures::HTMLPopoverHintEnabled()); + DCHECK_EQ(document.TopmostPopoverOrHint(), this); + document.SetPopoverHintShowing(nullptr); + } } GetPopoverData()->setInvoker(nullptr); @@ -1684,7 +1792,7 @@ // If the popover does not use autofocus, then the focus should remain on the // currently active element. - // https://open-ui.org/components/popup.research.explainer#focus-management + // https://open-ui.org/components/popover.research.explainer#focus-management if (!control) return; @@ -1775,10 +1883,12 @@ // from the (possibly cyclic) graph of connections. For example, if two popovers // have anchors pointing to each other, the only valid relationship is that the // first one to open is the "parent" and the second is the "child". Only -// popover=auto popovers are considered. +// popover=auto popovers can *be* ancestors, and only popover=auto/hint popovers +// can *have* ancestors. const HTMLElement* HTMLElement::FindTopmostPopoverAncestor( HTMLElement& new_popover) { DCHECK(new_popover.HasPopoverAttribute()); + DCHECK_NE(new_popover.PopoverType(), PopoverValueType::kManual); auto& document = new_popover.GetDocument(); DCHECK(RuntimeEnabledFeatures::HTMLPopoverAttributeEnabled( document.GetExecutionContext())); @@ -1789,6 +1899,9 @@ for (auto popover : document.PopoverStack()) { popover_positions.Set(popover, indx++); } + if (auto* popover_hint = document.PopoverHintShowing()) { + popover_positions.Set(popover_hint, indx++); + } popover_positions.Set(&new_popover, indx++); const HTMLElement* topmost_popover_ancestor = nullptr; @@ -1797,8 +1910,10 @@ if (!candidate) return; auto* candidate_ancestor = NearestInclusiveOpenPopover(candidate); - if (!candidate_ancestor) + if (!candidate_ancestor || + candidate_ancestor->PopoverType() != PopoverValueType::kAuto) { return; + } int candidate_position = popover_positions.at(candidate_ancestor); if (!topmost_popover_ancestor || popover_positions.at(topmost_popover_ancestor) < candidate_position) { @@ -1837,6 +1952,9 @@ auto* clicked_popover = NearestInclusiveOpenPopover(&node); auto* invoker_popover = NearestInclusiveTargetPopoverForInvoker(&node); auto get_stack_position = [&document](const HTMLElement* popover) { + if (popover && popover == document.PopoverHintShowing()) { + return document.PopoverStack().size() + 1; + } auto pos = document.PopoverStack().Find(popover); return pos == kNotFound ? 0 : (pos + 1); }; @@ -1852,10 +1970,12 @@ DCHECK(event.isTrusted()); auto& document = target_node.GetDocument(); if (!RuntimeEnabledFeatures::HTMLPopoverAttributeEnabled( - document.GetExecutionContext())) + document.GetExecutionContext())) { return; - if (!document.TopmostPopover()) + } + if (!document.TopmostPopoverOrHint()) { return; + } const AtomicString& event_type = event.type(); if (IsA<PointerEvent>(event)) { @@ -1885,7 +2005,8 @@ if (same_target) { HideAllPopoversUntil( ancestor_popover, document, HidePopoverFocusBehavior::kNone, - HidePopoverTransitionBehavior::kFireEventsAndWaitForTransitions); + HidePopoverTransitionBehavior::kFireEventsAndWaitForTransitions, + HidePopoverIndependence::kHideUnrelated); } } } else if (event_type == event_type_names::kKeydown) { @@ -1893,8 +2014,8 @@ if (key_event && key_event->key() == "Escape") { DCHECK(!event.GetEventPath().IsEmpty()); DCHECK_EQ(Event::PhaseType::kNone, event.eventPhase()); - // Escape key just pops the topmost popover off the stack. - document.TopmostPopover()->HidePopoverInternal( + // Escape key just pops the topmost popover=auto/hint off the stack. + document.TopmostPopoverOrHint()->HidePopoverInternal( HidePopoverFocusBehavior::kFocusPreviousElement, HidePopoverTransitionBehavior::kFireEventsAndWaitForTransitions, /*exception_state=*/nullptr); @@ -1984,7 +2105,8 @@ GetDocument().AddConsoleMessage(console_message); HTMLElement::HideAllPopoversUntil( nullptr, GetDocument(), HidePopoverFocusBehavior::kNone, - HidePopoverTransitionBehavior::kNoEventsNoWaiting); + HidePopoverTransitionBehavior::kNoEventsNoWaiting, + HidePopoverIndependence::kHideUnrelated); return; } }
diff --git a/third_party/blink/renderer/core/html/html_element.h b/third_party/blink/renderer/core/html/html_element.h index b0569437..3865660f 100644 --- a/third_party/blink/renderer/core/html/html_element.h +++ b/third_party/blink/renderer/core/html/html_element.h
@@ -32,6 +32,7 @@ #include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_set.h" #include "third_party/blink/renderer/platform/text/text_direction.h" #include "third_party/blink/renderer/platform/wtf/casting.h" +#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h" namespace blink { @@ -62,9 +63,11 @@ enum class PopoverValueType { kNone, kAuto, + kHint, kManual, }; constexpr const char* kPopoverTypeValueAuto = "auto"; +constexpr const char* kPopoverTypeValueHint = "hint"; constexpr const char* kPopoverTypeValueManual = "manual"; enum class PopoverTriggerAction { @@ -84,6 +87,11 @@ kNoEventsNoWaiting, }; +enum class HidePopoverIndependence { + kLeaveUnrelated, + kHideUnrelated, +}; + class CORE_EXPORT HTMLElement : public Element { DEFINE_WRAPPERTYPEINFO(); @@ -211,6 +219,9 @@ // Popover API related functions. void UpdatePopoverAttribute(String); bool HasPopoverAttribute() const; + // The IDL reflections: + AtomicString popover() const; + void setPopover(const AtomicString& value); PopoverValueType PopoverType() const; bool popoverOpen() const; bool IsPopoverReady(PopoverTriggerAction action, @@ -244,7 +255,8 @@ static void HideAllPopoversUntil(const HTMLElement*, Document&, HidePopoverFocusBehavior, - HidePopoverTransitionBehavior); + HidePopoverTransitionBehavior, + HidePopoverIndependence); // This function checks that the ancestor relationships are still valid for // the entire popover stack. These can change in various ways, such as a // triggering element changing its `disabled` attribute. If any relationships
diff --git a/third_party/blink/renderer/core/html/html_element.idl b/third_party/blink/renderer/core/html/html_element.idl index 24336eb..92a66a3 100644 --- a/third_party/blink/renderer/core/html/html_element.idl +++ b/third_party/blink/renderer/core/html/html_element.idl
@@ -69,7 +69,8 @@ [MeasureAs=ElementTogglePopover,RuntimeEnabled=HTMLPopoverAttribute,RaisesException] void togglePopover(optional boolean force); [MeasureAs=ElementShowPopover,RuntimeEnabled=HTMLPopoverAttribute,RaisesException] void showPopover(); [MeasureAs=ElementHidePopover,RuntimeEnabled=HTMLPopoverAttribute,RaisesException] void hidePopover(); - [CEReactions,RuntimeEnabled=HTMLPopoverAttribute,Reflect,ReflectOnly=("auto","manual"),ReflectEmpty="auto",ReflectInvalid="manual"] attribute DOMString? popover; +// [CEReactions,RuntimeEnabled=HTMLPopoverAttribute,Reflect,ReflectOnly=("auto","hint","manual"),ReflectEmpty="auto",ReflectInvalid="manual"] attribute DOMString? popover; + [CEReactions,RuntimeEnabled=HTMLPopoverAttribute] attribute DOMString? popover; // Used by both Anchor Positioning and Popover [CEReactions,RuntimeEnabled=CSSAnchorPositioning] attribute Element? anchorElement;
diff --git a/third_party/blink/renderer/core/html/html_frame_element_base.cc b/third_party/blink/renderer/core/html/html_frame_element_base.cc index d8df68e..ca9855c 100644 --- a/third_party/blink/renderer/core/html/html_frame_element_base.cc +++ b/third_party/blink/renderer/core/html/html_frame_element_base.cc
@@ -93,7 +93,6 @@ KURL url = GetDocument().CompleteURL(url_); - WillPerformContainerInitiatedNavigation(url); // There is no (easy) way to tell if |url_| is relative at this point. That // is determined in the KURL constructor. If we fail to create an absolute // URL at this point, *and* the base URL is a data URL, assume |url_| was
diff --git a/third_party/blink/renderer/core/html/html_frame_owner_element.cc b/third_party/blink/renderer/core/html/html_frame_owner_element.cc index 0edf7c8..3f5cdaf 100644 --- a/third_party/blink/renderer/core/html/html_frame_owner_element.cc +++ b/third_party/blink/renderer/core/html/html_frame_owner_element.cc
@@ -482,7 +482,7 @@ void HTMLFrameOwnerElement::AddResourceTiming( mojom::blink::ResourceTimingInfoPtr info) { // Resource timing info should only be reported if the subframe is attached. - DCHECK(ContentFrame() && ContentFrame()->IsLocalFrame()); + DCHECK(ContentFrame()); // Make sure we don't double-report, e.g. in the case of restored iframes. if (!HasPendingFallbackTimingInfo()) { @@ -512,17 +512,6 @@ fallback_timing_info_.reset(); } -void HTMLFrameOwnerElement::WillPerformContainerInitiatedNavigation( - const KURL& url) { - if (!url.ProtocolIsInHTTPFamily() && - !url.ProtocolIs(url::kUuidInPackageScheme)) { - return; - } - - fallback_timing_info_ = CreateResourceTimingInfo(base::TimeTicks::Now(), url, - /*response=*/nullptr); -} - // This will report fallback timing only if the "real" resource timing had not // been previously reported: e.g. a cross-origin iframe without TAO. void HTMLFrameOwnerElement::ReportFallbackResourceTimingIfNeeded() { @@ -704,6 +693,15 @@ bool replace_current_item) { TRACE_EVENT0("navigation", "HTMLFrameOwnerElement::LoadOrRedirectSubframe"); + // If the subframe navigation is aborted or TAO fails, we report a "fallback" + // entry that starts at navigation and ends at load/error event. + if (url.ProtocolIsInHTTPFamily() || + url.ProtocolIs(url::kUuidInPackageScheme)) { + fallback_timing_info_ = + CreateResourceTimingInfo(base::TimeTicks::Now(), url, + /*response=*/nullptr); + } + // Update the |should_lazy_load_children_| value according to the "loading" // attribute immediately, so that it still gets respected even if the "src" // attribute gets parsed in ParseAttribute() before the "loading" attribute @@ -730,6 +728,7 @@ if (ContentFrame()) { FrameLoadRequest frame_load_request(GetDocument().domWindow(), request); + frame_load_request.SetIsContainerInitiated(true); frame_load_request.SetClientRedirectReason( ClientNavigationReason::kFrameNavigation); WebFrameLoadType frame_load_type = WebFrameLoadType::kStandard; @@ -790,6 +789,7 @@ } FrameLoadRequest frame_load_request(GetDocument().domWindow(), request); + frame_load_request.SetIsContainerInitiated(true); child_frame->Loader().StartNavigation(frame_load_request, child_load_type); return true;
diff --git a/third_party/blink/renderer/core/html/html_frame_owner_element.h b/third_party/blink/renderer/core/html/html_frame_owner_element.h index ca27f17..55d4d6f5 100644 --- a/third_party/blink/renderer/core/html/html_frame_owner_element.h +++ b/third_party/blink/renderer/core/html/html_frame_owner_element.h
@@ -124,8 +124,6 @@ void DidReportResourceTiming(); bool HasPendingFallbackTimingInfo() const; - void WillPerformContainerInitiatedNavigation(const KURL&); - // For unit tests, manually trigger the UpdateContainerPolicy method. void UpdateContainerPolicyForTests() { UpdateContainerPolicy(); } @@ -191,6 +189,7 @@ // based on the frame attributes. virtual network::mojom::blink::TrustTokenParamsPtr ConstructTrustTokenParams() const; + void ReportFallbackResourceTimingIfNeeded(); protected: bool is_swapping_frames() const { return is_swapping_frames_; } @@ -237,7 +236,6 @@ bool is_loading_attr_lazy, AutomaticLazyLoadReason auto_lazy_load_reason); - void ReportFallbackResourceTimingIfNeeded(); // Check if the frame should be lazy-loaded and apply when conditions are // passed. Return true when lazy-load is applied. bool LazyLoadIfPossible(const KURL&,
diff --git a/third_party/blink/renderer/core/html/html_plugin_element.cc b/third_party/blink/renderer/core/html/html_plugin_element.cc index 9072e8b..111fdc2 100644 --- a/third_party/blink/renderer/core/html/html_plugin_element.cc +++ b/third_party/blink/renderer/core/html/html_plugin_element.cc
@@ -631,8 +631,6 @@ DCHECK(OwnedEmbeddedContentView()); } - WillPerformContainerInitiatedNavigation(completed_url); - // If the plugin element already contains a subframe, // loadOrRedirectSubframe will re-use it. Otherwise, it will create a // new frame and set it as the LayoutEmbeddedContent's EmbeddedContentView, @@ -710,6 +708,7 @@ } void HTMLPlugInElement::DispatchErrorEvent() { + ReportFallbackResourceTimingIfNeeded(); if (IsA<PluginDocument>(GetDocument()) && GetDocument().LocalOwner()) { GetDocument().LocalOwner()->DispatchEvent( *Event::Create(event_type_names::kError));
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc b/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc index 4ce14da..4070147 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc
@@ -1332,6 +1332,17 @@ #endif } stitched_block_size += NGFragment(writing_direction, walker).BlockSize(); + + // Repeated content isn't stitched, so just stop when we have processed one + // fragment. + if (walker.BreakToken() && walker.BreakToken()->IsRepeated()) { +#if DCHECK_IS_ON() + // We haven't necessarily found |fragment|, but it doesn't matter in this + // case. Just silence the DHCECK below. + found_self = true; +#endif + break; + } } #if DCHECK_IS_ON() DCHECK(found_self);
diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc index 3f1f52b..4308beef 100644 --- a/third_party/blink/renderer/core/loader/document_loader.cc +++ b/third_party/blink/renderer/core/loader/document_loader.cc
@@ -289,7 +289,6 @@ CommitReason commit_reason; uint64_t main_resource_identifier; mojom::blink::ResourceTimingInfoPtr resource_timing_info_for_parent; - base::TimeTicks last_redirect_end_time; WebScopedVirtualTimePauser virtual_time_pauser; Member<PrefetchedSignedExchangeManager> prefetched_signed_exchange_manager; ukm::SourceId ukm_source_id; @@ -314,6 +313,7 @@ absl::optional<FencedFrame::RedactedFencedFrameProperties> fenced_frame_properties; bool has_storage_access; + mojom::blink::ParentResourceTimingAccess parent_resource_timing_access; }; // Asserts size of DocumentLoader, so that whenever a new attribute is added to @@ -513,7 +513,8 @@ reduced_accept_language_(params_->reduced_accept_language), navigation_delivery_type_(params_->navigation_delivery_type), view_transition_state_(std::move(params_->view_transition_state)), - has_storage_access_(params_->has_storage_access) { + has_storage_access_(params_->has_storage_access), + parent_resource_timing_access_(params_->parent_resource_timing_access) { DCHECK(frame_); DCHECK(params_); @@ -533,6 +534,8 @@ document_policy_ = CreateDocumentPolicy(); WebNavigationTimings& timings = params_->navigation_timings; + parent_resource_timing_access_ = timings.parent_resource_timing_access; + if (!timings.input_start.is_null()) document_load_timing_.SetInputStart(timings.input_start); if (timings.navigation_start.is_null()) { @@ -826,7 +829,7 @@ DCHECK(frame_->DomWindow()); SoftNavigationHeuristics* heuristics = SoftNavigationHeuristics::From(*frame_->DomWindow()); - heuristics->SetBackForwardNavigationURL(script_state, new_url); + heuristics->SetAsyncSoftNavigationURL(script_state, new_url); } } SinglePageAppNavigationType single_page_app_navigation_type = @@ -1099,6 +1102,7 @@ const absl::optional<WebURLError>& error) { TRACE_EVENT0("loading", "DocumentLoader::BodyLoadingFinished"); + DCHECK(frame_); if (!error) { GetFrameLoader().Progress().CompleteProgress(main_resource_identifier_); probe::DidFinishLoading( @@ -1246,10 +1250,6 @@ probe::ToCoreProbeSink(GetFrame()), main_resource_identifier_, this, url_after_redirect, http_method_, http_body_.get()); - if (ResourceLoadTiming* timing = redirect_response.GetResourceLoadTiming()) { - redirect_end_time_ = timing->ReceiveHeadersEnd(); - } - DCHECK(!GetTiming().FetchStart().is_null()); GetTiming().AddRedirect(url_before_redirect, url_after_redirect); } @@ -1884,11 +1884,7 @@ WarnIfSandboxIneffective(document->domWindow()); - if (view_transition_state_) { - ViewTransitionSupplement::CreateFromSnapshotForNavigation( - *document, std::move(*view_transition_state_)); - view_transition_state_.reset(); - } + StartViewTransitionIfNeeded(*document); } void DocumentLoader::WillCommitNavigation() { @@ -2344,40 +2340,30 @@ frame_->DomWindow()->SetPolicyContainer(std::move(policy_container_)); frame_->DomWindow()->SetContentSecurityPolicy(csp); + BlinkStorageKey storage_key(storage_key_); + // TODO(crbug.com/1199077): For some reason `storage_key_` is occasionally + // null. If that's the case this will create one based on the + // `security_origin`. + // TODO(crbug.com/1199077): Some tests (potentially other code?) rely on an + // opaque origin + nonce. Investigate whether this combination should be + // disallowed. + if (storage_key.GetSecurityOrigin()->IsOpaque() && !storage_key.GetNonce()) { + storage_key = BlinkStorageKey::CreateFirstParty(security_origin); + } + // Now that we have the final window and Agent, ensure the security origin has // the appropriate agent cluster id. This may derive a new security origin. security_origin = security_origin->GetOriginForAgentCluster( frame_->DomWindow()->GetAgent()->cluster_id()); - if (storage_key_.GetNonce()) { - // If the nonce isn't null, we can use the simpler form of the constructor. - frame_->DomWindow()->SetStorageKey(BlinkStorageKey::CreateWithNonce( - security_origin, *storage_key_.GetNonce())); - } else { - // TODO(crbug.com/1159586): Remove this when 3psp storage is on. It's here - // to preserve the information that is stripped due to the key being - // re-made. - const auto& storage_key_with_3psp = - storage_key_.CopyWithForceEnabledThirdPartyStoragePartitioning(); - BlinkSchemefulSite top_level_site = storage_key_with_3psp.GetTopLevelSite(); - // If `security_origin` is opaque or does not match `top_level_site` we - // must ensure `ancestor_chain_bit` is kCrossSite. - mojom::blink::AncestorChainBit ancestor_chain_bit = - storage_key_with_3psp.GetAncestorChainBit(); - if (security_origin->IsOpaque() || - BlinkSchemefulSite(security_origin) != top_level_site) { - ancestor_chain_bit = mojom::blink::AncestorChainBit::kCrossSite; - } - // TODO(https://crbug.com/888079): Just use the storage key sent by the - // browser once the browser will be able to compute the origin in all cases. - frame_->DomWindow()->SetStorageKey(BlinkStorageKey::Create( - security_origin, top_level_site, ancestor_chain_bit)); - } + // TODO(https://crbug.com/888079): Just use the storage key sent by the + // browser once the browser will be able to compute the origin in all cases. + frame_->DomWindow()->SetStorageKey(storage_key.WithOrigin(security_origin)); - if (storage_key_ == session_storage_key_ || - storage_key_.GetSecurityOrigin()->IsOpaque() || + if (storage_key == session_storage_key_ || + storage_key.GetSecurityOrigin()->IsOpaque() || session_storage_key_.GetSecurityOrigin()->IsOpaque()) { - // If the `storage_key_` and `session_storage_key_` match (or either are + // If the `storage_key` and `session_storage_key_` match (or either are // opaque), we should just use whatever storage key was built above as we // aren't preventing partition. frame_->DomWindow()->SetSessionStorageKey( @@ -2640,27 +2626,32 @@ if (response_.ShouldPopulateResourceTiming() || is_error_page_for_failed_navigation_) { - // We only report resource timing to the parent if: - // 1. We have a parent (owner) - // 2. Timing Allow Passed - otherwise we report fallback timing. - // 3. It's an external navigation (kWebNavigationTypeOther) - // TODO (crbug.com/1410705): Using navigation_type_ for this covers - // most cases but might still have very rare racy edge cases, such as - // extension or window.open with target cancelling an ongoing navigation - // and start a new navigation to the same URL. - if (frame_->Owner() && response_.TimingAllowPassed() && - navigation_type_ == WebNavigationType::kWebNavigationTypeOther) { - resource_timing_info_for_parent_ = CreateResourceTimingInfo( - GetTiming().NavigationStart(), original_url_, &response_); - if (!is_same_origin_initiator || - document_load_timing_.HasCrossOriginRedirect()) { - resource_timing_info_for_parent_->content_type = g_empty_string; - resource_timing_info_for_parent_->response_status = 0; + // We only report resource timing info to the parent if: + // 1. The navigation is container-initiated (e.g. iframe changed src) + // 2. TAO passed. + if (parent_resource_timing_access_ != + mojom::blink::ParentResourceTimingAccess::kDoNotReport && + response_.TimingAllowPassed()) { + ResourceResponse response_for_parent(response_); + if (parent_resource_timing_access_ == + mojom::blink::ParentResourceTimingAccess:: + kReportWithoutResponseDetails) { + response_for_parent.SetType(network::mojom::FetchResponseType::kOpaque); } + + DCHECK(frame_->Owner()); + DCHECK(GetRequestorOrigin()); + resource_timing_info_for_parent_ = CreateResourceTimingInfo( + GetTiming().NavigationStart(), original_url_, &response_for_parent); + resource_timing_info_for_parent_->last_redirect_end_time = - redirect_end_time_; + document_load_timing_.RedirectEnd(); } + // TimingAllowPassed only applies to resource + // timing reporting. Navigation timing is always same-origin with the + // document that holds to the timing entry, as navigation timing represents + // the timing of that document itself. response_.SetTimingAllowPassed(true); mojom::blink::ResourceTimingInfoPtr navigation_timing_info = CreateResourceTimingInfo(base::TimeTicks(), @@ -2668,8 +2659,9 @@ ? pre_redirect_url_for_failed_navigations_ : url_, &response_); - navigation_timing_info->last_redirect_end_time = redirect_end_time_; - DCHECK(frame_); + navigation_timing_info->last_redirect_end_time = + document_load_timing_.RedirectEnd(); + DCHECK(frame_->DomWindow()); DOMWindowPerformance::performance(*frame_->DomWindow()) ->CreateNavigationTimingInstance(std::move(navigation_timing_info)); @@ -3101,6 +3093,10 @@ } GetTiming().SetActivationStart(params.activation_start); + + DCHECK(!view_transition_state_); + view_transition_state_ = std::move(params.view_transition_state); + StartViewTransitionIfNeeded(*frame_->GetDocument()); } HashMap<KURL, EarlyHintsPreloadEntry> @@ -3272,6 +3268,14 @@ }; } +void DocumentLoader::StartViewTransitionIfNeeded(Document& document) { + if (view_transition_state_) { + ViewTransitionSupplement::CreateFromSnapshotForNavigation( + document, std::move(*view_transition_state_)); + view_transition_state_.reset(); + } +} + // static void DocumentLoader::DisableCodeCacheForTesting() { GetDisableCodeCacheForTesting() = true;
diff --git a/third_party/blink/renderer/core/loader/document_loader.h b/third_party/blink/renderer/core/loader/document_loader.h index dc759a0..11e3bce 100644 --- a/third_party/blink/renderer/core/loader/document_loader.h +++ b/third_party/blink/renderer/core/loader/document_loader.h
@@ -49,6 +49,8 @@ #include "third_party/blink/public/mojom/loader/content_security_notifier.mojom-blink.h" #include "third_party/blink/public/mojom/loader/mhtml_load_result.mojom-blink-forward.h" #include "third_party/blink/public/mojom/loader/same_document_navigation_type.mojom-blink.h" +#include "third_party/blink/public/mojom/navigation/navigation_params.mojom-blink-forward.h" +#include "third_party/blink/public/mojom/navigation/navigation_params.mojom-shared.h" #include "third_party/blink/public/mojom/page/page.mojom-blink-forward.h" #include "third_party/blink/public/mojom/page_state/page_state.mojom-blink.h" #include "third_party/blink/public/mojom/service_worker/controller_service_worker_mode.mojom-blink.h" @@ -601,6 +603,11 @@ ContentSecurityPolicy* CreateCSP(); bool IsSameOriginInitiator() const; + + // This initiates a view transition if the `view_transition_state_` has been + // specified. + void StartViewTransitionIfNeeded(Document& document); + // Params are saved in constructor and are cleared after StartLoading(). // TODO(dgozman): remove once StartLoading is merged with constructor. std::unique_ptr<WebNavigationParams> params_; @@ -753,7 +760,6 @@ CommitReason commit_reason_ = CommitReason::kRegular; uint64_t main_resource_identifier_ = 0; mojom::blink::ResourceTimingInfoPtr resource_timing_info_for_parent_; - base::TimeTicks redirect_end_time_; WebScopedVirtualTimePauser virtual_time_pauser_; Member<PrefetchedSignedExchangeManager> prefetched_signed_exchange_manager_; ukm::SourceId ukm_source_id_; @@ -817,6 +823,10 @@ // Indicates whether the document should be loaded with its has_storage_access // bit set. const bool has_storage_access_; + + // Only container-initiated navigations (e.g. iframe change src) report + // their resource timing to the parent. + mojom::blink::ParentResourceTimingAccess parent_resource_timing_access_; }; DECLARE_WEAK_IDENTIFIER_MAP(DocumentLoader);
diff --git a/third_party/blink/renderer/core/loader/empty_clients.cc b/third_party/blink/renderer/core/loader/empty_clients.cc index 1547749..3047062 100644 --- a/third_party/blink/renderer/core/loader/empty_clients.cc +++ b/third_party/blink/renderer/core/loader/empty_clients.cc
@@ -121,7 +121,8 @@ const absl::optional<Impression>&, const LocalFrameToken* initiator_frame_token, std::unique_ptr<SourceLocation>, - mojo::PendingRemote<mojom::blink::PolicyContainerHostKeepAliveHandle>) {} + mojo::PendingRemote<mojom::blink::PolicyContainerHostKeepAliveHandle>, + bool is_container_initiated) {} void EmptyLocalFrameClient::DispatchWillSendSubmitEvent(HTMLFormElement*) {}
diff --git a/third_party/blink/renderer/core/loader/empty_clients.h b/third_party/blink/renderer/core/loader/empty_clients.h index 84e9886..9e34e80 100644 --- a/third_party/blink/renderer/core/loader/empty_clients.h +++ b/third_party/blink/renderer/core/loader/empty_clients.h
@@ -308,8 +308,8 @@ const absl::optional<Impression>&, const LocalFrameToken* initiator_frame_token, std::unique_ptr<SourceLocation>, - mojo::PendingRemote<mojom::blink::PolicyContainerHostKeepAliveHandle>) - override; + mojo::PendingRemote<mojom::blink::PolicyContainerHostKeepAliveHandle>, + bool is_container_initiated) override; void DispatchWillSendSubmitEvent(HTMLFormElement*) override;
diff --git a/third_party/blink/renderer/core/loader/frame_load_request.h b/third_party/blink/renderer/core/loader/frame_load_request.h index 5282d87..8d28e63 100644 --- a/third_party/blink/renderer/core/loader/frame_load_request.h +++ b/third_party/blink/renderer/core/loader/frame_load_request.h
@@ -84,6 +84,10 @@ return client_navigation_reason_; } + void SetIsContainerInitiated(bool value) { is_container_initiated_ = value; } + + bool IsContainerInitiated() const { return is_container_initiated_; } + NavigationPolicy GetNavigationPolicy() const { return navigation_policy_; } void SetNavigationPolicy(NavigationPolicy navigation_policy) { navigation_policy_ = navigation_policy; @@ -240,6 +244,10 @@ mojom::blink::ForceHistoryPush force_history_push_ = mojom::blink::ForceHistoryPush::kNo; + + // Only container-initiated navigations (e.g. iframe change src) report a + // resource timing entry to the parent. + bool is_container_initiated_ = false; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/loader/frame_loader.cc b/third_party/blink/renderer/core/loader/frame_loader.cc index 8bad0fba..939b5977b 100644 --- a/third_party/blink/renderer/core/loader/frame_loader.cc +++ b/third_party/blink/renderer/core/loader/frame_loader.cc
@@ -852,7 +852,8 @@ request.GetInputStartTime(), request.HrefTranslate().GetString(), request.Impression(), request.GetInitiatorFrameToken(), request.TakeSourceLocation(), - request.TakeInitiatorPolicyContainerKeepAliveHandle()); + request.TakeInitiatorPolicyContainerKeepAliveHandle(), + request.IsContainerInitiated()); } static void FillStaticResponseIfNeeded(WebNavigationParams* params,
diff --git a/third_party/blink/renderer/core/navigation_api/navigate_event.cc b/third_party/blink/renderer/core/navigation_api/navigate_event.cc index 5c9824b..6fb51d1 100644 --- a/third_party/blink/renderer/core/navigation_api/navigate_event.cc +++ b/third_party/blink/renderer/core/navigation_api/navigate_event.cc
@@ -19,6 +19,7 @@ #include "third_party/blink/renderer/core/inspector/console_message.h" #include "third_party/blink/renderer/core/loader/document_loader.h" #include "third_party/blink/renderer/core/navigation_api/navigation_destination.h" +#include "third_party/blink/renderer/core/timing/soft_navigation_heuristics.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" namespace blink { @@ -150,6 +151,19 @@ state_object, dispatch_params_->frame_load_type, dispatch_params_->is_browser_initiated, dispatch_params_->is_synchronously_committed_same_document); + + // This is considered a soft navigation URL change at this point, when the + // user visible URL change happens. Skip the descendant check because the URL + // change doesn't happen in a JS task. + auto* soft_navigation_heuristics = + DomWindow() ? SoftNavigationHeuristics::From(*DomWindow()) : nullptr; + if (soft_navigation_heuristics && user_initiated_ && !download_request_) { + auto* script_state = ToScriptStateForMainWorld(DomWindow()->GetFrame()); + ScriptState::Scope scope(script_state); + soft_navigation_heuristics->SawURLChange(script_state, + dispatch_params_->url, + /*skip_descendant_check=*/true); + } } void NavigateEvent::FinalizeNavigationActionPromisesList() {
diff --git a/third_party/blink/renderer/core/navigation_api/navigation_api.cc b/third_party/blink/renderer/core/navigation_api/navigation_api.cc index a63be49..5eb87252 100644 --- a/third_party/blink/renderer/core/navigation_api/navigation_api.cc +++ b/third_party/blink/renderer/core/navigation_api/navigation_api.cc
@@ -858,18 +858,6 @@ transition_ = MakeGarbageCollected<NavigationTransition>( script_state, navigation_type, currentEntry()); navigate_event->DoCommit(); - - // This is considered a soft navigation URL change at this point, when the - // user visible URL change happens, and before the interception handler - // runs. We're skipping the descendant check because the the URL change - // doesn't happen in a JS task, and we know this URL change is related to - // the user initiated click event from the fact that - // `soft_navigation_scope` is not nullptr. - if (soft_navigation_scope) { - soft_navigation_heuristics->SawURLChange(script_state, - /*url=*/params->url, - /*skip_descendant_check=*/true); - } } if (navigate_event->HasNavigationActions() ||
diff --git a/third_party/blink/renderer/core/paint/image_painter.cc b/third_party/blink/renderer/core/paint/image_painter.cc index 9ca07ff..3efa2233 100644 --- a/third_party/blink/renderer/core/paint/image_painter.cc +++ b/third_party/blink/renderer/core/paint/image_painter.cc
@@ -215,10 +215,11 @@ paint_offset); context.SetStrokeStyle(kSolidStroke); context.SetStrokeColor(Color::kLightGray); - context.SetFillColor(Color::kTransparent); - context.DrawRect(ToPixelSnappedRect(content_rect), - PaintAutoDarkMode(layout_image_.StyleRef(), - DarkModeFilter::ElementRole::kBorder)); + gfx::RectF outline_rect(ToPixelSnappedRect(content_rect)); + outline_rect.Inset(0.5f); + context.StrokeRect(outline_rect, 1, + PaintAutoDarkMode(layout_image_.StyleRef(), + DarkModeFilter::ElementRole::kBorder)); return; }
diff --git a/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc b/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc index 9de1b30..15516e1 100644 --- a/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc +++ b/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc
@@ -476,7 +476,11 @@ // fragment of an OOF fragment is always simply the parent. if (!context.current_container.IsInFragmentationContext() || (fragment && fragment->IsMonolithic())) { - context.current_container.fragment = fragment; + // Anonymous blocks are not allowed to be containing blocks, so we should + // skip over any such elements. + if (!fragment || !fragment->IsAnonymousBlock()) { + context.current_container.fragment = fragment; + } } if (!object.CanContainAbsolutePositionObjects())
diff --git a/third_party/blink/renderer/core/paint/scrollable_area_painter.cc b/third_party/blink/renderer/core/paint/scrollable_area_painter.cc index 0c5642f..eb3ad77c 100644 --- a/third_party/blink/renderer/core/paint/scrollable_area_painter.cc +++ b/third_party/blink/renderer/core/paint/scrollable_area_painter.cc
@@ -63,11 +63,13 @@ larger_corner.set_size( gfx::Size(larger_corner.width() + 1, larger_corner.height() + 1)); context.SetStrokeColor(Color(217, 217, 217)); - context.SetStrokeThickness(1.0f); - context.SetFillColor(Color::kTransparent); - AutoDarkMode auto_dark_mode(PaintAutoDarkMode( - box->StyleRef(), DarkModeFilter::ElementRole::kBackground)); - context.DrawRect(larger_corner, auto_dark_mode); + context.SetStrokeStyle(kSolidStroke); + gfx::RectF corner_outline(larger_corner); + corner_outline.Inset(0.5f); + context.StrokeRect( + corner_outline, 1, + PaintAutoDarkMode(box->StyleRef(), + DarkModeFilter::ElementRole::kBackground)); } }
diff --git a/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.cc b/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.cc index de05bfe..72dedaa7 100644 --- a/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.cc +++ b/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.cc
@@ -117,20 +117,6 @@ Referrer referrer = SecurityPolicy::GenerateReferrer(referrer_policy, url, outgoing_referrer); - // TODO(mcnee): Speculation rules initially shipped with a bug where a policy - // of "no-referrer" would be assumed and the referrer policy restriction was - // not enforced. We emulate that behaviour here as sites did not have a means - // of specifying a suitable policy. SpeculationRulesReferrerPolicyKey shipped - // in M111. This workaround should be removed when the flag is removed. - // See https://crbug.com/1398772. - if (!RuntimeEnabledFeatures::SpeculationRulesReferrerPolicyKeyEnabled( - execution_context) && - !AcceptableReferrerPolicy(referrer, is_initially_same_site)) { - referrer = SecurityPolicy::GenerateReferrer( - network::mojom::ReferrerPolicy::kNever, url, outgoing_referrer); - DCHECK(AcceptableReferrerPolicy(referrer, is_initially_same_site)); - } - if (!AcceptableReferrerPolicy(referrer, is_initially_same_site)) { auto* console_message = MakeGarbageCollected<ConsoleMessage>( mojom::blink::ConsoleMessageSource::kOther,
diff --git a/third_party/blink/renderer/core/speculation_rules/speculation_rule_set.cc b/third_party/blink/renderer/core/speculation_rules/speculation_rule_set.cc index 97559fd..e6fc4411 100644 --- a/third_party/blink/renderer/core/speculation_rules/speculation_rule_set.cc +++ b/third_party/blink/renderer/core/speculation_rules/speculation_rule_set.cc
@@ -66,16 +66,14 @@ String* out_error) { // https://wicg.github.io/nav-speculation/speculation-rules.html#parse-a-speculation-rule - // If input has any key other than "source", "urls", "requires", "target_hint" - // and "relative_to", then return null. - const char* const kKnownKeys[] = {"source", "urls", "requires", - "target_hint", "where", "relative_to"}; + // If input has any key other than "source", "urls", "where", "requires", + // "target_hint", "referrer_policy", "relative_to", and "eagerness", then + // return null. + const char* const kKnownKeys[] = { + "source", "urls", "where", "requires", "target_hint", + "referrer_policy", "relative_to"}; const auto kConditionalKnownKeys = [context]() { Vector<const char*, 4> conditional_known_keys; - if (RuntimeEnabledFeatures::SpeculationRulesReferrerPolicyKeyEnabled( - context)) { - conditional_known_keys.push_back("referrer_policy"); - } if (RuntimeEnabledFeatures::SpeculationRulesEagernessEnabled(context)) { conditional_known_keys.push_back("eagerness"); } @@ -268,13 +266,12 @@ } } + // Let referrerPolicy be the empty string. absl::optional<network::mojom::ReferrerPolicy> referrer_policy; + // If input["referrer_policy"] exists: JSONValue* referrer_policy_value = input->Get("referrer_policy"); if (referrer_policy_value) { - // Feature gated due to known keys check above. - DCHECK(RuntimeEnabledFeatures::SpeculationRulesReferrerPolicyKeyEnabled( - context)); - + // If input["referrer_policy"] is not a referrer policy, then return null. String referrer_policy_str; if (!referrer_policy_value->AsString(&referrer_policy_str)) { SetParseErrorMessage(out_error, "A referrer policy must be a string."); @@ -293,6 +290,7 @@ return nullptr; } DCHECK_NE(referrer_policy_out, network::mojom::ReferrerPolicy::kDefault); + // Set referrerPolicy to input["referrer_policy"]. referrer_policy = referrer_policy_out; } }
diff --git a/third_party/blink/renderer/core/style/computed_style.cc b/third_party/blink/renderer/core/style/computed_style.cc index 0338383..41fd48d 100644 --- a/third_party/blink/renderer/core/style/computed_style.cc +++ b/third_party/blink/renderer/core/style/computed_style.cc
@@ -205,10 +205,6 @@ return *cached_data_->position_fallback_styles_; } -scoped_refptr<ComputedStyle> ComputedStyle::Clone(const ComputedStyle& other) { - return base::AdoptRef(new ComputedStyle(PassKey(), other)); -} - ALWAYS_INLINE ComputedStyle::ComputedStyle() : ComputedStyleBase(), RefCounted<ComputedStyle>() {} @@ -2472,6 +2468,16 @@ return element.IsInTopLayer() && TopLayer() == ETopLayer::kBrowser; } +ComputedStyleBuilder::ComputedStyleBuilder(const ComputedStyle& style) { + style_ = base::AdoptRef(new ComputedStyle(style)); + SetStyleBase(*style_); +} + +scoped_refptr<const ComputedStyle> ComputedStyleBuilder::CloneStyle() const { + DCHECK(style_); + return base::AdoptRef(new ComputedStyle(*style_)); +} + void ComputedStyleBuilder::PropagateIndependentInheritedProperties( const ComputedStyle& parent_style) { ComputedStyleBuilderBase::PropagateIndependentInheritedProperties(
diff --git a/third_party/blink/renderer/core/style/computed_style.h b/third_party/blink/renderer/core/style/computed_style.h index 73f0950e..6b0086b 100644 --- a/third_party/blink/renderer/core/style/computed_style.h +++ b/third_party/blink/renderer/core/style/computed_style.h
@@ -340,9 +340,6 @@ // into new instances. CORE_EXPORT static scoped_refptr<ComputedStyle> CreateInitialStyleSingleton(); - // Shallow copy into a new instance sharing DataPtrs. - CORE_EXPORT static scoped_refptr<ComputedStyle> Clone(const ComputedStyle&); - static const ComputedStyle* NullifyEnsured(const ComputedStyle* style) { if (!style) { return nullptr; @@ -2779,10 +2776,7 @@ // Access to UserModify(). friend class MatchedPropertiesCache; - explicit ComputedStyleBuilder(const ComputedStyle& style) { - style_ = ComputedStyle::Clone(style); - SetStyleBase(*style_); - } + CORE_EXPORT explicit ComputedStyleBuilder(const ComputedStyle& style); ComputedStyleBuilder(const ComputedStyleBuilder& builder) = delete; ComputedStyleBuilder(ComputedStyleBuilder&&) = default; ComputedStyleBuilder& operator=(const ComputedStyleBuilder&) = delete; @@ -2791,10 +2785,7 @@ scoped_refptr<const ComputedStyle> TakeStyle() { return std::move(style_); } // NOTE: Prefer `TakeStyle()` if possible. - scoped_refptr<const ComputedStyle> CloneStyle() const { - DCHECK(style_); - return ComputedStyle::Clone(*style_); - } + CORE_EXPORT scoped_refptr<const ComputedStyle> CloneStyle() const; CORE_EXPORT void InheritFrom( const ComputedStyle& inherit_parent,
diff --git a/third_party/blink/renderer/core/style/computed_style_test.cc b/third_party/blink/renderer/core/style/computed_style_test.cc index d8c35ea9..ea086d55 100644 --- a/third_party/blink/renderer/core/style/computed_style_test.cc +++ b/third_party/blink/renderer/core/style/computed_style_test.cc
@@ -51,8 +51,8 @@ initial_style_ = ComputedStyle::CreateInitialStyleSingleton(); } - scoped_refptr<ComputedStyle> CreateComputedStyle() { - return ComputedStyle::Clone(*initial_style_); + scoped_refptr<const ComputedStyle> InitialComputedStyle() { + return initial_style_; } ComputedStyleBuilder CreateComputedStyleBuilder() { @@ -118,7 +118,7 @@ } TEST_F(ComputedStyleTest, LayoutContainmentStackingContext) { - scoped_refptr<const ComputedStyle> style = CreateComputedStyle(); + scoped_refptr<const ComputedStyle> style = InitialComputedStyle(); EXPECT_FALSE(style->IsStackingContextWithoutContainment()); ComputedStyleBuilder builder(*style); @@ -210,7 +210,7 @@ TEST_F(ComputedStyleTest, UpdatePropertySpecificDifferencesRespectsTransformAnimation) { - scoped_refptr<const ComputedStyle> style = CreateComputedStyle(); + scoped_refptr<const ComputedStyle> style = InitialComputedStyle(); ComputedStyleBuilder builder(*style); builder.SetHasCurrentTransformAnimation(true); scoped_refptr<const ComputedStyle> other = builder.TakeStyle(); @@ -244,7 +244,7 @@ TEST_F(ComputedStyleTest, UpdatePropertySpecificDifferencesRespectsScaleAnimation) { - scoped_refptr<const ComputedStyle> style = CreateComputedStyle(); + scoped_refptr<const ComputedStyle> style = InitialComputedStyle(); ComputedStyleBuilder builder(*style); builder.SetHasCurrentScaleAnimation(true); scoped_refptr<const ComputedStyle> other = builder.TakeStyle(); @@ -256,7 +256,7 @@ TEST_F(ComputedStyleTest, UpdatePropertySpecificDifferencesRespectsRotateAnimation) { - scoped_refptr<const ComputedStyle> style = CreateComputedStyle(); + scoped_refptr<const ComputedStyle> style = InitialComputedStyle(); ComputedStyleBuilder builder(*style); builder.SetHasCurrentRotateAnimation(true); scoped_refptr<const ComputedStyle> other = builder.TakeStyle(); @@ -268,7 +268,7 @@ TEST_F(ComputedStyleTest, UpdatePropertySpecificDifferencesRespectsTranslateAnimation) { - scoped_refptr<const ComputedStyle> style = CreateComputedStyle(); + scoped_refptr<const ComputedStyle> style = InitialComputedStyle(); ComputedStyleBuilder builder(*style); builder.SetHasCurrentTranslateAnimation(true); scoped_refptr<const ComputedStyle> other = builder.TakeStyle(); @@ -280,7 +280,7 @@ TEST_F(ComputedStyleTest, UpdatePropertySpecificDifferencesCompositingReasonsOpacity) { - scoped_refptr<const ComputedStyle> style = CreateComputedStyle(); + scoped_refptr<const ComputedStyle> style = InitialComputedStyle(); ComputedStyleBuilder builder(*style); builder.SetHasCurrentOpacityAnimation(true); scoped_refptr<const ComputedStyle> other = builder.TakeStyle(); @@ -292,7 +292,7 @@ TEST_F(ComputedStyleTest, UpdatePropertySpecificDifferencesCompositingReasonsFilter) { - scoped_refptr<const ComputedStyle> style = CreateComputedStyle(); + scoped_refptr<const ComputedStyle> style = InitialComputedStyle(); ComputedStyleBuilder builder(*style); builder.SetHasCurrentFilterAnimation(true); scoped_refptr<const ComputedStyle> other = builder.TakeStyle(); @@ -304,7 +304,7 @@ TEST_F(ComputedStyleTest, UpdatePropertySpecificDifferencesCompositingReasonsBackdropFilter) { - scoped_refptr<const ComputedStyle> style = CreateComputedStyle(); + scoped_refptr<const ComputedStyle> style = InitialComputedStyle(); ComputedStyleBuilder builder(*style); builder.SetHasCurrentBackdropFilterAnimation(true); scoped_refptr<const ComputedStyle> other = builder.TakeStyle(); @@ -316,7 +316,7 @@ TEST_F(ComputedStyleTest, UpdatePropertySpecificDifferencesCompositingReasonsBackfaceVisibility) { - scoped_refptr<const ComputedStyle> style = CreateComputedStyle(); + scoped_refptr<const ComputedStyle> style = InitialComputedStyle(); ComputedStyleBuilder builder(*style); builder.SetBackfaceVisibility(EBackfaceVisibility::kHidden); scoped_refptr<const ComputedStyle> other = builder.TakeStyle(); @@ -328,7 +328,7 @@ TEST_F(ComputedStyleTest, UpdatePropertySpecificDifferencesCompositingReasonsWillChange) { - scoped_refptr<const ComputedStyle> style = CreateComputedStyle(); + scoped_refptr<const ComputedStyle> style = InitialComputedStyle(); ComputedStyleBuilder builder(*style); builder.SetBackfaceVisibility(EBackfaceVisibility::kHidden); builder.SetWillChangeProperties({CSSPropertyID::kOpacity}); @@ -357,7 +357,7 @@ TEST_F(ComputedStyleTest, UpdatePropertySpecificDifferencesCompositingReasonsOverflow) { - scoped_refptr<ComputedStyle> style = CreateComputedStyle(); + scoped_refptr<const ComputedStyle> style = InitialComputedStyle(); ComputedStyleBuilder builder(*style); builder.SetOverflowX(EOverflow::kHidden); scoped_refptr<const ComputedStyle> other = builder.TakeStyle(); @@ -369,7 +369,7 @@ TEST_F(ComputedStyleTest, UpdatePropertySpecificDifferencesCompositingReasonsContainsPaint) { - scoped_refptr<const ComputedStyle> style = CreateComputedStyle(); + scoped_refptr<const ComputedStyle> style = InitialComputedStyle(); ComputedStyleBuilder builder(*style); // This induces a flat used transform style. builder.SetContain(kContainsPaint); @@ -448,8 +448,8 @@ builder.SetBorderTopStyle(EBorderStyle::kSolid); builder.SetBorderRightStyle(EBorderStyle::kSolid); builder.SetBorderBottomStyle(EBorderStyle::kSolid); - scoped_refptr<const ComputedStyle> style = builder.TakeStyle(); - scoped_refptr<const ComputedStyle> other = ComputedStyle::Clone(*style); + scoped_refptr<const ComputedStyle> style = builder.CloneStyle(); + scoped_refptr<const ComputedStyle> other = builder.TakeStyle(); EXPECT_TRUE(style->BorderSizeEquals(*other)); UPDATE_STYLE(style, SetBorderLeftWidth, LayoutUnit(1)); @@ -545,7 +545,7 @@ builder.Set##flag(true); \ auto style = builder.TakeStyle(); \ EXPECT_TRUE(style->flag()); \ - auto other = CreateComputedStyle(); \ + auto other = InitialComputedStyle(); \ EXPECT_FALSE(other->flag()); \ EXPECT_EQ(ComputedStyle::Difference::inherited, \ ComputedStyle::ComputeDifference(style.get(), other.get())); \ @@ -560,7 +560,7 @@ builder.Set##flag(true); \ auto style = builder.TakeStyle(); \ EXPECT_TRUE(style->flag()); \ - auto other = CreateComputedStyle(); \ + auto other = InitialComputedStyle(); \ EXPECT_FALSE(other->flag()); \ EXPECT_EQ(ComputedStyle::Difference::kEqual, \ ComputedStyle::ComputeDifference(style.get(), other.get())); \ @@ -962,7 +962,7 @@ } TEST_F(ComputedStyleTest, InitialVariableNamesEmpty) { - scoped_refptr<ComputedStyle> style = CreateComputedStyle(); + scoped_refptr<const ComputedStyle> style = InitialComputedStyle(); EXPECT_TRUE(style->GetVariableNames().empty()); } @@ -1061,7 +1061,7 @@ } TEST_F(ComputedStyleTest, GetVariableNamesCount_Invalidation) { - scoped_refptr<const ComputedStyle> style = CreateComputedStyle(); + scoped_refptr<const ComputedStyle> style = InitialComputedStyle(); EXPECT_EQ(style->GetVariableNamesCount(), 0u); auto data = css_test_helpers::CreateVariableData("foo"); @@ -1502,7 +1502,7 @@ nullptr /* StyleRecalcContext */, StyleRequest(initial.get())); - scoped_refptr<ComputedStyle> style = CreateComputedStyle(); + scoped_refptr<const ComputedStyle> style = InitialComputedStyle(); state.SetStyle(*initial); EXPECT_FALSE(state.StyleBuilder().Animations()); EXPECT_FALSE(state.StyleBuilder().Transitions()); @@ -1773,7 +1773,7 @@ } TEST_F(ComputedStyleTest, BasicBuilder) { - scoped_refptr<ComputedStyle> original = CreateComputedStyle(); + scoped_refptr<const ComputedStyle> original = InitialComputedStyle(); Length left = Length::Fixed(1.0f); Length right = Length::Fixed(2.0f); @@ -1794,7 +1794,7 @@ TEST_F(ComputedStyleTest, MoveBuilder) { Length one = Length::Fixed(1.0f); - ComputedStyleBuilder builder1(*CreateComputedStyle()); + ComputedStyleBuilder builder1(*InitialComputedStyle()); builder1.SetScrollPaddingLeft(one); ComputedStyleBuilder builder2(std::move(builder1)); @@ -1809,10 +1809,10 @@ TEST_F(ComputedStyleTest, MoveAssignBuilder) { Length one = Length::Fixed(1.0f); - ComputedStyleBuilder builder1(*CreateComputedStyle()); + ComputedStyleBuilder builder1(*InitialComputedStyle()); builder1.SetScrollPaddingLeft(one); - ComputedStyleBuilder builder2(*CreateComputedStyle()); + ComputedStyleBuilder builder2(*InitialComputedStyle()); builder2 = std::move(builder1); EXPECT_FALSE(builder1.TakeStyle());
diff --git a/third_party/blink/renderer/core/testing/internals.cc b/third_party/blink/renderer/core/testing/internals.cc index 2025225..727c8e6f 100644 --- a/third_party/blink/renderer/core/testing/internals.cc +++ b/third_party/blink/renderer/core/testing/internals.cc
@@ -1139,6 +1139,9 @@ ShadowRoot* Internals::shadowRoot(Element* host) { DCHECK(host); + if (auto* input = DynamicTo<HTMLInputElement>(*host)) { + input->EnsureShadowSubtree(); + } return host->GetShadowRoot(); }
diff --git a/third_party/blink/renderer/core/timing/performance.cc b/third_party/blink/renderer/core/timing/performance.cc index f8cd29c..f5d79e56 100644 --- a/third_party/blink/renderer/core/timing/performance.cc +++ b/third_party/blink/renderer/core/timing/performance.cc
@@ -709,17 +709,6 @@ resource_timing_secondary_buffer_.push_back(entry); } -void Performance::AddResourceTimingWithUnparsedServerTiming( - mojom::blink::ResourceTimingInfoPtr info, - const String& server_timing_value, - const AtomicString& initiator_type) { - if (info->allow_timing_details) { - info->server_timing = - ParseServerTimingFromHeaderValueToMojo(server_timing_value); - } - AddResourceTiming(std::move(info), initiator_type); -} - // Called after loadEventEnd happens. void Performance::NotifyNavigationTimingToObservers() { if (navigation_timing_)
diff --git a/third_party/blink/renderer/core/timing/performance.h b/third_party/blink/renderer/core/timing/performance.h index 8909564f..4ab16f2 100644 --- a/third_party/blink/renderer/core/timing/performance.h +++ b/third_party/blink/renderer/core/timing/performance.h
@@ -200,11 +200,6 @@ void AddResourceTiming(mojom::blink::ResourceTimingInfoPtr, const AtomicString& initiator_type); - void AddResourceTimingWithUnparsedServerTiming( - mojom::blink::ResourceTimingInfoPtr, - const String& server_timing_value, - const AtomicString& initiator_type); - void NotifyNavigationTimingToObservers(); void AddFirstPaintTiming(base::TimeTicks start_time,
diff --git a/third_party/blink/renderer/core/timing/soft_navigation_heuristics.cc b/third_party/blink/renderer/core/timing/soft_navigation_heuristics.cc index 6ed3d24..911fe65d 100644 --- a/third_party/blink/renderer/core/timing/soft_navigation_heuristics.cc +++ b/third_party/blink/renderer/core/timing/soft_navigation_heuristics.cc
@@ -156,7 +156,7 @@ SetIsTrackingSoftNavigationHeuristicsOnDocument(false); } -void SoftNavigationHeuristics::SetBackForwardNavigationURL( +void SoftNavigationHeuristics::SetAsyncSoftNavigationURL( ScriptState* script_state, const String& url) { if (!url_.empty()) { @@ -178,11 +178,12 @@ } LocalDOMWindow* window = frame->DomWindow(); DCHECK(window); - // In case of a Soft Navigation using `history.back()`, `history.forward()` or - // `history.go()`, `SawURLChange` was called with an empty URL. If that's the - // case, don't report the Soft Navigation just yet, and wait for - // `SetBackForwardNavigationURL` to be called with the correct URL (which the - // renderer only knows about asynchronously). + // In case of a Soft Navigation where the url does not change immediately, + //`SawURLChange` was called with an empty URL. If that's the case, don't + // report the Soft Navigation just yet, and wait for + // `SetAsyncSoftNavigationURL` to be called with the correct URL (in the case + // of traversals, the renderer only knows about the correct URL asynchronously + // anyway). if (url_.empty()) { ResetPaintsIfNeeded(frame, window); return;
diff --git a/third_party/blink/renderer/core/timing/soft_navigation_heuristics.h b/third_party/blink/renderer/core/timing/soft_navigation_heuristics.h index 32db599..9d3193c 100644 --- a/third_party/blink/renderer/core/timing/soft_navigation_heuristics.h +++ b/third_party/blink/renderer/core/timing/soft_navigation_heuristics.h
@@ -41,8 +41,7 @@ bool skip_descendant_check = false); void ModifiedDOM(ScriptState*); uint32_t SoftNavigationCount() { return soft_navigation_count_; } - void SetBackForwardNavigationURL(ScriptState* script_state, - const String& url); + void SetAsyncSoftNavigationURL(ScriptState* script_state, const String& url); // TaskAttributionTracker::Observer's implementation. void OnCreateTaskScope(const scheduler::TaskAttributionId&) override;
diff --git a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc index 52c2f6a..972d38c 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
@@ -103,6 +103,7 @@ #include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h" #include "third_party/blink/renderer/core/html/portal/html_portal_element.h" #include "third_party/blink/renderer/core/html/shadow/shadow_element_names.h" +#include "third_party/blink/renderer/core/html_names.h" #include "third_party/blink/renderer/core/imagebitmap/image_bitmap.h" #include "third_party/blink/renderer/core/input_type_names.h" #include "third_party/blink/renderer/core/layout/layout_block_flow.h" @@ -3319,6 +3320,8 @@ return ax::mojom::blink::IsPopup::kNone; case PopoverValueType::kAuto: return ax::mojom::blink::IsPopup::kAuto; + case PopoverValueType::kHint: + return ax::mojom::blink::IsPopup::kHint; case PopoverValueType::kManual: return ax::mojom::blink::IsPopup::kManual; } @@ -5775,6 +5778,42 @@ } } + // For form controls that act as triggering elements for popovers of type + // kHint, then set aria-describedby to the popover. + if (auto* form_control = DynamicTo<HTMLFormControlElement>(element)) { + auto popover_target = form_control->popoverTargetElement(); + if (popover_target.popover && + popover_target.popover->PopoverType() == PopoverValueType::kHint) { + DCHECK(RuntimeEnabledFeatures::HTMLPopoverHintEnabled()); + description_from = ax::mojom::blink::DescriptionFrom::kPopoverAttribute; + if (description_sources) { + description_sources->push_back(DescriptionSource( + found_description, html_names::kPopovertargetAttr)); + description_sources->back().type = description_from; + } + AXObject* popover_ax_object = + AXObjectCache().GetOrCreate(popover_target.popover); + if (popover_ax_object) { + AXObjectSet visited; + description = RecursiveTextAlternative(*popover_ax_object, + popover_ax_object, visited); + if (related_objects) { + related_objects->push_back( + MakeGarbageCollected<NameSourceRelatedObject>(popover_ax_object, + description)); + } + if (description_sources) { + DescriptionSource& source = description_sources->back(); + source.related_objects = *related_objects; + source.text = description; + found_description = true; + } else { + return description; + } + } + } + } + description_from = ax::mojom::blink::DescriptionFrom::kNone; if (found_description) {
diff --git a/third_party/blink/renderer/modules/geolocation/geolocation.cc b/third_party/blink/renderer/modules/geolocation/geolocation.cc index 1ff5e69..f1872ed 100644 --- a/third_party/blink/renderer/modules/geolocation/geolocation.cc +++ b/third_party/blink/renderer/modules/geolocation/geolocation.cc
@@ -82,7 +82,6 @@ error_code = GeolocationPositionError::kPositionUnavailable; break; case device::mojom::blink::Geoposition::ErrorCode::NONE: - case device::mojom::blink::Geoposition::ErrorCode::TIMEOUT: NOTREACHED(); break; }
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc index dd6e469..6e6a5da6 100644 --- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc +++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
@@ -1694,14 +1694,8 @@ } void WebGLRenderingContextBase::SetIsInHiddenPage(bool hidden) { - is_hidden_ = hidden; if (GetDrawingBuffer()) GetDrawingBuffer()->SetIsInHiddenPage(hidden); - - if (!hidden && isContextLost() && restore_allowed_ && - auto_recovery_method_ == kAuto && !restore_timer_.IsActive()) { - restore_timer_.StartOneShot(base::TimeDelta(), FROM_HERE); - } } bool WebGLRenderingContextBase::PaintRenderingResultsToCanvas( @@ -8547,13 +8541,11 @@ WebGLContextEvent::Create(event_type_names::kWebglcontextlost, ""); Host()->HostDispatchEvent(event); restore_allowed_ = event->defaultPrevented(); - if (restore_allowed_ && !is_hidden_) { - if (auto_recovery_method_ == kAuto) { - // Defer the restore timer to give the context loss - // notifications time to propagate through the system: in - // particular, to the browser process. - restore_timer_.StartOneShot(kDurationBetweenRestoreAttempts, FROM_HERE); - } + if (restore_allowed_ && auto_recovery_method_ == kAuto) { + // Defer the restore timer to give the context loss + // notifications time to propagate through the system: in + // particular, to the browser process. + restore_timer_.StartOneShot(kDurationBetweenRestoreAttempts, FROM_HERE); } if (!restore_allowed_) {
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h index 9d9182e6..ddb31ceb 100644 --- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h +++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h
@@ -847,7 +847,6 @@ bool is_origin_top_left_ = false; - bool is_hidden_ = false; LostContextMode context_lost_mode_ = kNotLostContext; AutoRecoveryMethod auto_recovery_method_ = kManual; // Dispatches a context lost event once it is determined that one is needed.
diff --git a/third_party/blink/renderer/modules/webgpu/gpu.cc b/third_party/blink/renderer/modules/webgpu/gpu.cc index df95fe1..06384b8 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu.cc +++ b/third_party/blink/renderer/modules/webgpu/gpu.cc
@@ -168,8 +168,8 @@ GPUAdapter* gpu_adapter = nullptr; switch (status) { case WGPURequestAdapterStatus_Success: - gpu_adapter = MakeGarbageCollected<GPUAdapter>(this, "Default", adapter, - dawn_control_client_); + gpu_adapter = + MakeGarbageCollected<GPUAdapter>(this, adapter, dawn_control_client_); break; // Note: requestAdapter never rejects, but we print a console warning if @@ -216,7 +216,6 @@ IdentifiableTokenBuilder output_builder; if (adapter) { - output_builder.AddToken(IdentifiabilityBenignStringToken(adapter->name())); for (const auto& feature : adapter->features()->FeatureNameSet()) { output_builder.AddToken(IdentifiabilityBenignStringToken(feature)); }
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_adapter.cc b/third_party/blink/renderer/modules/webgpu/gpu_adapter.cc index d2fb2d4..d7a0e04 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_adapter.cc +++ b/third_party/blink/renderer/modules/webgpu/gpu_adapter.cc
@@ -86,13 +86,9 @@ GPUAdapter::GPUAdapter( GPU* gpu, - const String& name, WGPUAdapter handle, scoped_refptr<DawnControlClientHolder> dawn_control_client) - : DawnObjectBase(dawn_control_client), - name_(name), - handle_(handle), - gpu_(gpu) { + : DawnObjectBase(dawn_control_client), handle_(handle), gpu_(gpu) { WGPUAdapterProperties properties = {}; GetProcs().adapterGetProperties(handle_, &properties); is_fallback_adapter_ = properties.adapterType == WGPUAdapterType_CPU; @@ -135,10 +131,6 @@ } } -const String& GPUAdapter::name() const { - return name_; -} - GPUSupportedFeatures* GPUAdapter::features() const { return features_; }
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_adapter.h b/third_party/blink/renderer/modules/webgpu/gpu_adapter.h index 45bd1e5..27742ace 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_adapter.h +++ b/third_party/blink/renderer/modules/webgpu/gpu_adapter.h
@@ -26,7 +26,6 @@ public: GPUAdapter(GPU* gpu, - const String& name, WGPUAdapter handle, scoped_refptr<DawnControlClientHolder> dawn_control_client); @@ -35,7 +34,6 @@ void Trace(Visitor* visitor) const override; - const String& name() const; GPU* gpu() const { return gpu_; } GPUSupportedFeatures* features() const; GPUSupportedLimits* limits() const { return limits_; } @@ -64,7 +62,6 @@ WGPUDevice dawn_device, const char* error_message); - String name_; WGPUAdapter handle_; Member<GPU> gpu_; bool is_fallback_adapter_;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_adapter.idl b/third_party/blink/renderer/modules/webgpu/gpu_adapter.idl index dd0eb3ec..ee5fbe5 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_adapter.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_adapter.idl
@@ -8,7 +8,6 @@ Exposed(Window WebGPU, DedicatedWorker WebGPU), SecureContext ] interface GPUAdapter { - [HighEntropy=Direct, MeasureAs=GPUAdapter_Name] readonly attribute DOMString name; [SameObject] readonly attribute GPUSupportedFeatures features; [SameObject] readonly attribute GPUSupportedLimits limits; readonly attribute boolean isFallbackAdapter;
diff --git a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc index df89b5b..df05d7be 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc +++ b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc
@@ -99,7 +99,7 @@ HibernatedCanvasMemoryDumpProvider::GetInstance().Register(this); // Don't bother compressing very small canvases. - if (original_memory_size() < 16 * 1024 || + if (ImageMemorySize(*image) < 16 * 1024 || !base::FeatureList::IsEnabled(features::kCanvasCompressHibernatedImage)) { return; } @@ -187,6 +187,15 @@ sk_sp<SkData> encoded = params->image->encodeToData(SkEncodedImageFormat::kPNG, 100); + size_t original_memory_size = ImageMemorySize(*params->image); + int compression_ratio_percentage = static_cast<int>( + (static_cast<size_t>(100) * encoded->size()) / original_memory_size); + UMA_HISTOGRAM_PERCENTAGE("Blink.Canvas.2DLayerBridge.Compression.Ratio", + compression_ratio_percentage); + UMA_HISTOGRAM_CUSTOM_COUNTS( + "Blink.Canvas.2DLayerBridge.Compression.SnapshotSizeKb", + static_cast<int>(original_memory_size / 1024), 10, 500000, 50); + auto* reply_task_runner = params->reply_task_runner.get(); reply_task_runner->PostTask( FROM_HERE, @@ -205,8 +214,15 @@ DCHECK( base::FeatureList::IsEnabled(features::kCanvasCompressHibernatedImage)); + base::TimeTicks before = base::TimeTicks::Now(); // Note: not discarding the encoded image. - return SkImage::MakeFromEncoded(encoded_)->makeRasterImage(); + auto image = SkImage::MakeFromEncoded(encoded_)->makeRasterImage(); + base::TimeTicks after = base::TimeTicks::Now(); + UMA_HISTOGRAM_TIMES( + "Blink.Canvas.2DLayerBridge.Compression.DecompressionTime", + after - before); + return image; + ; } void HibernationHandler::Clear() { @@ -226,6 +242,12 @@ } } +// static +size_t HibernationHandler::ImageMemorySize(const SkImage& image) { + return static_cast<size_t>(image.height()) * image.width() * + image.imageInfo().bytesPerPixel(); +} + size_t HibernationHandler::original_memory_size() const { return static_cast<size_t>(width_) * height_ * bytes_per_pixel_; }
diff --git a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.h b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.h index 475e747..d553ae4e5 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.h +++ b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.h
@@ -143,6 +143,7 @@ std::unique_ptr<HibernationHandler::BackgroundTaskParams> params, sk_sp<SkData> encoded); scoped_refptr<base::SingleThreadTaskRunner> GetMainThreadTaskRunner() const; + static size_t ImageMemorySize(const SkImage& image); // Incremented each time the canvas is hibernated. uint64_t epoch_ = 0;
diff --git a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc index b8ece06..7683956 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc +++ b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc
@@ -35,6 +35,7 @@ #include "base/run_loop.h" #include "base/task/single_thread_task_runner.h" #include "base/test/bind.h" +#include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" #include "base/trace_event/memory_allocator_dump.h" @@ -1120,6 +1121,7 @@ {features::kCanvas2DHibernation, features::kCanvasCompressHibernatedImage}, {}); + base::HistogramTester histogram_tester; auto task_runner = base::MakeRefCounted<TestSingleThreadTaskRunner>(); ScopedTestingPlatformSupport<GpuMemoryBufferTestPlatform> platform; @@ -1152,8 +1154,18 @@ EXPECT_LT(handler.memory_size(), uncompressed_size); EXPECT_EQ(handler.original_memory_size(), uncompressed_size); + histogram_tester.ExpectTotalCount( + "Blink.Canvas.2DLayerBridge.Compression.Ratio", 1); + histogram_tester.ExpectUniqueSample( + "Blink.Canvas.2DLayerBridge.Compression.SnapshotSizeKb", + uncompressed_size / 1024, 1); + histogram_tester.ExpectTotalCount( + "Blink.Canvas.2DLayerBridge.Compression.DecompressionTime", 0); + SetIsInHiddenPage(bridge.get(), platform, false); EXPECT_FALSE(handler.is_encoded()); + histogram_tester.ExpectTotalCount( + "Blink.Canvas.2DLayerBridge.Compression.DecompressionTime", 1); EXPECT_TRUE(bridge->IsAccelerated()); EXPECT_FALSE(bridge->IsHibernating());
diff --git a/third_party/blink/renderer/platform/graphics/graphics_context.cc b/third_party/blink/renderer/platform/graphics/graphics_context.cc index 1ccf618..33000a3 100644 --- a/third_party/blink/renderer/platform/graphics/graphics_context.cc +++ b/third_party/blink/renderer/platform/graphics/graphics_context.cc
@@ -545,29 +545,6 @@ } } -// Draws a filled rectangle with a stroked border. -void GraphicsContext::DrawRect(const gfx::Rect& rect, - const AutoDarkMode& auto_dark_mode) { - if (rect.IsEmpty()) - return; - - SkRect sk_rect = gfx::RectToSkRect(rect); - if (ImmutableState()->FillColor().Alpha()) - DrawRect(sk_rect, ImmutableState()->FillFlags(), auto_dark_mode); - - if (ImmutableState()->GetStrokeData().Style() != kNoStroke && - ImmutableState()->StrokeColor().Alpha()) { - // Stroke a width: 1 inset border - cc::PaintFlags flags(ImmutableState()->FillFlags()); - flags.setColor(StrokeColor().toSkColor4f()); - flags.setStyle(cc::PaintFlags::kStroke_Style); - flags.setStrokeWidth(1); - - sk_rect.inset(0.5f, 0.5f); - DrawRect(sk_rect, flags, auto_dark_mode); - } -} - template <typename TextPaintInfo> void GraphicsContext::DrawTextInternal(const Font& font, const TextPaintInfo& text_info,
diff --git a/third_party/blink/renderer/platform/graphics/graphics_context.h b/third_party/blink/renderer/platform/graphics/graphics_context.h index 7f77d59..67f2ba1ad 100644 --- a/third_party/blink/renderer/platform/graphics/graphics_context.h +++ b/third_party/blink/renderer/platform/graphics/graphics_context.h
@@ -267,10 +267,6 @@ // ---------- End state management methods ----------------- - // DrawRect() fills and always strokes using a 1-pixel stroke inset from - // the rect borders (of the pre-set stroke color). - void DrawRect(const gfx::Rect&, const AutoDarkMode& auto_dark_mode); - // DrawLine() only operates on horizontal or vertical lines and uses the // current stroke settings. For dotted or dashed stroke, the line need to be // top-to-down or left-to-right to get correct interval of dots/dashes.
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.h b/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.h index ea98312e..7aea5ae 100644 --- a/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.h +++ b/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.h
@@ -60,7 +60,7 @@ const gfx::Rect& bounds) { return Draw(context, client, type, [&]() { DrawingRecorder recorder(context, client, type, bounds); - context.DrawRect(bounds, AutoDarkMode::Disabled()); + context.FillRect(bounds, AutoDarkMode::Disabled()); }); }
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_timing_utils.cc b/third_party/blink/renderer/platform/loader/fetch/resource_timing_utils.cc index f06d6d7f..29ea11dd 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_timing_utils.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_timing_utils.cc
@@ -20,6 +20,8 @@ namespace blink { +namespace { + Vector<mojom::blink::ServerTimingInfoPtr> ParseServerTimingFromHeaderValueToMojo(const String& value) { std::unique_ptr<ServerTimingHeaderVector> headers = @@ -33,6 +35,8 @@ return result; } +} // namespace + mojom::blink::ResourceTimingInfoPtr CreateResourceTimingInfo( base::TimeTicks start_time, const KURL& initial_url, @@ -81,11 +85,11 @@ } } - bool passes_cors = response->IsCorsSameOrigin(); + bool allow_response_details = response->IsCorsSameOrigin(); info->content_type = g_empty_string; - if (passes_cors) { + if (allow_response_details) { info->response_status = response->HttpStatusCode(); if (!response->HttpContentType().IsNull()) { info->content_type = response->HttpContentType(); @@ -94,7 +98,7 @@ bool expose_body_sizes = RuntimeEnabledFeatures::ResourceTimingUseCORSForBodySizesEnabled() - ? passes_cors + ? allow_response_details : info->allow_timing_details; if (expose_body_sizes && response) {
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_timing_utils.h b/third_party/blink/renderer/platform/loader/fetch/resource_timing_utils.h index 51382262..bcae05dc 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_timing_utils.h +++ b/third_party/blink/renderer/platform/loader/fetch/resource_timing_utils.h
@@ -17,9 +17,6 @@ class KURL; class ResourceResponse; -BLINK_PLATFORM_EXPORT WTF::Vector<mojom::blink::ServerTimingInfoPtr> -ParseServerTimingFromHeaderValueToMojo(const String& value); - BLINK_PLATFORM_EXPORT mojom::blink::ResourceTimingInfoPtr CreateResourceTimingInfo(base::TimeTicks start_time, const KURL& initial_url,
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index ab952dfc..70d9703 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1798,7 +1798,12 @@ status: "experimental", // Because the OT is already underway, it is being left with the "popup" name. origin_trial_feature_name: "HTMLPopupAttribute", - implied_by: ["HTMLSelectMenuElement"], + implied_by: ["HTMLSelectMenuElement","HTMLPopoverHint"], + }, + { + // TODO(crbug.com/1416284): Enables popover=hint functionality. + name: "HTMLPopoverHint", + status: "experimental", }, { name: "HTMLSelectMenuElement", @@ -3093,14 +3098,6 @@ name: "SpeculationRulesPrefetchWithSubresources", base_feature: "none", }, - // Adds a "referrer_policy" key to speculation rules. See https://crbug.com/1355146 - // TODO(mcnee): This feature shipped in M111. Clean up this flag in M113. - { - name: "SpeculationRulesReferrerPolicyKey", - status: "stable", - origin_trial_feature_name: "SpeculationRulesReferrerPolicyKey", - implied_by: ["SpeculationRulesPrefetchFuture"], - }, { name: "SpeculationRulesRelativeToDocument", base_feature: "none",
diff --git a/third_party/blink/renderer/platform/storage/blink_storage_key_fuzzer.cc b/third_party/blink/renderer/platform/storage/blink_storage_key_fuzzer.cc index 2183b48..9620cea 100644 --- a/third_party/blink/renderer/platform/storage/blink_storage_key_fuzzer.cc +++ b/third_party/blink/renderer/platform/storage/blink_storage_key_fuzzer.cc
@@ -6,18 +6,19 @@ #include "base/i18n/icu_util.h" #include "base/test/scoped_feature_list.h" #include "mojo/core/embedder/embedder.h" -#include "mojo/public/cpp/bindings/message.h" #include "net/base/features.h" #include "third_party/blink/public/common/storage_key/storage_key.h" #include "third_party/blink/public/common/storage_key/storage_key_mojom_traits.h" #include "third_party/blink/public/mojom/storage_key/storage_key.mojom-shared.h" #include "third_party/blink/renderer/platform/storage/blink_storage_key.h" #include "third_party/blink/renderer/platform/storage/blink_storage_key_mojom_traits.h" +#include "third_party/blink/renderer/platform/wtf/allocator/partitions.h" struct Environment { Environment() { CHECK(base::i18n::InitializeICU()); mojo::core::Init(); + WTF::Partitions::Initialize(); } // used by ICU integration. base::AtExitManager at_exit_manager; @@ -45,15 +46,15 @@ mojom_serialized_as_wtf.AppendRange(mojom_serialized.begin(), mojom_serialized.end()); blink::BlinkStorageKey mojom_blink_storage_key; - blink::mojom::blink::StorageKey::Deserialize(mojom_serialized_as_wtf, - &mojom_blink_storage_key); + assert(blink::mojom::blink::StorageKey::Deserialize( + mojom_serialized_as_wtf, &mojom_blink_storage_key)); WTF::Vector<uint8_t> mojom_blink_serialized = blink::mojom::blink::StorageKey::Serialize(&mojom_blink_storage_key); std::vector<uint8_t> mojom_blink_serialized_as_std( mojom_blink_serialized.begin(), mojom_blink_serialized.end()); blink::StorageKey mojom_storage_key; - blink::mojom::StorageKey::Deserialize(mojom_blink_serialized_as_std, - &mojom_storage_key); + assert(blink::mojom::StorageKey::Deserialize(mojom_blink_serialized_as_std, + &mojom_storage_key)); assert(maybe_storage_key->ExactMatchForTesting(mojom_storage_key)); // Test type conversion path.
diff --git a/third_party/blink/tools/blinkpy/tool/commands/copy_existing_baselines.py b/third_party/blink/tools/blinkpy/tool/commands/copy_existing_baselines.py index 48b7ecdb..476f834 100644 --- a/third_party/blink/tools/blinkpy/tool/commands/copy_existing_baselines.py +++ b/third_party/blink/tools/blinkpy/tool/commands/copy_existing_baselines.py
@@ -144,7 +144,7 @@ port.baseline_version_dir(), self._file_name_for_expected_result(virtual_test_name, suffix)) - if port.skips_test(test_name): + if port.skips_test(virtual_test_name): self._log_skipped_test(port, virtual_test_name) if self._tool.filesystem.exists(new_baseline): self._tool.filesystem.remove(new_baseline)
diff --git a/third_party/blink/tools/blinkpy/tool/commands/copy_existing_baselines_unittest.py b/third_party/blink/tools/blinkpy/tool/commands/copy_existing_baselines_unittest.py index 3ebbd27..a0e2f64 100644 --- a/third_party/blink/tools/blinkpy/tool/commands/copy_existing_baselines_unittest.py +++ b/third_party/blink/tools/blinkpy/tool/commands/copy_existing_baselines_unittest.py
@@ -3,9 +3,11 @@ # found in the LICENSE file. import optparse +from unittest import mock from blinkpy.tool.commands.rebaseline_unittest import BaseTestCase from blinkpy.tool.commands.copy_existing_baselines import CopyExistingBaselines +from blinkpy.web_tests.port.base import VirtualTestSuite class TestCopyExistingBaselines(BaseTestCase): @@ -297,6 +299,37 @@ 'platform/test-linux-trusty/failures/expected/image-expected.txt' ))) + def test_no_copy_skipped_virtual_test(self): + """Verify that a virtual test skipped for a platform is not copied.""" + linux_only_suite = VirtualTestSuite( + prefix='linux-only', + platforms=['Linux'], + bases=['failures/expected/image.html'], + args=['--dummy-flag']) + self._write( + self.baseline_path( + 'platform/test-win-win10/failures/expected/image-expected.txt' + ), 'original test-win-win10 result') + + with mock.patch( + 'blinkpy.web_tests.port.test.TestPort.virtual_test_suites', + return_value=[linux_only_suite]): + self.command.execute( + self.options(port_name='test-win-win10', + test='failures/expected/image.html'), [], + self.tool) + + self.assertEqual( + self._read( + self.baseline_path( + 'platform/test-linux-trusty/failures/expected/image-expected.txt' + )), 'original test-win-win10 result') + self.assertFalse( + self.tool.filesystem.exists( + self.baseline_path( + 'platform/test-win-win10/virtual/linux-only/failures/expected/image-expected.txt' + ))) + def test_port_for_primary_baseline(self): # Testing a protected method - pylint: disable=protected-access self.assertEqual(
diff --git a/third_party/blink/tools/blinkpy/w3c/wpt_results_processor.py b/third_party/blink/tools/blinkpy/w3c/wpt_results_processor.py index dd8883d53..ff93640 100644 --- a/third_party/blink/tools/blinkpy/w3c/wpt_results_processor.py +++ b/third_party/blink/tools/blinkpy/w3c/wpt_results_processor.py
@@ -594,7 +594,6 @@ stale expectations by default. * 'known_intermittent': When omitted, no intermittent statuses are expected. - * 'duration': Time taken to run the test. See Also: https://github.com/web-platform-tests/wpt/blob/131b8a541ba98afcef35ae757e4fb2f805714230/tools/wptrunner/wptrunner/metadata.py#L439-L450 @@ -603,6 +602,9 @@ compact_results = [] for result in results: compact_result = {'status': result['status']} + duration = result.get('duration') + if duration: + compact_result['duration'] = duration expected = result.get('expected') if expected and expected != result['status']: compact_result['expected'] = expected
diff --git a/third_party/blink/tools/blinkpy/w3c/wpt_results_processor_unittest.py b/third_party/blink/tools/blinkpy/w3c/wpt_results_processor_unittest.py index 148ea78..948744bb 100644 --- a/third_party/blink/tools/blinkpy/w3c/wpt_results_processor_unittest.py +++ b/third_party/blink/tools/blinkpy/w3c/wpt_results_processor_unittest.py
@@ -992,5 +992,7 @@ }], 'status': 'OK', + 'duration': + 1000, 'known_intermittent': ['CRASH'], }])
diff --git a/third_party/blink/tools/run_wpt_tests.py b/third_party/blink/tools/run_wpt_tests.py index 470c209..cb51f03e 100755 --- a/third_party/blink/tools/run_wpt_tests.py +++ b/third_party/blink/tools/run_wpt_tests.py
@@ -927,10 +927,10 @@ 'if using only emulators.') self.provision_devices(devices) + self.update_options() yield def update_options(self): - super().update_options() self._options.device_serial.extend(sorted(self.devices)) self._options.package_name = (self._options.package_name or self.get_browser_package_name())
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 79fd021..c3631d8 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -2924,6 +2924,8 @@ crbug.com/626703 [ Win ] virtual/partitioned-cookies/http/tests/inspector-protocol/network/disabled-cache-navigation.js [ Failure ] # ====== New tests from wpt-importer added here ====== +crbug.com/626703 external/wpt/css/css-images/image-set/image-set-zero-resolution-rendering-2.html [ Failure ] +crbug.com/626703 external/wpt/css/css-images/image-set/image-set-zero-resolution-rendering.html [ Failure ] crbug.com/626703 virtual/plz-dedicated-worker/external/wpt/html/cross-origin-embedder-policy/credentialless/dedicated-worker.https.window.html [ Failure Timeout ] crbug.com/626703 [ Linux ] external/wpt/html/semantics/links/hyperlink-auditing/headers.optional.html [ Timeout ] crbug.com/626703 [ Mac13 ] external/wpt/html/semantics/links/hyperlink-auditing/headers.optional.html [ Timeout ] @@ -6890,16 +6892,16 @@ crbug.com/v8/13743 fast/forms/ValidityState-patternMismatch.html [ Failure Pass ] # To land rename CL in devtools repo -crbug.com/1418045 http/tests/devtools/tracing/buffer-usage.js [ Timeout Crash Failure Pass ] -crbug.com/1418045 http/tests/devtools/report-protocol-errors.js [ Timeout Crash Failure Pass ] -crbug.com/1418045 http/tests/devtools/tracing/trace-event-self-time.js [ Timeout Crash Failure Pass ] -crbug.com/1418045 http/tests/devtools/oopif/oopif-elements-inspect.js [ Timeout Crash Failure Pass ] -crbug.com/1418045 http/tests/devtools/oopif/oopif-performance-monitor.js [ Timeout Crash Failure Pass ] -crbug.com/1418045 http/tests/devtools/tracing/timeline-js/cpu-profile-unsorted-timestamps.js [ Timeout Crash Failure Pass ] -crbug.com/1418045 http/tests/devtools/profiler/sampling-profiler-basic.js [ Timeout Crash Failure Pass ] -crbug.com/1418045 http/tests/devtools/sdk/network-interception-wildcard-pattern-matching.js [ Timeout Crash Failure Pass ] -crbug.com/1418045 http/tests/devtools/elements/event-listeners-framework-with-service-worker.js [ Timeout Crash Failure Pass ] -crbug.com/1418045 http/tests/devtools/service-workers/service-worker-agents.js [ Timeout Crash Failure Pass ] -crbug.com/1418045 http/tests/devtools/service-workers/service-worker-manager.js [ Timeout Crash Failure Pass ] -crbug.com/1418045 http/tests/devtools/persistence/persistence-sync-content-nodejs.js [ Timeout Crash Failure Pass ] -crbug.com/1418045 http/tests/devtools/application-panel/resources-panel-resource-preview.js [ Timeout Crash Failure Pass ] +crbug.com/1418045 http/tests/devtools/tracing/buffer-usage.js [ Crash Failure Pass Timeout ] +crbug.com/1418045 http/tests/devtools/report-protocol-errors.js [ Crash Failure Pass Timeout ] +crbug.com/1418045 http/tests/devtools/tracing/trace-event-self-time.js [ Crash Failure Pass Timeout ] +crbug.com/1418045 http/tests/devtools/oopif/oopif-elements-inspect.js [ Crash Failure Pass Timeout ] +crbug.com/1418045 http/tests/devtools/oopif/oopif-performance-monitor.js [ Crash Failure Pass Timeout ] +crbug.com/1418045 http/tests/devtools/tracing/timeline-js/cpu-profile-unsorted-timestamps.js [ Crash Failure Pass Timeout ] +crbug.com/1418045 http/tests/devtools/profiler/sampling-profiler-basic.js [ Crash Failure Pass Timeout ] +crbug.com/1418045 http/tests/devtools/sdk/network-interception-wildcard-pattern-matching.js [ Crash Failure Pass Timeout ] +crbug.com/1418045 http/tests/devtools/elements/event-listeners-framework-with-service-worker.js [ Crash Failure Pass Timeout ] +crbug.com/1418045 http/tests/devtools/service-workers/service-worker-agents.js [ Crash Failure Pass Timeout ] +crbug.com/1418045 http/tests/devtools/service-workers/service-worker-manager.js [ Crash Failure Pass Timeout ] +crbug.com/1418045 http/tests/devtools/persistence/persistence-sync-content-nodejs.js [ Crash Failure Pass Timeout ] +crbug.com/1418045 http/tests/devtools/application-panel/resources-panel-resource-preview.js [ Crash Failure Pass Timeout ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites index 7194fcf24..4b87e444 100644 --- a/third_party/blink/web_tests/VirtualTestSuites +++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -1174,10 +1174,18 @@ "prefix": "popover-disabled", "platforms": ["Linux", "Mac", "Win"], "bases": [], - "args": ["--disable-blink-features=HTMLSelectMenuElement,HTMLPopoverAttribute"], + "args": ["--disable-blink-features=HTMLSelectMenuElement,HTMLPopoverAttribute,HTMLPopoverHint"], "expires": "Jul 1, 2023" }, { + "prefix": "popover-hint-disabled", + "platforms": ["Linux", "Mac", "Win"], + "bases": [], + "args": ["--enable-blink-features=HTMLPopoverAttribute", + "--disable-blink-features=HTMLPopoverHint"], + "expires": "Jan 1, 2024" + }, + { "prefix": "expose-lcp-render-time", "platforms": [ "Linux",
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json index 94113dc..b9b1c83 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -91048,6 +91048,19 @@ {} ] ], + "out-of-flow-in-multicolumn-116.html": [ + "fac536a65b34163867de1aad2b7f7378046abb47", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], "overflow-clip-000.html": [ "72b10f5cdd3092a042f1f90bff04e9428d61608e", [ @@ -135221,32 +135234,6 @@ {} ] ], - "image-set-invalid-resolution-rendering-2.html": [ - "c8b560b7fcb3773947ea6c443441fe4397d3bf8e", - [ - null, - [ - [ - "/css/css-images/image-set/reference/image-set-rendering-ref.html", - "==" - ] - ], - {} - ] - ], - "image-set-invalid-resolution-rendering.html": [ - "91aeaccebdc323a45240ab971989fe1f6464f46b", - [ - null, - [ - [ - "/css/css-images/image-set/reference/image-set-rendering-ref.html", - "==" - ] - ], - {} - ] - ], "image-set-linear-gradient-rendering.html": [ "2fc31b95a81e3c46fde0f42edcaad04c1ed6f1b9", [ @@ -135519,6 +135506,32 @@ ], {} ] + ], + "image-set-zero-resolution-rendering-2.html": [ + "5c835a3fbcc8b4304d4bf13ff4bd037d8f518dd7", + [ + null, + [ + [ + "/css/css-images/image-set/reference/image-set-rendering-ref.html", + "==" + ] + ], + {} + ] + ], + "image-set-zero-resolution-rendering.html": [ + "d7e4eb7fdc25af16c17e9e7549f67389afea3285", + [ + null, + [ + [ + "/css/css-images/image-set/reference/image-set-rendering-ref.html", + "==" + ] + ], + {} + ] ] }, "infinite-radial-gradient-refcrash.html": [ @@ -153236,7 +153249,7 @@ ] ], "nesting-basic.html": [ - "dde3ebbcfdb8d268d22fa8ce6940655808c0a202", + "19ff48e4a29588e48eb19570149ad7525827cd8c", [ null, [ @@ -265222,16 +265235,6 @@ } }, "support": { - ".cache": { - "gitignore2.json": [ - "6e2c795a75ebbba367fa5a46852dca88bca7c835", - [] - ], - "mtime.json": [ - "a5fe875091039492485267682436620cc735681f", - [] - ] - }, ".gitignore": [ "d93e645d547894b50149d3726de2654957b6e06f", [] @@ -269355,6 +269358,10 @@ "5e812c1ab92b6abc720216be781f821b7b592661", [] ], + "compute_pressure_cross_origin_focus_control.tentative.https.window.js.ini": [ + "ec03acb4589e5e5a957eb619eed700367900d6bb", + [] + ], "compute_pressure_detached_iframe.tentative.https.html.ini": [ "35432640a4335b60d7e1e71b28aa9a19b58f61da", [] @@ -269387,6 +269394,10 @@ "5970aeaff5128f90add28045f94e294f211aab73", [] ], + "compute_pressure_same_origin_focus_control.tentative.https.window.js.ini": [ + "dc7f8d7cb367d3d19a0f150169f676a8c0d46407", + [] + ], "compute_pressure_take_records.tentative.https.window.js.ini": [ "94e875de071bb838887e77a0bba13b6c0cdbf2b5", [] @@ -300249,6 +300260,14 @@ "f2b544a7d84384c975f58ab57a829a3c4cee6556", [] ], + "image-set-zero-resolution-rendering-2.html.ini": [ + "778000386d8fe4d83aff87cb8cf8a4bdb938e6fc", + [] + ], + "image-set-zero-resolution-rendering.html.ini": [ + "f2243377a7f43e8907262abf66cbf70811e578b9", + [] + ], "reference": { "image-set-conic-gradient-rendering-ref.html": [ "2a5133ee94e792877410cae71be904c585bf0a6c", @@ -304210,6 +304229,10 @@ "7c33b48f5e6077ad87a230d8ca54976e55785445", [] ], + "getclientrects-000.html.ini": [ + "23360a44c7cd81c0d6e465d0401c5ec851b792e6", + [] + ], "getclientrects-001.html.ini": [ "59242d8056b3a4cf5812991a1f2e79d1238eac22", [] @@ -305295,7 +305318,7 @@ [] ], "nesting-basic-ref.html": [ - "8825ad47d277feb6e64fde381107833e84ccbc56", + "8038f369cde2b496106223551ab9441a79d2621e", [] ], "supports-is-consistent-ref.html": [ @@ -309366,6 +309389,10 @@ [] ] }, + "shape-image-003.html.ini": [ + "0a4d469255313aec5fabc656327057b20c1c15fe", + [] + ], "shape-image-004.html.ini": [ "461a202b5972e2da219fa1d18784033872891be9", [] @@ -315049,6 +315076,10 @@ "be8ba325fbe07e9c6a2af6f40cdeca78f4c9c841", [] ], + "text-transform-capitalize-022.html.ini": [ + "f4a6665417c2b26b7fccca3fd7b5e05e219e0e30", + [] + ], "text-transform-capitalize-026.html.ini": [ "6e52a555638556b0cd1cc16bf167482196479d88", [] @@ -320813,6 +320844,10 @@ "2a170629651d9defa1951ceceeab784ca50ea285", [] ], + "kind-of-widget-fallback-input-submit-border-right-width-001.html.ini": [ + "1e55e271c6c6f134ac658bcefa5369580ea553da", + [] + ], "kind-of-widget-fallback-input-submit-border-top-left-radius-001.html.ini": [ "3c0a4536d792ebcd543ab708a30b850998a25a60", [] @@ -320821,6 +320856,10 @@ "268cb3d48ba138d9f23501af4e028ac13e099d09", [] ], + "kind-of-widget-fallback-input-text-background-origin-001.html.ini": [ + "b5b8f0ea2c69a7494b89e5b208bfcc303baf20a1", + [] + ], "kind-of-widget-fallback-input-text-border-bottom-right-radius-001.html.ini": [ "8cf94321dc1df346f82158550e4cd2ad2b5b6e3d", [] @@ -321036,6 +321075,10 @@ "kind-of-widget-fallback-textarea-border-start-start-radius-001.html.ini": [ "7507d0dd65818071cdfc2fdbe3a96d7249cc1e24", [] + ], + "kind-of-widget-fallback-textarea-border-top-color-001.html.ini": [ + "9af42e769df5911125cc0aca08424b5836c96aca", + [] ] }, "compute-kind-widget-no-fallback-props-001.html.ini": [ @@ -328756,10 +328799,6 @@ "cab488fce6ad05f23f3286d9f53c4d050ee96aa7", [] ], - "media-query-matches-in-iframe-expected.txt": [ - "13cf904ee5ad53b1974139db08974c3a5d8604e8", - [] - ], "media-query-matches-in-iframe.html.ini": [ "e0829db3d9282a76cc3fd2039bfbf968080f3a6f", [] @@ -328838,12 +328877,8 @@ [] ] }, - "test_media_queries-expected.txt": [ - "0baac7d12c7ddbfb6e3bdf86ea5ddecc8447ab46", - [] - ], "test_media_queries.html.ini": [ - "b0ddcef7ba1396027ff2a7c18331b6f0f222857a", + "f21b93fe675e818d92f8a5aaabe0ca101e31e3eb", [] ], "viewport-script-dynamic-ref.html": [ @@ -343294,10 +343329,18 @@ "c6e046747c6092994e7f72c3132299b3dada8978", [] ], + "open-features-non-integer-height.html.ini": [ + "2c26934862f4a84b273590a8b7cf185ae15c1940", + [] + ], "open-features-non-integer-innerheight.html.ini": [ "aadc15b7492590b3a6bc7106f2fed3a5000777a7", [] ], + "open-features-non-integer-innerwidth.html.ini": [ + "e28fcf4bfc56438a02a9283766541df2910677b7", + [] + ], "open-features-non-integer-left-expected.txt": [ "62b1506da1c9b363345ccfdd989590ac6ec30d5c", [] @@ -346716,6 +346759,10 @@ "46ad58d83bf6e98913ca4c564b7acb8f19fa0093", [] ], + "popup-meta-http-equiv.https.html.ini": [ + "bb5e9fa51915d02574ebdba9c23f557f5e567360", + [] + ], "popup-redirect-cache.https.html.headers": [ "46ad58d83bf6e98913ca4c564b7acb8f19fa0093", [] @@ -355239,7 +355286,7 @@ [] ], "select-event.html.ini": [ - "4cabb085251cfd1eac6bc694eb7c963be6d1ab30", + "7ac279e52f4eacc5275677ac1604146157a45e77", [] ] }, @@ -362526,7 +362573,7 @@ [] ], "cross-origin-iframe.sub.html.ini": [ - "87d0f1d05a85f0703a13ce619a3e7ad54bf3d91f", + "49c5d9b0639187d7cd2e5e53309c1984628f6c86", [] ], "idlharness.window-expected.txt": [ @@ -362594,7 +362641,13 @@ "same-origin-grand-child-iframe.sub.html.ini": [ "8cc9dfe7b58ef24eaea9603008ad524a6f3551c2", [] - ] + ], + "v2": { + "delay-test.html.ini": [ + "9900ba92af3389fbee98bd06a35b2df172f3527e", + [] + ] + } }, "intervention-reporting": { "META.yml": [ @@ -371943,7 +371996,7 @@ [] ], "frame-timing.js": [ - "019bd424b55065451eb4ad0a132d3a6befbbb5fc", + "65710e22c8fc39b4cc3ef5aa93460a2f4736f8d6", [] ], "frameset-timing-frame.html": [ @@ -372070,6 +372123,14 @@ "c104f3c8f0695a96646cf24a730eef0342f95876", [] ], + "object-frame-options-200.asis": [ + "122445326bdef6d058e1adf4d6a2b51e4f6889da", + [] + ], + "object-frame-options-403.asis": [ + "fd64f0bcdbb7c17f60f485a25cfa78c6317e0ce6", + [] + ], "object-navigate-back.html": [ "a746947818ffb4e36367f620d603c2f6874dab10", [] @@ -416356,6 +416417,25 @@ } ] ], + "compute_pressure_cross_origin_focus_control.tentative.https.window.js": [ + "982e4bba0e6cb70d5eef7361a0110ab4b07be20e", + [ + "compute-pressure/compute_pressure_cross_origin_focus_control.tentative.https.window.html", + { + "script_metadata": [ + [ + "timeout", + "long" + ], + [ + "script", + "/common/get-host-info.sub.js" + ] + ], + "timeout": "long" + } + ] + ], "compute_pressure_detached_iframe.tentative.https.html": [ "3b0a5504e536acf9426476122f59b7c8ed24b150", [ @@ -416456,7 +416536,7 @@ ] ], "compute_pressure_privacy_test.tentative.https.window.js": [ - "3a4198f547cc4b5f5fdf075f13efabc8429408a5", + "ceea886323cdfcb37f3deda425d90ef358a28c59", [ "compute-pressure/compute_pressure_privacy_test.tentative.https.window.html", { @@ -416494,6 +416574,13 @@ } ] ], + "compute_pressure_same_origin_focus_control.tentative.https.window.js": [ + "746f119f249c8c1a7d6451a5672823d011adf22e", + [ + "compute-pressure/compute_pressure_same_origin_focus_control.tentative.https.window.html", + {} + ] + ], "compute_pressure_supported_sources.tentative.https.window.js": [ "2a69e731e7f9f7c5c0b54ea3b7bc9202bda57f16", [ @@ -451527,7 +451614,7 @@ }, "inline": { "append.tentative.html": [ - "ee9a9e4ddbcf78a7517d8d038d66844880719e63", + "f80875622366939f48a7471513fb6319f75be718", [ null, {} @@ -458373,6 +458460,13 @@ null, {} ] + ], + "update-media-feature.html": [ + "8064117da73f956625f309263c9401b8adafc3a3", + [ + null, + {} + ] ] }, "motion": { @@ -582685,6 +582779,15 @@ {} ] ], + "entries-for-object-frame-options-deny.html": [ + "a69b642971ba6adfbde8afcd451b29603cb7fcf3", + [ + null, + { + "timeout": "long" + } + ] + ], "entry-attributes.html": [ "94f219f229107e4764134187f111dcc7757f617d", [ @@ -582782,7 +582885,7 @@ ] ], "iframe-sequence-of-events.html": [ - "02d1c362c9df491439fd81ed9be48d5859a2e94f", + "5d719fb9153f18f35d239c3135f3fd844aa8558c", [ null, {}
diff --git a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_cross_origin_focus_control.tentative.https.window.js.ini b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_cross_origin_focus_control.tentative.https.window.js.ini new file mode 100644 index 0000000..ec03acb --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_cross_origin_focus_control.tentative.https.window.js.ini
@@ -0,0 +1,2 @@ +[compute_pressure_cross_origin_focus_control.tentative.https.window.html] + expected: CRASH
diff --git a/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_same_origin_focus_control.tentative.https.window.js.ini b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_same_origin_focus_control.tentative.https.window.js.ini new file mode 100644 index 0000000..dc7f8d7 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/compute-pressure/compute_pressure_same_origin_focus_control.tentative.https.window.js.ini
@@ -0,0 +1,2 @@ +[compute_pressure_same_origin_focus_control.tentative.https.window.html] + expected: CRASH
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-116.html b/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-116.html new file mode 100644 index 0000000..fac536a --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-116.html
@@ -0,0 +1,13 @@ +<!DOCTYPE html> +<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1412313"> +<link rel="match" href="../reference/ref-filled-green-100px-square.xht"> +<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> +<div style="columns:1; column-fill:auto; height:100px; width:100px;"> + <div style="contain:size; height:100px; background:green;"> + <div style="height:50px;"></div> + <span style="position:relative; height:50px;"> + <div style="height:25px; background:red;"></div> + <div style="position:absolute; top:0; width:100px; height:25px; background:green;"></div> + </span> + </div> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/table/repeated-section/background-001.tentative.html b/third_party/blink/web_tests/external/wpt/css/css-break/table/repeated-section/background-001.tentative.html new file mode 100644 index 0000000..2084f4ad --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-break/table/repeated-section/background-001.tentative.html
@@ -0,0 +1,13 @@ +<!DOCTYPE html> +<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org"> +<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1418818"> +<link rel="match" href="../../../reference/ref-filled-green-100px-square.xht"> +<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> +<div style="columns:2; column-fill:auto; gap:0; width:100px; height:400px;"> + <div style="display:table; width:100%;"> + <div style="display:table-header-group; break-inside:avoid;"> + <div style="height:100px; background:linear-gradient(green 100px, red 100px);"></div> + </div> + <div style="height:400px;"></div> + </div> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-invalid-resolution-rendering-2.html b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-zero-resolution-rendering-2.html similarity index 72% rename from third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-invalid-resolution-rendering-2.html rename to third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-zero-resolution-rendering-2.html index c8b560b7..5c835a3f 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-invalid-resolution-rendering-2.html +++ b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-zero-resolution-rendering-2.html
@@ -4,13 +4,13 @@ <link rel="author" title="Traian Captan" href="mailto:tcaptan@chromium.org"> <link rel="help" href="https://drafts.csswg.org/css-images-4/#image-set-notation"> <link rel="match" href="reference/image-set-rendering-ref.html"> -<meta name="assert" content="image-set rendering when resolution is invalid"> +<meta name="assert" content="image-set rendering with zero resolution"> <style> #test { - background-image: url("/images/green.png"); + background-image: url("/images/red.png"); background-image: image-set( - url("/images/red.png") 0x, - url("/images/red.png") 2x + url("/images/green.png") 0x, + url("/images/green.png") 2x ); width: 100px; height: 100px;
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-zero-resolution-rendering-2.html.ini b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-zero-resolution-rendering-2.html.ini new file mode 100644 index 0000000..7780003 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-zero-resolution-rendering-2.html.ini
@@ -0,0 +1,2 @@ +[image-set-zero-resolution-rendering-2.html] + expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-invalid-resolution-rendering.html b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-zero-resolution-rendering.html similarity index 71% rename from third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-invalid-resolution-rendering.html rename to third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-zero-resolution-rendering.html index 91aeacc..d7e4eb7f 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-invalid-resolution-rendering.html +++ b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-zero-resolution-rendering.html
@@ -4,11 +4,11 @@ <link rel="author" title="Traian Captan" href="mailto:tcaptan@chromium.org"> <link rel="help" href="https://drafts.csswg.org/css-images-4/#image-set-notation"> <link rel="match" href="reference/image-set-rendering-ref.html"> -<meta name="assert" content="image-set rendering when resolution is invalid"> +<meta name="assert" content="image-set rendering with zero resolution"> <style> #test { - background-image: url("/images/green.png"); - background-image: image-set(url("/images/red.png") 0x); + background-image: url("/images/red.png"); + background-image: image-set(url("/images/green.png") 0x); width: 100px; height: 100px; }
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-zero-resolution-rendering.html.ini b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-zero-resolution-rendering.html.ini new file mode 100644 index 0000000..f2243377 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-zero-resolution-rendering.html.ini
@@ -0,0 +1,2 @@ +[image-set-zero-resolution-rendering.html] + expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-multicol/getclientrects-000.html.ini b/third_party/blink/web_tests/external/wpt/css/css-multicol/getclientrects-000.html.ini new file mode 100644 index 0000000..23360a44 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-multicol/getclientrects-000.html.ini
@@ -0,0 +1,18 @@ +[getclientrects-000.html] + [horizontal-tb ltr] + expected: [FAIL, PASS] + + [horizontal-tb rtl] + expected: [FAIL, PASS] + + [vertical-lr ltr] + expected: [FAIL, PASS] + + [vertical-lr rtl] + expected: [FAIL, PASS] + + [vertical-rl ltr] + expected: [FAIL, PASS] + + [vertical-rl rtl] + expected: [FAIL, PASS]
diff --git a/third_party/blink/web_tests/external/wpt/css/css-nesting/nesting-basic-ref.html b/third_party/blink/web_tests/external/wpt/css/css-nesting/nesting-basic-ref.html index 8825ad47d..8038f36 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-nesting/nesting-basic-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/css-nesting/nesting-basic-ref.html
@@ -5,8 +5,8 @@ <style> .test { background-color: green; - width: 100px; - height: 100px; + width: 30px; + height: 30px; display: grid; }
diff --git a/third_party/blink/web_tests/external/wpt/css/css-nesting/nesting-basic.html b/third_party/blink/web_tests/external/wpt/css/css-nesting/nesting-basic.html index dde3ebb..19ff48e4 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-nesting/nesting-basic.html +++ b/third_party/blink/web_tests/external/wpt/css/css-nesting/nesting-basic.html
@@ -6,8 +6,8 @@ <style> .test { background-color: red; - width: 100px; - height: 100px; + width: 30px; + height: 30px; display: grid; }
diff --git a/third_party/blink/web_tests/external/wpt/css/css-shapes/shape-outside/shape-image/shape-image-003.html.ini b/third_party/blink/web_tests/external/wpt/css/css-shapes/shape-outside/shape-image/shape-image-003.html.ini new file mode 100644 index 0000000..0a4d469 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-shapes/shape-outside/shape-image/shape-image-003.html.ini
@@ -0,0 +1,2 @@ +[shape-image-003.html] + expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/text-transform-capitalize-022.html.ini b/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/text-transform-capitalize-022.html.ini new file mode 100644 index 0000000..f4a6665 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/text-transform-capitalize-022.html.ini
@@ -0,0 +1,2 @@ +[text-transform-capitalize-022.html] + expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-submit-border-right-width-001.html.ini b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-submit-border-right-width-001.html.ini new file mode 100644 index 0000000..1e55e27 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-submit-border-right-width-001.html.ini
@@ -0,0 +1,2 @@ +[kind-of-widget-fallback-input-submit-border-right-width-001.html] + expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-text-background-origin-001.html.ini b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-text-background-origin-001.html.ini new file mode 100644 index 0000000..b5b8f0e --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-text-background-origin-001.html.ini
@@ -0,0 +1,2 @@ +[kind-of-widget-fallback-input-text-background-origin-001.html] + expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-textarea-border-top-color-001.html.ini b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-textarea-border-top-color-001.html.ini new file mode 100644 index 0000000..9af42e76 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-textarea-border-top-color-001.html.ini
@@ -0,0 +1,2 @@ +[kind-of-widget-fallback-textarea-border-top-color-001.html] + expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/mediaqueries/test_media_queries.html.ini b/third_party/blink/web_tests/external/wpt/css/mediaqueries/test_media_queries.html.ini new file mode 100644 index 0000000..f21b93f --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/mediaqueries/test_media_queries.html.ini
@@ -0,0 +1,6 @@ +[test_media_queries.html] + ['or' keyword: should_not_apply: (height) or (height)] + expected: FAIL + + [nesting: should_not_apply: ((height))] + expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/open-close/open-features-non-integer-height.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/open-close/open-features-non-integer-height.html.ini new file mode 100644 index 0000000..2c26934 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/open-close/open-features-non-integer-height.html.ini
@@ -0,0 +1,2 @@ +[open-features-non-integer-height.html] + expected: ERROR
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/open-close/open-features-non-integer-innerwidth.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/open-close/open-features-non-integer-innerwidth.html.ini new file mode 100644 index 0000000..e28fcf4 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/open-close/open-features-non-integer-innerwidth.html.ini
@@ -0,0 +1,2 @@ +[open-features-non-integer-innerwidth.html] + expected: [ERROR, OK]
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/popup-meta-http-equiv.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/popup-meta-http-equiv.https.html.ini new file mode 100644 index 0000000..bb5e9fa --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/popup-meta-http-equiv.https.html.ini
@@ -0,0 +1,2 @@ +[popup-meta-http-equiv.https.html] + expected: ERROR
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/textfieldselection/select-event.html.ini b/third_party/blink/web_tests/external/wpt/html/semantics/forms/textfieldselection/select-event.html.ini index 4cabb08..7ac279e 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/textfieldselection/select-event.html.ini +++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/textfieldselection/select-event.html.ini
@@ -4,15 +4,14 @@ [input type password: select() event queue] expected: - if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [FAIL, PASS] - if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [FAIL, PASS] + if (product == "content_shell") and (os == "linux") and (flag_specific == ""): [PASS, FAIL] + if (product == "content_shell") and (os == "mac"): [FAIL, PASS] FAIL [input type password: select() twice in disconnected node (must fire select only once)] expected: - if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL] - if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [PASS, FAIL] - if (product == "content_shell") and (os == "mac"): FAIL + if (product == "content_shell") and (os == "linux") and (flag_specific == ""): [FAIL, PASS] + if (product == "content_shell") and (os == "mac"): [PASS, FAIL] if product == "chrome": FAIL [input type password: selectionDirection a second time (must not fire select)] @@ -39,9 +38,7 @@ if product == "chrome": FAIL [input type password: selectionEnd out of range a second time (must not fire select)] - expected: - if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [FAIL, PASS] - FAIL + expected: FAIL [input type password: selectionEnd out of range disconnected node] expected: FAIL @@ -57,9 +54,7 @@ expected: FAIL [input type password: selectionStart a second time (must not fire select)] - expected: - if (product == "content_shell") and (os == "mac"): PASS - FAIL + expected: FAIL [input type password: selectionStart disconnected node] expected: FAIL @@ -85,17 +80,22 @@ expected: FAIL [input type password: setRangeText() a second time (must not fire select)] - expected: FAIL + expected: + if (product == "content_shell") and (os == "linux") and (flag_specific == ""): [FAIL, PASS] + FAIL [input type password: setRangeText() disconnected node] expected: FAIL [input type password: setRangeText() event queue] expected: + if (product == "content_shell") and (os == "linux") and (flag_specific == ""): [PASS, FAIL] if product == "chrome": FAIL [input type password: setRangeText() twice in disconnected node (must fire select only once)] - expected: FAIL + expected: + if (product == "content_shell") and (os == "linux") and (flag_specific == ""): [FAIL, PASS] + FAIL [input type password: setSelectionRange out of range a second time (must not fire select)] expected: FAIL @@ -127,39 +127,42 @@ expected: FAIL [input type search: select() event queue] - expected: - if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [FAIL, PASS] - if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [FAIL, PASS] - FAIL + expected: FAIL [input type search: select() twice in disconnected node (must fire select only once)] expected: - if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL] - if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [PASS, FAIL] - if (product == "content_shell") and (os == "mac"): FAIL + if (product == "content_shell") and (os == "mac"): [FAIL, PASS] if product == "chrome": FAIL [input type search: selectionDirection a second time (must not fire select)] - expected: FAIL + expected: + if (product == "content_shell") and (os == "mac"): [PASS, FAIL] + FAIL [input type search: selectionDirection disconnected node] - expected: FAIL + expected: + if (product == "content_shell") and (os == "mac"): [PASS, FAIL] + FAIL [input type search: selectionDirection event queue] expected: + if (product == "content_shell") and (os == "mac"): [FAIL, PASS] if product == "chrome": FAIL [input type search: selectionDirection twice in disconnected node (must fire select only once)] expected: FAIL [input type search: selectionEnd a second time (must not fire select)] - expected: FAIL + expected: + if (product == "content_shell") and (os == "mac"): [PASS, FAIL] + FAIL [input type search: selectionEnd disconnected node] expected: FAIL [input type search: selectionEnd event queue] expected: + if (product == "content_shell") and (os == "mac"): [FAIL, PASS] if product == "chrome": FAIL [input type search: selectionEnd out of range a second time (must not fire select)] @@ -180,6 +183,7 @@ [input type search: selectionStart a second time (must not fire select)] expected: + if (product == "content_shell") and (os == "mac"): [PASS, FAIL] if product == "chrome": PASS FAIL @@ -188,6 +192,7 @@ [input type search: selectionStart event queue] expected: + if (product == "content_shell") and (os == "mac"): [PASS, FAIL] if product == "chrome": FAIL [input type search: selectionStart out of range a second time (must not fire select)] @@ -207,9 +212,7 @@ expected: FAIL [input type search: setRangeText() a second time (must not fire select)] - expected: - if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [FAIL, PASS] - FAIL + expected: FAIL [input type search: setRangeText() disconnected node] expected: FAIL @@ -252,40 +255,49 @@ [input type tel: select() event queue] expected: - if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [FAIL, PASS] - if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [FAIL, PASS] + if (product == "content_shell") and (os == "linux") and (flag_specific == ""): [PASS, FAIL] + if (product == "content_shell") and (os == "mac"): [FAIL, PASS] FAIL [input type tel: select() twice in disconnected node (must fire select only once)] expected: - if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL] - if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [PASS, FAIL] + if (product == "content_shell") and (os == "linux") and (flag_specific == ""): [FAIL, PASS] if (product == "content_shell") and (os == "mac"): FAIL if product == "chrome": FAIL [input type tel: selectionDirection a second time (must not fire select)] expected: - if (product == "content_shell") and (os == "linux") and (flag_specific == ""): PASS + if (product == "content_shell") and (os == "linux") and (flag_specific == ""): [PASS, FAIL] + if (product == "content_shell") and (os == "mac"): [PASS, FAIL] FAIL [input type tel: selectionDirection disconnected node] - expected: FAIL + expected: + if (product == "content_shell") and (os == "mac"): [PASS, FAIL] + FAIL [input type tel: selectionDirection event queue] expected: + if (product == "content_shell") and (os == "linux") and (flag_specific == ""): [FAIL, PASS] + if (product == "content_shell") and (os == "mac"): [PASS, FAIL] if product == "chrome": FAIL [input type tel: selectionDirection twice in disconnected node (must fire select only once)] - expected: FAIL + expected: + if (product == "content_shell") and (os == "linux") and (flag_specific == ""): [PASS, FAIL] + FAIL [input type tel: selectionEnd a second time (must not fire select)] - expected: FAIL + expected: + if (product == "content_shell") and (os == "mac"): [PASS, FAIL] + FAIL [input type tel: selectionEnd disconnected node] expected: FAIL [input type tel: selectionEnd event queue] expected: + if (product == "content_shell") and (os == "mac"): [PASS, FAIL] if product == "chrome": FAIL [input type tel: selectionEnd out of range a second time (must not fire select)] @@ -305,13 +317,16 @@ expected: FAIL [input type tel: selectionStart a second time (must not fire select)] - expected: FAIL + expected: + if (product == "content_shell") and (os == "mac"): [PASS, FAIL] + FAIL [input type tel: selectionStart disconnected node] expected: FAIL [input type tel: selectionStart event queue] expected: + if (product == "content_shell") and (os == "mac"): [PASS, FAIL] if product == "chrome": FAIL [input type tel: selectionStart out of range a second time (must not fire select)] @@ -338,13 +353,10 @@ [input type tel: setRangeText() event queue] expected: - if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [PASS, FAIL] if product == "chrome": FAIL [input type tel: setRangeText() twice in disconnected node (must fire select only once)] - expected: - if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [FAIL, PASS] - FAIL + expected: FAIL [input type tel: setSelectionRange out of range a second time (must not fire select)] expected: FAIL @@ -361,7 +373,7 @@ [input type tel: setSelectionRange() a second time (must not fire select)] expected: - if (product == "content_shell") and (os == "linux") and (flag_specific == ""): PASS + if (product == "content_shell") and (os == "linux") and (flag_specific == ""): [FAIL, PASS] FAIL [input type tel: setSelectionRange() disconnected node] @@ -369,38 +381,42 @@ [input type tel: setSelectionRange() event queue] expected: + if (product == "content_shell") and (os == "linux") and (flag_specific == ""): [PASS, FAIL] if product == "chrome": FAIL [input type tel: setSelectionRange() twice in disconnected node (must fire select only once)] - expected: FAIL + expected: + if (product == "content_shell") and (os == "linux") and (flag_specific == ""): [FAIL, PASS] + FAIL [input type text: select() disconnected node] expected: FAIL [input type text: select() event queue] expected: - if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [FAIL, PASS] + if (product == "content_shell") and (os == "linux") and (flag_specific == ""): [FAIL, PASS] FAIL [input type text: select() twice in disconnected node (must fire select only once)] expected: - if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [PASS, FAIL] - if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL] + if (product == "content_shell") and (os == "linux") and (flag_specific == ""): [PASS, FAIL] if (product == "content_shell") and (os == "mac"): FAIL if product == "chrome": FAIL [input type text: selectionDirection a second time (must not fire select)] expected: - if (product == "content_shell") and (os == "linux") and (flag_specific == ""): PASS - if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [PASS, FAIL] + if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): PASS + if (product == "content_shell") and (os == "mac"): [PASS, FAIL] FAIL [input type text: selectionDirection disconnected node] - expected: FAIL + expected: + if (product == "content_shell") and (os == "mac"): [PASS, FAIL] + FAIL [input type text: selectionDirection event queue] expected: - if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [PASS, FAIL] + if (product == "content_shell") and (os == "mac"): [PASS, FAIL] if product == "chrome": FAIL [input type text: selectionDirection twice in disconnected node (must fire select only once)] @@ -408,8 +424,8 @@ [input type text: selectionEnd a second time (must not fire select)] expected: - if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [PASS, FAIL] - if (product == "content_shell") and (os == "linux") and (flag_specific == ""): PASS + if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): PASS + if (product == "content_shell") and (os == "mac"): [PASS, FAIL] FAIL [input type text: selectionEnd disconnected node] @@ -417,7 +433,7 @@ [input type text: selectionEnd event queue] expected: - if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [PASS, FAIL] + if (product == "content_shell") and (os == "mac"): [PASS, FAIL] if product == "chrome": FAIL [input type text: selectionEnd out of range a second time (must not fire select)] @@ -438,8 +454,7 @@ [input type text: selectionStart a second time (must not fire select)] expected: - if (product == "content_shell") and (os == "linux") and (flag_specific == ""): PASS - if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [PASS, FAIL] + if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): PASS if (product == "content_shell") and (os == "mac"): PASS FAIL @@ -448,7 +463,7 @@ [input type text: selectionStart event queue] expected: - if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [PASS, FAIL] + if (product == "content_shell") and (os == "mac"): FAIL if product == "chrome": FAIL [input type text: selectionStart out of range a second time (must not fire select)] @@ -465,7 +480,9 @@ expected: FAIL [input type text: selectionStart twice in disconnected node (must fire select only once)] - expected: FAIL + expected: + if (product == "content_shell") and (os == "mac"): [FAIL, PASS] + FAIL [input type text: setRangeText() a second time (must not fire select)] expected: FAIL @@ -495,8 +512,7 @@ [input type text: setSelectionRange() a second time (must not fire select)] expected: - if (product == "content_shell") and (os == "linux") and (flag_specific == ""): PASS - if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [PASS, FAIL] + if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): PASS FAIL [input type text: setSelectionRange() disconnected node] @@ -514,38 +530,44 @@ [input type url: select() event queue] expected: - if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [FAIL, PASS] - if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [FAIL, PASS] + if (product == "content_shell") and (os == "linux") and (flag_specific == ""): [FAIL, PASS] FAIL [input type url: select() twice in disconnected node (must fire select only once)] expected: - if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): [PASS, FAIL] - if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL] - if (product == "content_shell") and (os == "mac"): FAIL + if (product == "content_shell") and (os == "linux") and (flag_specific == ""): [PASS, FAIL] + if (product == "content_shell") and (os == "mac"): [FAIL, PASS] if product == "chrome": FAIL [input type url: selectionDirection a second time (must not fire select)] - expected: FAIL + expected: + if (product == "content_shell") and (os == "mac"): [PASS, FAIL] + FAIL [input type url: selectionDirection disconnected node] - expected: FAIL + expected: + if (product == "content_shell") and (os == "mac"): [PASS, FAIL] + FAIL [input type url: selectionDirection event queue] expected: + if (product == "content_shell") and (os == "mac"): [FAIL, PASS] if product == "chrome": FAIL [input type url: selectionDirection twice in disconnected node (must fire select only once)] expected: FAIL [input type url: selectionEnd a second time (must not fire select)] - expected: FAIL + expected: + if (product == "content_shell") and (os == "mac"): [PASS, FAIL] + FAIL [input type url: selectionEnd disconnected node] expected: FAIL [input type url: selectionEnd event queue] expected: + if (product == "content_shell") and (os == "mac"): [PASS, FAIL] if product == "chrome": FAIL [input type url: selectionEnd out of range a second time (must not fire select)] @@ -565,13 +587,16 @@ expected: FAIL [input type url: selectionStart a second time (must not fire select)] - expected: FAIL + expected: + if (product == "content_shell") and (os == "mac"): [PASS, FAIL] + FAIL [input type url: selectionStart disconnected node] expected: FAIL [input type url: selectionStart event queue] expected: + if (product == "content_shell") and (os == "mac"): [FAIL, PASS] if product == "chrome": FAIL [input type url: selectionStart out of range a second time (must not fire select)] @@ -617,26 +642,31 @@ expected: FAIL [input type url: setSelectionRange() a second time (must not fire select)] - expected: FAIL + expected: + if (product == "content_shell") and (os == "mac"): [FAIL, PASS] + FAIL [input type url: setSelectionRange() disconnected node] expected: FAIL [input type url: setSelectionRange() event queue] expected: + if (product == "content_shell") and (os == "mac"): [PASS, FAIL] if product == "chrome": FAIL [input type url: setSelectionRange() twice in disconnected node (must fire select only once)] - expected: FAIL + expected: + if (product == "content_shell") and (os == "mac"): [FAIL, PASS] + FAIL [textarea: select() disconnected node] expected: - if (product == "content_shell") and (os == "mac"): FAIL + if (product == "content_shell") and (os == "mac"): [FAIL, PASS] if product == "chrome": FAIL [textarea: select() event queue] expected: - if (product == "content_shell") and (os == "mac"): PASS + if (product == "content_shell") and (os == "mac"): [PASS, FAIL] if product == "chrome": PASS FAIL @@ -684,7 +714,7 @@ [textarea: selectionStart a second time (must not fire select)] expected: - if (product == "content_shell") and (os == "mac"): FAIL + if (product == "content_shell") and (os == "mac"): [FAIL, PASS] if product == "chrome": FAIL [textarea: selectionStart disconnected node] @@ -692,8 +722,7 @@ [textarea: selectionStart event queue] expected: - if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [FAIL, PASS] - if (product == "content_shell") and (os == "mac"): PASS + if (product == "content_shell") and (os == "mac"): [PASS, FAIL] FAIL [textarea: selectionStart out of range a second time (must not fire select)] @@ -711,8 +740,7 @@ [textarea: selectionStart twice in disconnected node (must fire select only once)] expected: - if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL] - if (product == "content_shell") and (os == "mac"): FAIL + if (product == "content_shell") and (os == "mac"): [FAIL, PASS] if product == "chrome": FAIL [textarea: setRangeText() a second time (must not fire select)]
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-attribute-basic.html b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-attribute-basic.html index e9167aae..c80534af 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-attribute-basic.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-attribute-basic.html
@@ -15,6 +15,7 @@ <div popover id=boolean>Pop up</div> <div popover="">Pop up</div> <div popover=auto>Pop up</div> + <div popover=hint>Pop up</div> <div popover=manual>Pop up</div> <article popover>Different element type</article> <header popover>Different element type</header> @@ -163,6 +164,10 @@ assert_equals(popover.popover,'manual','Invalid values should reflect as "manual"'); popover.removeAttribute('popover'); assert_equals(popover.popover,null,'No value should reflect as null'); + if (popoverHintSupported()) { + popover.popover='hint'; + assert_equals(popover.getAttribute('popover'),'hint'); + } popover.popover='auto'; assert_equals(popover.getAttribute('popover'),'auto'); popover.popover=''; @@ -223,7 +228,13 @@ const popover = createPopover(t); popover.showPopover(); assert_true(popover.matches(':open')); - popover.setAttribute('popover','manual'); // Change popover type + if (popoverHintSupported()) { + popover.setAttribute('popover','hint'); // Change popover type + assert_false(popover.matches(':open')); + popover.showPopover(); + assert_true(popover.matches(':open')); + popover.setAttribute('popover','manual'); + } assert_false(popover.matches(':open')); popover.showPopover(); assert_true(popover.matches(':open')); @@ -237,7 +248,7 @@ assert_false(popover.matches(':open'),'From "auto" to "invalid" (which is interpreted as "manual") should close the popover'); },'Changing attribute values should close open popovers'); - const validTypes = ["auto","manual"]; + const validTypes = popoverHintSupported() ? ["auto","hint","manual"] : ["auto","manual"]; validTypes.forEach(type => { test((t) => { const popover = createPopover(t); @@ -376,6 +387,7 @@ popover.hidePopover(); break; case 'auto': + case 'hint': assert_false(popover.matches(':open'),'A popover=auto should light-dismiss'); break; }
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-backdrop-appearance.html b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-backdrop-appearance.html index c71e148..cf57aee 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-backdrop-appearance.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-backdrop-appearance.html
@@ -36,7 +36,7 @@ <p>Test for [popover]::backdrop presence and stacking order. The test passes if there are 3 stacked boxes, with the brightest green on top.</p> <div popover id=bottom>Bottom - <div popover id=middle>Middle + <div popover=hint id=middle>Middle <div popover=manual id=top>Top</div> </div> </div>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-invoking-attribute.html b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-invoking-attribute.html index 7b1dc20a..9b7a714f 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-invoking-attribute.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-invoking-attribute.html
@@ -10,6 +10,7 @@ <script src="/resources/testdriver.js"></script> <script src="/resources/testdriver-actions.js"></script> <script src="/resources/testdriver-vendor.js"></script> +<script src="resources/popover-utils.js"></script> <body> <script> @@ -60,8 +61,9 @@ ...supportedInputButtonTypes, ...unsupportedTypes, ]; +const validTypes = popoverHintSupported() ? ["auto","hint","manual"] : ["auto","manual"]; window.addEventListener('load', () => { - ["auto","manual"].forEach(type => { + validTypes.forEach(type => { invokers.forEach(testcase => { ["toggle","hide","show","ShOw","garbage",null,undefined].forEach(action => { [false,true].forEach(use_idl_for_target => {
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-light-dismiss.html b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-light-dismiss.html index 2e9fdb4..2f7e2de9 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-light-dismiss.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-light-dismiss.html
@@ -461,6 +461,52 @@ },'Ensure circular/convoluted ancestral relationships are functional, with a direct showPopover()'); </script> +<div popover id=p10>Popover</div> +<div popover=hint id=p11>Hint</div> +<div popover=manual id=p12>Manual</div> +<style> + #p10 {top:100px;} + #p11 {top:200px;} + #p12 {top:300px;} +</style> +<script> +if (popoverHintSupported()) { + promise_test(async () => { + const auto = document.querySelector('#p10'); + const hint = document.querySelector('#p11'); + const manual = document.querySelector('#p12'); + // All three can be open at once, if shown in this order: + auto.showPopover(); + hint.showPopover(); + manual.showPopover(); + assert_true(auto.matches(':open')); + assert_true(hint.matches(':open')); + assert_true(manual.matches(':open')); + // Clicking the hint will close the auto, but not the manual. + await clickOn(hint); + assert_false(auto.matches(':open'),'auto should be hidden'); + assert_true(hint.matches(':open'),'hint should stay open'); + assert_true(manual.matches(':open'),'manual does not light dismiss'); + // Clicking outside should close the hint, but not the manual: + await clickOn(outside); + assert_false(auto.matches(':open')); + assert_false(hint.matches(':open'),'hint should close'); + assert_true(manual.matches(':open'),'manual does not light dismiss'); + manual.hidePopover(); + assert_false(manual.matches(':open')); + auto.showPopover(); + hint.showPopover(); + assert_true(auto.matches(':open')); + assert_true(hint.matches(':open')); + // Clicking on the auto should close the hint: + await clickOn(auto); + assert_true(auto.matches(':open'),'auto should stay open'); + assert_false(hint.matches(':open'),'hint should light dismiss'); + auto.hidePopover(); + assert_false(auto.matches(':open')); + },'Light dismiss of mixed popover types including hints'); +} +</script> <div popover id=p13>Popover 1 <div popover id=p14>Popover 2 <div popover id=p15>Popover 3</div>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-types-with-hints.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-types-with-hints.tentative.html new file mode 100644 index 0000000..39d24a0a --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-types-with-hints.tentative.html
@@ -0,0 +1,184 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<link rel="author" href="mailto:masonf@chromium.org"> +<link rel=help href="https://open-ui.org/components/popup.research.explainer"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<div> + <div popover>Popover</div> + <div popover=hint>Hint</div> + <div popover=manual>Async</div> + <div popover=manual>Async</div> + <script> + { + const auto = document.currentScript.parentElement.querySelector('[popover=""]'); + const hint = document.currentScript.parentElement.querySelector('[popover=hint]'); + const manual = document.currentScript.parentElement.querySelectorAll('[popover=manual]')[0]; + const manual2 = document.currentScript.parentElement.querySelectorAll('[popover=manual]')[1]; + function assert_state_1(autoOpen,hintOpen,manualOpen,manual2Open) { + assert_equals(auto.matches(':open'),autoOpen,'auto open state is incorrect'); + assert_equals(hint.matches(':open'),hintOpen,'hint open state is incorrect'); + assert_equals(manual.matches(':open'),manualOpen,'manual open state is incorrect'); + assert_equals(manual2.matches(':open'),manual2Open,'manual2 open state is incorrect'); + } + test(() => { + assert_state_1(false,false,false,false); + auto.showPopover(); + assert_state_1(true,false,false,false); + hint.showPopover(); + assert_state_1(true,true,false,false); + manual.showPopover(); + assert_state_1(true,true,true,false); + manual2.showPopover(); + assert_state_1(true,true,true,true); + hint.hidePopover(); + assert_state_1(true,false,true,true); + auto.hidePopover(); + assert_state_1(false,false,true,true); + auto.showPopover(); + hint.showPopover(); + assert_state_1(true,true,true,true); + auto.hidePopover(); // Non-nested tooltips can stay open when unrelated popovers are hidden. + assert_state_1(false,true,true,true); + hint.hidePopover(); + manual.hidePopover(); + assert_state_1(false,false,false,true); + manual2.hidePopover(); + assert_state_1(false,false,false,false); + },'manuals do not close popovers'); + + test(() => { + assert_state_1(false,false,false,false); + hint.showPopover(); + manual.showPopover(); + manual2.showPopover(); + assert_state_1(false,true,true,true); + auto.showPopover(); + assert_state_1(true,false,true,true); + auto.hidePopover(); + assert_state_1(false,false,true,true); + manual.hidePopover(); + manual2.hidePopover(); + assert_state_1(false,false,false,false); + },'autos close hints but not manuals'); + } + </script> +</div> + +<div> + <div popover>popover 1 + <div popover>popover 2 + <p id=anchorid>Anchor</p> + <div popover>popover 3</div> + </div> + </div> + <div popover=hint anchor=anchorid>Hint anchored to pop-up</div> + <script> + { + const popover1 = document.currentScript.parentElement.querySelectorAll('[popover=""]')[0]; + const popover2 = document.currentScript.parentElement.querySelectorAll('[popover=""]')[1]; + const popover3 = document.currentScript.parentElement.querySelectorAll('[popover=""]')[2]; + const hint = document.currentScript.parentElement.querySelector('[popover=hint]'); + function assert_state_2(popover1Open,popover2Open,popover3Open,hintOpen) { + assert_equals(popover1.matches(':open'),popover1Open,'popover1 open state is incorrect'); + assert_equals(popover2.matches(':open'),popover2Open,'popover2 open state is incorrect'); + assert_equals(popover3.matches(':open'),popover3Open,'popover3 open state is incorrect'); + assert_equals(hint.matches(':open'),hintOpen,'hint open state is incorrect'); + } + test(() => { + assert_state_2(false,false,false,false); + popover1.showPopover(); + popover2.showPopover(); + popover3.showPopover(); + assert_state_2(true,true,true,false); + hint.showPopover(); // Because hint is nested in popover2, popover3 should be hidden + assert_state_2(true,true,false,true); + popover1.hidePopover(); // Should close the hint, which is anchored to popover2 + assert_state_2(false,false,false,false); + },'hint is not closed by pre-existing auto'); + } + </script> +</div> + +<div> + <div popover=hint>Hint + <div popover=hint>Nested hint</div> + </div> + <script> + test(() => { + const hint1 = document.currentScript.parentElement.querySelectorAll('[popover=hint]')[0]; + const hint2 = document.currentScript.parentElement.querySelectorAll('[popover=hint]')[1]; + hint1.showPopover(); + assert_true(hint1.matches(':open')); + assert_false(hint2.matches(':open')); + hint2.showPopover(); + assert_false(hint1.matches(':open')); + assert_true(hint2.matches(':open')); + hint2.hidePopover(); + },'If a popover=hint is shown, it should hide any other open popover=hint pop-ups, including ancestral pop-ups. (You can\'t nest popover=hint)'); + </script> +</div> + +<div> + <div popover="hint">Hint + <div popover>Nested auto (note - never visible, since inside display:none subtree)</div> + </div> + <script> + test(() => { + const hint = document.currentScript.parentElement.querySelector('[popover=hint]'); + const auto = document.currentScript.parentElement.querySelector('[popover=""]'); + hint.showPopover(); + assert_true(hint.matches(':open')); + assert_false(auto.matches(':open')); + auto.showPopover(); + assert_false(hint.matches(':open')); + assert_true(auto.matches(':open')); + auto.hidePopover(); + },'If a popover=auto is shown, it should hide any open popover=hint, including if the popover=hint is an ancestral pop-up of the popover=auto. (You can\'t nest a popover=auto inside a popover=hint)'); + </script> +</div> + +<div> + <div popover>Auto + <div popover>Nested Auto</div> + <div popover=hint>Nested hint</div> + </div> + <script> + test(() => { + const auto = document.currentScript.parentElement.querySelectorAll('[popover=""]')[0]; + const auto2 = document.currentScript.parentElement.querySelectorAll('[popover=""]')[1]; + const hint = document.currentScript.parentElement.querySelector('[popover=hint]'); + auto.showPopover(); + auto2.showPopover(); + assert_true(auto.matches(':open')); + assert_true(auto2.matches(':open')); + hint.showPopover(); // This should hide auto2, since it is nested in auto1. + assert_true(auto.matches(':open')); + assert_false(auto2.matches(':open')); + assert_true(hint.matches(':open')); + auto.hidePopover(); // Should hide both auto and hint. + assert_false(auto.matches(':open')); + assert_false(hint.matches(':open')); + },'If you: a) show a popover=auto (call it D), then b) show a descendent popover=hint of D (call it T), then c) hide D, then T should be hidden. (A popover=hint can be nested inside a popover=auto)'); + </script> +</div> + +<div> + <div popover>Auto</div> + <div popover=hint>Non-Nested hint</div> + <script> + test(() => { + const auto = document.currentScript.parentElement.querySelector('[popover=""]'); + const hint = document.currentScript.parentElement.querySelector('[popover=hint]'); + auto.showPopover(); + hint.showPopover(); + assert_true(auto.matches(':open')); + assert_true(hint.matches(':open')); + auto.hidePopover(); + assert_false(auto.matches(':open')); + assert_true(hint.matches(':open')); + hint.hidePopover(); + },'If you: a) show a popover=auto (call it D), then b) show a non-descendent popover=hint of D (call it T), then c) hide D, then T should be left showing. (Non-nested popover=hint can stay open when unrelated popover=autos are hidden)'); + </script> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/resources/popover-utils.js b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/resources/popover-utils.js index 0df24ccd..404b893b 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/resources/popover-utils.js +++ b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/resources/popover-utils.js
@@ -107,3 +107,10 @@ window.addEventListener('load',show,{once:true}); } } +function popoverHintSupported() { + // TODO(crbug.com/1416284): This function should be removed, and + // any calls replaced with `true`, once popover=hint ships. + const testElement = document.createElement('div'); + testElement.popover = 'hint'; + return testElement.popover === 'hint'; +}
diff --git a/third_party/blink/web_tests/external/wpt/intersection-observer/cross-origin-iframe.sub.html.ini b/third_party/blink/web_tests/external/wpt/intersection-observer/cross-origin-iframe.sub.html.ini index 87d0f1d0..49c5d9b0 100644 --- a/third_party/blink/web_tests/external/wpt/intersection-observer/cross-origin-iframe.sub.html.ini +++ b/third_party/blink/web_tests/external/wpt/intersection-observer/cross-origin-iframe.sub.html.ini
@@ -10,11 +10,10 @@ [topDocument.scrollingElement.scrollTop = 100] expected: + if (product == "content_shell") and (os == "win") and (port == "win11"): [FAIL, PASS] if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): FAIL - if (product == "content_shell") and (os == "mac"): [PASS, FAIL] [topDocument.scrollingElement.scrollTop = 200] expected: - if (product == "content_shell") and (os == "win") and (port == "win11"): PASS - if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): PASS + if (product == "content_shell") and (os == "win"): PASS FAIL
diff --git a/third_party/blink/web_tests/external/wpt/intersection-observer/v2/delay-test.html.ini b/third_party/blink/web_tests/external/wpt/intersection-observer/v2/delay-test.html.ini new file mode 100644 index 0000000..9900ba92 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/intersection-observer/v2/delay-test.html.ini
@@ -0,0 +1,3 @@ +[delay-test.html] + ['delay' parameter throttles frequency of notifications.] + expected: [FAIL, PASS]
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/entries-for-object-frame-options-deny.html b/third_party/blink/web_tests/external/wpt/resource-timing/entries-for-object-frame-options-deny.html new file mode 100644 index 0000000..a69b642 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/resource-timing/entries-for-object-frame-options-deny.html
@@ -0,0 +1,35 @@ +<!DOCTYPE HTML> +<html> +<head> +<meta charset="utf-8" /> +<meta name="timeout" content="long"> +<link rel="author" title="Noam Rosenthal" href="noam@chromium.org"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="resources/entry-invariants.js"></script> +</head> +<body> +<script> +const {REMOTE_ORIGIN} = get_host_info(); + +promise_test(async t => { + const success_url = new URL("/resource-timing/resources/object-frame-options-200.asis", REMOTE_ORIGIN).href; + const fail_url = new URL("/resource-timing/resources/object-frame-options-403.asis", REMOTE_ORIGIN).href; + const load_object = async url => { + const object = document.createElement("object"); + object.data = url; + document.body.appendChild(object); + t.add_cleanup(() => object.remove()); + await new Promise(resolve => { + object.onload = object.onerror = resolve; + }); + }; + + await Promise.all([success_url, fail_url].map(load_object)); + assert_equals(performance.getEntriesByName(success_url).length, 1); + assert_equals(performance.getEntriesByName(fail_url).length, 1); +}, "Test that object elements with X-Frame-Options: Deny produce resource timing entries"); +</script> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/iframe-sequence-of-events.html b/third_party/blink/web_tests/external/wpt/resource-timing/iframe-sequence-of-events.html index 02d1c36..5d719fb9 100644 --- a/third_party/blink/web_tests/external/wpt/resource-timing/iframe-sequence-of-events.html +++ b/third_party/blink/web_tests/external/wpt/resource-timing/iframe-sequence-of-events.html
@@ -3,6 +3,7 @@ <title>Test the sequence of events when reporting iframe timing.</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="resources/entry-invariants.js"></script> <script src="resources/frame-timing.js"></script> <script src="/common/utils.js"></script> <script src="/common/get-host-info.sub.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resources/frame-timing.js b/third_party/blink/web_tests/external/wpt/resource-timing/resources/frame-timing.js index 019bd42..65710e2 100644 --- a/third_party/blink/web_tests/external/wpt/resource-timing/resources/frame-timing.js +++ b/third_party/blink/web_tests/external/wpt/resource-timing/resources/frame-timing.js
@@ -25,8 +25,8 @@ function test_frame_timing_change_src(type, - origin1 = document.origin, - origin2 = document.origin, + origin1 = location.origin, + origin2 = location.origin, tao = false, label = '') { const uid = token(); promise_test(async t => { @@ -59,5 +59,11 @@ const entries = performance.getEntries().filter(e => e.name.includes(uid)); assert_equals(entries.length, 2); + for (const entry of entries) { + if (tao || entry.name.startsWith(location.origin)) + invariants.assert_tao_pass_no_redirect_http(entry); + else + invariants.assert_tao_failure_resource(entry); + } }, label || `A ${type} should report separate RT entries if its src changed from the outside`); }
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resources/object-frame-options-200.asis b/third_party/blink/web_tests/external/wpt/resource-timing/resources/object-frame-options-200.asis new file mode 100644 index 0000000..12244532 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/resource-timing/resources/object-frame-options-200.asis
@@ -0,0 +1,6 @@ +HTTP/1.0 200 OK +Content-Type: text/html +X-Frame-Options: DENY +Content-Security-Policy: frame-ancestors 'none' + +Hello
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resources/object-frame-options-403.asis b/third_party/blink/web_tests/external/wpt/resource-timing/resources/object-frame-options-403.asis new file mode 100644 index 0000000..fd64f0bc --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/resource-timing/resources/object-frame-options-403.asis
@@ -0,0 +1,6 @@ +HTTP/1.0 403 OK +Content-Type: text/html +X-Frame-Options: DENY +Content-Security-Policy: frame-ancestors 'none' + +Hello
diff --git a/third_party/blink/web_tests/platform/mac/wpt_internal/compute-pressure/losing-focus-suspends-data-delivery.https.window-expected.txt b/third_party/blink/web_tests/platform/mac/wpt_internal/compute-pressure/losing-focus-suspends-data-delivery.https.window-expected.txt new file mode 100644 index 0000000..0a85053 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/wpt_internal/compute-pressure/losing-focus-suspends-data-delivery.https.window-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Observer should not receive PressureRecord if page loses focus assert_equals: expected "fair" but got "nominal" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/popover-disabled/popover-disabled-expected.txt b/third_party/blink/web_tests/virtual/popover-disabled/popover-disabled-expected.txt deleted file mode 100644 index 58123bd..0000000 --- a/third_party/blink/web_tests/virtual/popover-disabled/popover-disabled-expected.txt +++ /dev/null
@@ -1,15 +0,0 @@ -CONSOLE ERROR: Found a 'popover' attribute. If you are testing the popover API, you must enable Experimental Web Platform Features. If not, note that custom attributes must start with 'data-': https://html.spec.whatwg.org/multipage/dom.html#custom-data-attribute. This usage will *likely cause site breakage* when the popover API ships: https://chromestatus.com/feature/5463833265045504. -CONSOLE ERROR: Found a 'popover' attribute. If you are testing the popover API, you must enable Experimental Web Platform Features. If not, note that custom attributes must start with 'data-': https://html.spec.whatwg.org/multipage/dom.html#custom-data-attribute. This usage will *likely cause site breakage* when the popover API ships: https://chromestatus.com/feature/5463833265045504. -CONSOLE ERROR: Found a 'popover' attribute. If you are testing the popover API, you must enable Experimental Web Platform Features. If not, note that custom attributes must start with 'data-': https://html.spec.whatwg.org/multipage/dom.html#custom-data-attribute. This usage will *likely cause site breakage* when the popover API ships: https://chromestatus.com/feature/5463833265045504. -CONSOLE ERROR: Found a 'popover' attribute. If you are testing the popover API, you must enable Experimental Web Platform Features. If not, note that custom attributes must start with 'data-': https://html.spec.whatwg.org/multipage/dom.html#custom-data-attribute. This usage will *likely cause site breakage* when the popover API ships: https://chromestatus.com/feature/5463833265045504. -CONSOLE ERROR: Found a 'popover' attribute. If you are testing the popover API, you must enable Experimental Web Platform Features. If not, note that custom attributes must start with 'data-': https://html.spec.whatwg.org/multipage/dom.html#custom-data-attribute. This usage will *likely cause site breakage* when the popover API ships: https://chromestatus.com/feature/5463833265045504. -This is a testharness.js-based test. -PASS Basic tests -PASS <div popover="auto">This content should be visible, if HTMLPopoverAttribute is disabled</div> should be stylable/visible and not display:none -PASS <div popover="async">This content should be visible, if HTMLPopoverAttribute is disabled</div> should be stylable/visible and not display:none -PASS <div popover="invalid">This content should be visible, if HTMLPopoverAttribute is disabled</div> should be stylable/visible and not display:none -PASS <div popover="">This content should be visible, if HTMLPopoverAttribute is disabled</div> should be stylable/visible and not display:none -PASS <div popover="" id="foo">This content should be visible, if HTMLPopoverAttribute is disabled</div> should be stylable/visible and not display:none -PASS The popover IDL attribute should not be present on Element -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/virtual/popover-hint-disabled/README.md b/third_party/blink/web_tests/virtual/popover-hint-disabled/README.md new file mode 100644 index 0000000..7d98127 --- /dev/null +++ b/third_party/blink/web_tests/virtual/popover-hint-disabled/README.md
@@ -0,0 +1,5 @@ +# Overview + +This suite runs a small subset of tests with `--enable-features=HTMLPopoverAttribute` +and `--disable-features=HTMLPopoverHint`, to make sure no popover=hint behavior is +inadvertently exposed when the feature is disabled.
diff --git a/third_party/blink/web_tests/virtual/popover-hint-disabled/popover-hint-disabled.html b/third_party/blink/web_tests/virtual/popover-hint-disabled/popover-hint-disabled.html new file mode 100644 index 0000000..88950768 --- /dev/null +++ b/third_party/blink/web_tests/virtual/popover-hint-disabled/popover-hint-disabled.html
@@ -0,0 +1,27 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<script src='../../resources/testharness.js'></script> +<script src="../../resources/testharnessreport.js"></script> + +<div popover=hint id=target>This should be a MANUAL popover, if HTMLPopoverAttribute is enabled and HTMLPopoverHint is disabled</div> + +<script> +const target = document.getElementById('target'); +test(() => { + assert_false(target.matches(':open'),"The :open pseudo class should be available and false"); + assert_true(target.matches(':closed'),"The :closed pseudo class should be available and true"); +},'popover=hint should still function as a popover'); + +test(() => { + assert_true(target.matches(':closed')); + target.showPopover(); // Shouldn't throw + assert_true(target.matches(':open')); + target.hidePopover(); + assert_true(target.matches(':closed')); +},`popover=hint should function as a manual popover`); + +test(() => { + assert_equals(target.popover,'manual','With HTMLPopoverHint disabled, popover=hint should be treated as a manual popover'); + assert_equals(target.getAttribute('popover'),'hint','The content attribute should still be "hint"'); +},`popover=hint should *not* be feature detected`); +</script>
diff --git a/third_party/blink/web_tests/wpt_internal/compute-pressure/losing-focus-suspends-data-delivery.https.window.js.ini b/third_party/blink/web_tests/wpt_internal/compute-pressure/losing-focus-suspends-data-delivery.https.window.js.ini new file mode 100644 index 0000000..9264d33 --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/compute-pressure/losing-focus-suspends-data-delivery.https.window.js.ini
@@ -0,0 +1,3 @@ +[losing-focus-suspends-data-delivery.https.window.html] + [Observer should not receive PressureRecord if page loses focus] + expected: FAIL
diff --git a/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/resources/transition-to-prerender.html b/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/resources/transition-to-prerender.html new file mode 100644 index 0000000..688318a --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/resources/transition-to-prerender.html
@@ -0,0 +1,54 @@ +<!DOCTYPE html> +<title>View transitions: prerender navigation helper</title> +<link rel="help" href="https://github.com/WICG/view-transitions"> +<link rel="author" href="mailto:vmpstr@chromium.org"> +<meta name="view-transition" content="same-origin"> +<script src="/speculation-rules/prerender/resources/utils.js"></script> +<style> +html { background: red; } +div { + width: 200px; + height: 200px; + background: red; + color: black; + position: absolute; + top: 40px; + right: 8px; + view-transition-name: target; +} + +::view-transition { + background: lightblue; +} + +::view-transition-group(root) { + visibility: hidden; + animation-duration: 500s; +} + +::view-transition-group(target) { + animation-play-state: paused; +} +::view-transition-new(target) { + animation: unset; + opacity: 1; +} +::view-transition-old(target) { + animation: unset; + opacity: 0; +} +</style> +<div id=target> + There should be a green square on the left side of the screen, + on a field of lightblue. There should be no red in the final state. +</div> + +<script> +if (document.prerendering) { + target.style.background = "green"; +} +const channel = new PrerenderChannel('prerender-channel'); +channel.postMessage('loaded!'); +</script> + +
diff --git a/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/transition-to-prerender-manual.html b/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/transition-to-prerender-manual.html new file mode 100644 index 0000000..1b5f38c --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/transition-to-prerender-manual.html
@@ -0,0 +1,57 @@ +<!DOCTYPE html> +<html class=reftest-wait> +<title>View transitions: prerender navigation</title> +<link rel="help" href="https://github.com/WICG/view-transitions"> +<link rel="author" href="mailto:vmpstr@chromium.org"> +<!-- TODO(crbug.com/1418681). This test should work automatically, + but doesn't due to the referenced bug. +<link rel="match" href="transition-to-prerender-ref.html"> +--> +<script src="/common/utils.js"></script> +<script src="/speculation-rules/prerender/resources/utils.js"></script> +<meta name="view-transition" content="same-origin"> + +<script src="/common/reftest-wait.js"></script> + +<style> +html { background: red; } +#target { + width: 200px; + height: 200px; + background: black; + color: white; + position: absolute; + top: 40px; + view-transition-name: target; +} +</style> + +<div id=target></div> + +<script> + +const uid = token(); + +function startTest() { + const old_url = "/transition-to-prerender-manual.html"; + const new_url = `/resources/transition-to-prerender.html?uid=${uid}`; + window.location.href = window.location.href.replace(old_url, new_url); +} + +async function waitForPrerender() { + const channel = new PrerenderChannel('prerender-channel', uid); + + const gotMessage = new Promise(resolve => { + channel.addEventListener('message', resolve) + }, { + once: true + }); + + startPrerendering(`resources/transition-to-prerender.html?uid=${uid}`); + await gotMessage; + startTest(); +} + +onload = waitForPrerender; +</script> +
diff --git a/third_party/crashpad/README.chromium b/third_party/crashpad/README.chromium index b795818..a85bf36 100644 --- a/third_party/crashpad/README.chromium +++ b/third_party/crashpad/README.chromium
@@ -2,7 +2,7 @@ Short Name: crashpad URL: https://crashpad.chromium.org/ Version: unknown -Revision: 3e8727238bae3c069bd71cfb3b2bbaa98b55f05b +Revision: 7a997fb25352a1c0cf99020ee82c4dfeae251eda License: Apache 2.0 License File: crashpad/LICENSE Security Critical: yes
diff --git a/third_party/crashpad/crashpad/handler/linux/cros_crash_report_exception_handler.cc b/third_party/crashpad/crashpad/handler/linux/cros_crash_report_exception_handler.cc index a3a6855..86142883 100644 --- a/third_party/crashpad/crashpad/handler/linux/cros_crash_report_exception_handler.cc +++ b/third_party/crashpad/crashpad/handler/linux/cros_crash_report_exception_handler.cc
@@ -17,6 +17,7 @@ #include <vector> #include "base/logging.h" +#include "base/strings/stringprintf.h" #include "client/settings.h" #include "handler/linux/capture_snapshot.h" #include "handler/minidump_to_upload_parameters.h" @@ -246,6 +247,16 @@ // crash_reporter needs to know the pid and uid of the crashing process. std::vector<std::string> argv({"/sbin/crash_reporter"}); + // Used to distinguish between non-fatal and fatal crashes. + const ExceptionSnapshot* const exception_snapshot = snapshot->Exception(); + if (exception_snapshot) { + // convert to int32, since crashpad uses -1 as a signal for non-fatal + // crashes. + argv.push_back(base::StringPrintf( + "--chrome_signal=%d", + static_cast<int32_t>(exception_snapshot->Exception()))); + } + argv.push_back("--chrome_memfd=" + std::to_string(file_writer.fd())); const pid_t pid = process_snapshot->ProcessID();
diff --git a/third_party/crashpad/crashpad/tools/BUILD.gn b/third_party/crashpad/crashpad/tools/BUILD.gn index 4c5d446b..3a042ed 100644 --- a/third_party/crashpad/crashpad/tools/BUILD.gn +++ b/third_party/crashpad/crashpad/tools/BUILD.gn
@@ -25,6 +25,22 @@ deps = [ "$mini_chromium_source_parent:base" ] } +crashpad_executable("dump_minidump_annotations") { + sources = [ "dump_minidump_annotations.cc" ] + + deps = [ + ":tool_support", + "../client", + "../snapshot", + "../util", + ] + + if (crashpad_is_win) { + cflags = + [ "/wd4201" ] # nonstandard extension used : nameless struct/union + } +} + if (!crashpad_is_ios) { crashpad_executable("crashpad_database_util") { sources = [ "crashpad_database_util.cc" ]
diff --git a/third_party/crashpad/crashpad/tools/dump_minidump_annotations.cc b/third_party/crashpad/crashpad/tools/dump_minidump_annotations.cc new file mode 100644 index 0000000..1c26c1b --- /dev/null +++ b/third_party/crashpad/crashpad/tools/dump_minidump_annotations.cc
@@ -0,0 +1,147 @@ +// Copyright 2023 The Crashpad Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include <getopt.h> + +#include "base/files/file_path.h" +#include "client/annotation.h" +#include "util/file/file_reader.h" +#include "snapshot/minidump/process_snapshot_minidump.h" +#include "tools/tool_support.h" + +namespace crashpad { +namespace { + +void Usage(const base::FilePath& me) { + // clang-format off + fprintf(stderr, +"Usage: %" PRFilePath " [OPTION]... PATH\n" +"Dump annotations from minidumps.\n" +"\n" +" --help display this help and exit\n" +" --version output version information and exit\n", + me.value().c_str()); + // clang-format on + ToolSupport::UsageTail(me); +} + +struct Options { + const char* minidump; +}; + +int DumpMinidumpAnnotationsMain(int argc, char* argv[]) { + const base::FilePath argv0( + ToolSupport::CommandLineArgumentToFilePathStringType(argv[0])); + const base::FilePath me(argv0.BaseName()); + + enum OptionFlags { + // Long options without short equivalents. + kOptionLastChar = 255, + kOptionMinidump, + + // Standard options. + kOptionHelp = -2, + kOptionVersion = -3, + }; + + static constexpr option long_options[] = { + {"minidump", required_argument, nullptr, kOptionMinidump}, + {"help", no_argument, nullptr, kOptionHelp}, + {"version", no_argument, nullptr, kOptionVersion}, + {nullptr, 0, nullptr, 0}, + }; + + Options options = {}; + + int opt; + while ((opt = getopt_long(argc, argv, "", long_options, nullptr)) != -1) { + switch (opt) { + case kOptionMinidump: { + options.minidump = optarg; + break; + } + case kOptionHelp: { + Usage(me); + return EXIT_SUCCESS; + } + case kOptionVersion: { + ToolSupport::Version(me); + return EXIT_SUCCESS; + } + default: { + ToolSupport::UsageHint(me, nullptr); + return EXIT_FAILURE; + } + } + } + argc -= optind; + argv += optind; + + if (!options.minidump) { + ToolSupport::UsageHint(me, "--minidump is required"); + return EXIT_FAILURE; + } + + FileReader reader; + if (!reader.Open(base::FilePath( + ToolSupport::CommandLineArgumentToFilePathStringType( + options.minidump)))) { + return EXIT_FAILURE; + } + + ProcessSnapshotMinidump snapshot; + if (!snapshot.Initialize(&reader)) { + return EXIT_FAILURE; + } + + for (const ModuleSnapshot* module : snapshot.Modules()) { + printf("Module: %s\n", module->Name().c_str()); + printf(" Simple Annotations\n"); + for (const auto& kv : module->AnnotationsSimpleMap()) { + printf(" simple_annotations[\"%s\"] = %s\n", + kv.first.c_str(), kv.second.c_str()); + } + + printf(" Vectored Annotations\n"); + int index = 0; + for (const std::string& annotation : module->AnnotationsVector()) { + printf(" vectored_annotations[%d] = %s\n", index, annotation.c_str()); + index++; + } + + printf(" Annotation Objects\n"); + for (const AnnotationSnapshot& annotation : module->AnnotationObjects()) { + printf(" annotation_objects[\"%s\"] = ", annotation.name.c_str()); + if (annotation.type != static_cast<uint16_t>(Annotation::Type::kString)) { + + printf("<non-string value, not printing>\n"); + continue; + } + + std::string value(reinterpret_cast<const char*>(annotation.value.data()), + annotation.value.size()); + + printf("%s\n", value.c_str()); + } + } + + return EXIT_SUCCESS; +} + +} // namespace +} // namespace crashpad + +int main(int argc, char* argv[]) { + return crashpad::DumpMinidumpAnnotationsMain(argc, argv); +}
diff --git a/third_party/wpt_tools/PRESUBMIT.py b/third_party/wpt_tools/PRESUBMIT.py index 87ca0efa..0eb104d6 100644 --- a/third_party/wpt_tools/PRESUBMIT.py +++ b/third_party/wpt_tools/PRESUBMIT.py
@@ -10,6 +10,10 @@ USE_PYTHON3 = True +import pathlib +import textwrap + + def _TestWPTLint(input_api, output_api): # We test 'wpt lint' by deferring to the web_tests/external presubmit test, # which runs 'wpt lint' against web_tests/external/wpt. @@ -55,10 +59,47 @@ return [] +def _TestWPTRolled(input_api, output_api): + """Warn developers making manual changes to `wpt_tools/`.""" + subject, *_ = input_api.change.DescriptionText().splitlines() + if input_api.re.search(r'\broll wpt tooling\b', subject, + input_api.re.IGNORECASE): + return [] + + include_file = input_api.os_path.join(input_api.PresubmitLocalPath(), + 'WPTIncludeList') + rolled_files = {pathlib.PurePosixPath(line) + for line in input_api.ReadFile(include_file).splitlines()} + wpt_dir = pathlib.Path(input_api.PresubmitLocalPath()) / 'wpt' + + def exclude_unrolled_files(affected_file): + try: + path_from_wpt = pathlib.Path( + affected_file.AbsoluteLocalPath()).relative_to(wpt_dir) + return pathlib.PurePosixPath(path_from_wpt.as_posix()) in rolled_files + except ValueError: + # Exclude file relative to `wpt_tools` but not to `wpt_tools/wpt`. + return False + + if input_api.AffectedFiles(file_filter=exclude_unrolled_files): + message = textwrap.dedent( + """\ + Thanks for your patch to `//third_party/wpt_tools/wpt`. This directory is + semiregularly overwritten by rolls from the upstream repo: + https://github.com/web-platform-tests/wpt + + Please submit your change upstream as a pull request instead, then run + `//third_party/wpt_tools/roll_wpt.py` to pick up the change. + """) + return [output_api.PresubmitPromptWarning(message)] + return [] + + def CheckChangeOnUpload(input_api, output_api): results = [] results += _TestWPTLint(input_api, output_api) results += _TestWPTManifest(input_api, output_api) + results += _TestWPTRolled(input_api, output_api) return results @@ -66,4 +107,5 @@ results = [] results += _TestWPTLint(input_api, output_api) results += _TestWPTManifest(input_api, output_api) + results += _TestWPTRolled(input_api, output_api) return results
diff --git a/third_party/zlib/contrib/optimizations/inffast_chunk.c b/third_party/zlib/contrib/optimizations/inffast_chunk.c index 5b09487..a38e14d 100644 --- a/third_party/zlib/contrib/optimizations/inffast_chunk.c +++ b/third_party/zlib/contrib/optimizations/inffast_chunk.c
@@ -1,5 +1,6 @@ /* inffast_chunk.c -- fast decoding * Copyright (C) 1995-2017 Mark Adler + * Copyright 2023 The Chromium Authors * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -24,8 +25,8 @@ Entry assumptions: state->mode == LEN - strm->avail_in >= INFLATE_FAST_MIN_INPUT (6 or 8 bytes) - strm->avail_out >= INFLATE_FAST_MIN_OUTPUT (258 bytes) + strm->avail_in >= INFLATE_FAST_MIN_INPUT (6 or 8 bytes + 7 bytes) + strm->avail_out >= INFLATE_FAST_MIN_OUTPUT (258 bytes + 2 bytes) start >= strm->avail_out state->bits < 8 (state->hold >> state->bits) == 0 @@ -42,7 +43,7 @@ Notes: - INFLATE_FAST_MIN_INPUT: 6 or 8 bytes + INFLATE_FAST_MIN_INPUT: 6 or 8 bytes + 7 bytes - The maximum input bits used by a length/distance pair is 15 bits for the length code, 5 bits for the length extra, 15 bits for the distance code, @@ -64,11 +65,11 @@ (state->hold >> state->bits) == 0 - INFLATE_FAST_MIN_OUTPUT: 258 bytes + INFLATE_FAST_MIN_OUTPUT: 258 bytes + 2 bytes for literals = 260 bytes - The maximum bytes that a single length/distance pair can output is 258 bytes, which is the maximum length that can be coded. inflate_fast() - requires strm->avail_out >= 258 for each loop to avoid checking for + requires strm->avail_out >= 260 for each loop to avoid checking for available output space while decoding. */ void ZLIB_INTERNAL inflate_fast_chunk_(strm, start) @@ -124,22 +125,50 @@ lmask = (1U << state->lenbits) - 1; dmask = (1U << state->distbits) - 1; +#ifdef INFLATE_CHUNK_READ_64LE +#define REFILL() do { \ + Assert(bits < 64, "### Too many bits in inflate_fast."); \ + hold |= read64le(in) << bits; \ + in += 7; \ + in -= bits >> 3; \ + bits |= 56; \ + } while (0) +#endif + /* decode literals and length/distances until end-of-block or not enough input data or output space */ do { - if (bits < 15) { #ifdef INFLATE_CHUNK_READ_64LE - hold |= read64le(in) << bits; - in += 6; - bits += 48; + REFILL(); #else + if (bits < 15) { hold += (unsigned long)(*in++) << bits; bits += 8; hold += (unsigned long)(*in++) << bits; bits += 8; -#endif } +#endif here = lcode + (hold & lmask); +#ifdef INFLATE_CHUNK_READ_64LE + if (here->op == 0) { /* literal */ + Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here->val)); + *out++ = (unsigned char)(here->val); + hold >>= here->bits; + bits -= here->bits; + here = lcode + (hold & lmask); + if (here->op == 0) { /* literal */ + Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ? + "inflate: 2nd literal '%c'\n" : + "inflate: 2nd literal 0x%02x\n", here->val)); + *out++ = (unsigned char)(here->val); + hold >>= here->bits; + bits -= here->bits; + here = lcode + (hold & lmask); + } + } +#endif dolen: op = (unsigned)(here->bits); hold >>= op; @@ -155,33 +184,25 @@ len = (unsigned)(here->val); op &= 15; /* number of extra bits */ if (op) { +#ifndef INFLATE_CHUNK_READ_64LE if (bits < op) { -#ifdef INFLATE_CHUNK_READ_64LE - hold |= read64le(in) << bits; - in += 6; - bits += 48; -#else hold += (unsigned long)(*in++) << bits; bits += 8; -#endif } +#endif len += (unsigned)hold & ((1U << op) - 1); hold >>= op; bits -= op; } Tracevv((stderr, "inflate: length %u\n", len)); +#ifndef INFLATE_CHUNK_READ_64LE if (bits < 15) { -#ifdef INFLATE_CHUNK_READ_64LE - hold |= read64le(in) << bits; - in += 6; - bits += 48; -#else hold += (unsigned long)(*in++) << bits; bits += 8; hold += (unsigned long)(*in++) << bits; bits += 8; -#endif } +#endif here = dcode + (hold & dmask); dodist: op = (unsigned)(here->bits); @@ -191,11 +212,11 @@ if (op & 16) { /* distance base */ dist = (unsigned)(here->val); op &= 15; /* number of extra bits */ + /* we have two fast-path loads: 10+10 + 15+5 + 15 = 55, + but we may need to refill here in the worst case */ if (bits < op) { #ifdef INFLATE_CHUNK_READ_64LE - hold |= read64le(in) << bits; - in += 6; - bits += 48; + REFILL(); #else hold += (unsigned long)(*in++) << bits; bits += 8;
diff --git a/third_party/zlib/contrib/optimizations/inffast_chunk.h b/third_party/zlib/contrib/optimizations/inffast_chunk.h index 39c771b8..cc861bd 100644 --- a/third_party/zlib/contrib/optimizations/inffast_chunk.h +++ b/third_party/zlib/contrib/optimizations/inffast_chunk.h
@@ -1,6 +1,7 @@ /* inffast_chunk.h -- header to use inffast_chunk.c * Copyright (C) 1995-2003, 2010 Mark Adler * Copyright (C) 2017 ARM, Inc. + * Copyright 2023 The Chromium Authors * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -11,16 +12,31 @@ #include "inffast.h" -/* INFLATE_FAST_MIN_INPUT: the minimum number of input bytes needed so that - we can safely call inflate_fast() with only one up-front bounds check. One +/* INFLATE_FAST_MIN_INPUT: + The minimum number of input bytes needed so that we can safely call + inflate_fast() with only one up-front bounds check. One length/distance code pair (15 bits for the length code, 5 bits for length extra, 15 bits for the distance code, 13 bits for distance extra) requires - reading up to 48 input bits (6 bytes). The wide input data reading option - requires a little endian machine, and reads 64 input bits (8 bytes). + reading up to 48 input bits. Additionally, in the same iteraction, we may + decode two literals from the root-table (requiring MIN_OUTPUT = 258 + 2). + + Each root-table entry is up to 10 bits, for a total of 68 input bits each + iteraction. + + The refill variant reads 8 bytes from the buffer at a time, and advances + the input pointer by up to 7 bytes, ensuring there are at least 56-bits + available in the bit-buffer. The technique was documented by Fabian Giesen + on his blog as variant 4 in the article 'Reading bits in far too many ways': + https://fgiesen.wordpress.com/2018/02/20/ + + In the worst case, we may refill twice in the same iteraction, requiring + MIN_INPUT = 8 + 7. */ #ifdef INFLATE_CHUNK_READ_64LE #undef INFLATE_FAST_MIN_INPUT -#define INFLATE_FAST_MIN_INPUT 8 +#define INFLATE_FAST_MIN_INPUT 15 +#undef INFLATE_FAST_MIN_OUTPUT +#define INFLATE_FAST_MIN_OUTPUT 260 #endif void ZLIB_INTERNAL inflate_fast_chunk_ OF((z_streamp strm, unsigned start));
diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py index 4fcaaab..d058a1a 100755 --- a/tools/clang/scripts/update.py +++ b/tools/clang/scripts/update.py
@@ -35,7 +35,7 @@ # https://chromium.googlesource.com/chromium/src/+/main/docs/updating_clang.md # Reverting problematic clang rolls is safe, though. # This is the output of `git describe` and is usable as a commit-ish. -CLANG_REVISION = 'llvmorg-17-init-2387-g68e81d7e' +CLANG_REVISION = 'llvmorg-17-init-3170-g6e30dffe' CLANG_SUB_REVISION = 1 PACKAGE_VERSION = '%s-%s' % (CLANG_REVISION, CLANG_SUB_REVISION)
diff --git a/tools/fuchsia/local-sdk.py b/tools/fuchsia/local-sdk.py index 57b74965..c09ab58 100755 --- a/tools/fuchsia/local-sdk.py +++ b/tools/fuchsia/local-sdk.py
@@ -4,6 +4,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import filecmp import hashlib import json import os @@ -38,33 +39,28 @@ Run('scripts/fx', 'build', 'sdk', 'build/images') -def _CopyFilesIntoExistingDirectory(src, dst): - for entry in os.listdir(src): - src_path = os.path.join(src, entry) - dst_path = os.path.join(dst, entry) - if os.path.isdir(src_path): - if not os.path.exists(dst_path): - os.mkdir(dst_path) - _CopyFilesIntoExistingDirectory(src_path, dst_path) - else: - shutil.copy(src_path, dst_path) +def Copy(src, dst): + if os.path.exists(dst) and filecmp.cmp(src, dst, shallow=False): + return + shutil.copy2(src, dst) def main(args): - if len(args) == 0 or len(args) > 2 or not os.path.isdir(args[0]): + if len(args) == 0 or not os.path.isdir(args[0]): print("""usage: %s <path_to_fuchsia_tree> [architecture]""" % SELF_FILE) return 1 - target_archs = [] - if len(args) > 1: - arch = args[1] - if arch not in ['x64', 'arm64']: - print('Unknown architecture: ' + arch) - print('Must be "x64" or "arm64".') - return 1 - target_archs = [arch] + ALL_ARCHS = set(['x64', 'arm64']) + if len(args) == 1: + target_archs = ALL_ARCHS else: - target_archs = ['x64', 'arm64'] + target_archs = set(args[1:]) + unknown_archs = target_archs - ALL_ARCHS + if unknown_archs: + print( + f'Unknown architectures: {unknown_archs}. Known architectures: {ALL_ARCHS}' + ) + return 1 # Nuke the SDK from DEPS, put our just-built one there, and set a fake .hash # file. This means that on next gclient runhooks, we'll restore to the @@ -99,7 +95,10 @@ Run('scripts/sdk/gn/generate.py', '--archive', sdk_tar_path, '--output', sdk_gn_dir) - _CopyFilesIntoExistingDirectory(sdk_gn_dir, sdk_output_dir) + shutil.copytree(sdk_gn_dir, + sdk_output_dir, + copy_function=Copy, + dirs_exist_ok=True) # Merge the manifests. manifest_path = os.path.join(sdk_output_dir, 'meta', 'manifest.json')
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 68248fb..7b75595 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -31211,6 +31211,7 @@ <int value="16" label="Video encoding error"/> <int value="17" label="Projector transcription error"/> <int value="18" label="Low DriveFS free space quota"/> + <int value="19" label="Video encoder does not support reconfiguration"/> </enum> <enum name="EnhancedBookmarkViewMode"> @@ -42348,6 +42349,7 @@ <int value="4477" label="FencedFrameConfigAttribute"/> <int value="4478" label="URLSearchParams_Has_Delete_MultipleArguments"/> <int value="4479" label="PaymentHandlerMinimalHeaderUX"/> + <int value="4480" label="PopoverTypeHint"/> </enum> <enum name="FeaturePolicyAllowlistType"> @@ -58558,6 +58560,7 @@ <int value="-1811949013" label="SameSiteByDefaultCookies:disabled"/> <int value="-1811394154" label="disable-webrtc-hw-vp8-encoding"/> <int value="-1810891359" label="SendTabToSelfManageDevicesLink:disabled"/> + <int value="-1810354047" label="GifRecording:enabled"/> <int value="-1810294310" label="AndroidPaymentApps:enabled"/> <int value="-1809969509" label="FilesSinglePartitionFormat:disabled"/> <int value="-1809891158" label="WebAuthenticationCable:enabled"/> @@ -58680,7 +58683,6 @@ <int value="-1731997767" label="SharingHubDesktopAppMenu:enabled"/> <int value="-1731267886" label="AutofillEnableStickyPaymentsBubble:enabled"/> <int value="-1731149013" label="AndroidMessagesIntegration:enabled"/> - <int value="-1730755478" label="ClosedTabCache:disabled"/> <int value="-1729926412" label="enable-webusb-notifications"/> <int value="-1729808721" label="SubresourceRedirect:enabled"/> <int value="-1728605240" label="UseXpsForPrintingFromPdf:enabled"/> @@ -58815,6 +58817,8 @@ <int value="-1646653199" label="WallpaperGooglePhotosIntegration:enabled"/> <int value="-1646196271" label="WebRtcStatsReportIdl:disabled"/> <int value="-1646016597" label="IsolatePrerenders:disabled"/> + <int value="-1646002522" + label="ChromeOSAmbientModeManagedScreensaver:enabled"/> <int value="-1645071473" label="ChromeColors:disabled"/> <int value="-1644308778" label="WASAPIRawAudioCapture:disabled"/> <int value="-1643933608" label="SyncAutofillWalletOfferData:enabled"/> @@ -59158,6 +59162,7 @@ <int value="-1466206556" label="ArcDocumentsProviderUnknownSize:enabled"/> <int value="-1466100014" label="EchePhoneHubPermissionsOnboarding:disabled"/> <int value="-1465172796" label="CCTModule:disabled"/> + <int value="-1465138299" label="GifRecording:disabled"/> <int value="-1464860971" label="BluetoothCoredump:enabled"/> <int value="-1464832541" label="EnableFuzzyAppSearch:disabled"/> <int value="-1463489219" label="OfflinePagesCTSuppressNotifications:enabled"/> @@ -62211,6 +62216,8 @@ <int value="255806443" label="GetDisplayMediaSet:disabled"/> <int value="256753680" label="ChromeKioskEnableLacros:disabled"/> <int value="257206347" label="GuestOSGenericInstaller:disabled"/> + <int value="257348975" + label="ChromeOSAmbientModeManagedScreensaver:disabled"/> <int value="258621334" label="HappinessTrackingSurveysForDesktopDemo:disabled"/> <int value="259021228" label="OffMainThreadFetch:disabled"/> @@ -63632,7 +63639,6 @@ <int value="1065451331" label="NtpRealboxPedals:disabled"/> <int value="1065481614" label="SystemEmojiPickerGIFSupport:disabled"/> <int value="1065547630" label="EnableInputNoiseCancellationUi:disabled"/> - <int value="1065553214" label="ClosedTabCache:enabled"/> <int value="1067618884" label="enable-experimental-input-view-features"/> <int value="1067990299" label="enable-ui-devtools"/> <int value="1069325321" label="CrostiniGpuSupport:enabled"/>
diff --git a/tools/metrics/histograms/histograms_index.txt b/tools/metrics/histograms/histograms_index.txt index ec3798c..d48203b 100644 --- a/tools/metrics/histograms/histograms_index.txt +++ b/tools/metrics/histograms/histograms_index.txt
@@ -29,6 +29,7 @@ tools/metrics/histograms/metadata/cookie/histograms.xml tools/metrics/histograms/metadata/cras/histograms.xml tools/metrics/histograms/metadata/cros/histograms.xml +tools/metrics/histograms/metadata/cros_audio/histograms.xml tools/metrics/histograms/metadata/cros_ml/histograms.xml tools/metrics/histograms/metadata/cross_device/histograms.xml tools/metrics/histograms/metadata/crostini/histograms.xml
diff --git a/tools/metrics/histograms/metadata/autofill/histograms.xml b/tools/metrics/histograms/metadata/autofill/histograms.xml index fc0b76fb..b236042 100644 --- a/tools/metrics/histograms/metadata/autofill/histograms.xml +++ b/tools/metrics/histograms/metadata/autofill/histograms.xml
@@ -2431,7 +2431,7 @@ </summary> </histogram> -<histogram name="Autofill.Leipzig.FillingAssistanceOrigin" +<histogram name="Autofill.Leipzig.FillingAssistanceCategory" enum="AutofillCategoryResolvedFillingAssistance" expires_after="2023-12-12"> <owner>koerber@chromium.org</owner> <owner>fleimgruber@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/blink/histograms.xml b/tools/metrics/histograms/metadata/blink/histograms.xml index 93540b5..e9a7426 100644 --- a/tools/metrics/histograms/metadata/blink/histograms.xml +++ b/tools/metrics/histograms/metadata/blink/histograms.xml
@@ -164,6 +164,36 @@ </summary> </histogram> +<histogram name="Blink.Canvas.2DLayerBridge.Compression.DecompressionTime" + units="ms" expires_after="2023-08-08"> + <owner>lizeb@chromium.org</owner> + <owner>fserb@chromium.org</owner> + <summary> + When a compressed hibernated 2D canvas snapshot is decompressed, duration in + ms. Reported each time a canvas snapshot is decompressed. + </summary> +</histogram> + +<histogram name="Blink.Canvas.2DLayerBridge.Compression.Ratio" units="%" + expires_after="2023-08-08"> + <owner>lizeb@chromium.org</owner> + <owner>fserb@chromium.org</owner> + <summary> + When a hibernated 2D canvas snapshot is compressed, the compression ratio + achieved. Reported each time a canvas snapshot is compressed. + </summary> +</histogram> + +<histogram name="Blink.Canvas.2DLayerBridge.Compression.SnapshotSizeKb" + units="KB" expires_after="2023-08-08"> + <owner>lizeb@chromium.org</owner> + <owner>fserb@chromium.org</owner> + <summary> + When a hibernated 2D canvas snapshot is compressed, the size before + compression. Reported each time a canvas snapshot is compressed. + </summary> +</histogram> + <histogram name="Blink.Canvas.2DLayerBridge.WillReadFrequently" enum="BooleanWillReadFrequently" expires_after="2024-04-01"> <owner>aaronhk@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/chromeos_settings/histograms.xml b/tools/metrics/histograms/metadata/chromeos_settings/histograms.xml index 35893e4..80b4b3d2c 100644 --- a/tools/metrics/histograms/metadata/chromeos_settings/histograms.xml +++ b/tools/metrics/histograms/metadata/chromeos_settings/histograms.xml
@@ -75,26 +75,6 @@ </summary> </histogram> -<histogram name="ChromeOS.Settings.Device.Audio.InputMuteStateChange" - enum="AudioMuteButtonAction" expires_after="2024-02-14"> - <owner>gavinwill@chromium.org</owner> - <owner>cros-peripherals@google.com</owner> - <summary> - Recorded when the user changes the input audio mute state by pressing the - mute button on the Audio Settings page. - </summary> -</histogram> - -<histogram name="ChromeOS.Settings.Device.Audio.OutputMuteStateChange" - enum="AudioMuteButtonAction" expires_after="2024-02-14"> - <owner>gavinwill@chromium.org</owner> - <owner>cros-peripherals@google.com</owner> - <summary> - Recorded when the user changes the output audio mute state by pressing the - mute button on the Audio Settings page. - </summary> -</histogram> - <histogram name="ChromeOS.Settings.Device.KeyboardAutoRepeatEnabled" enum="BooleanEnabled" expires_after="2023-11-01"> <owner>ckincaid@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/content/histograms.xml b/tools/metrics/histograms/metadata/content/histograms.xml index 3f0641222..b36e3a5 100644 --- a/tools/metrics/histograms/metadata/content/histograms.xml +++ b/tools/metrics/histograms/metadata/content/histograms.xml
@@ -940,7 +940,7 @@ </histogram> <histogram name="ContentSuggestions.Feed.ContentDuplication.Position{Index}" - enum="Boolean" expires_after="2023-03-01"> + enum="Boolean" expires_after="2023-09-01"> <obsolete> Deprecated in 11/2022. Replaced by ContentDuplication2 metrics. </obsolete> @@ -958,7 +958,7 @@ </histogram> <histogram name="ContentSuggestions.Feed.ContentDuplication.{Range}" units="%" - expires_after="2023-03-01"> + expires_after="2023-09-01"> <obsolete> Deprecated in 11/2022. Replaced by ContentDuplication2 metrics. </obsolete> @@ -976,7 +976,7 @@ </histogram> <histogram name="ContentSuggestions.Feed.ContentDuplication2.Position{Index}" - enum="Boolean" expires_after="2023-03-01"> + enum="Boolean" expires_after="2023-09-01"> <owner>jianli@chromium.org</owner> <owner>feed@chromium.org</owner> <summary> @@ -993,7 +993,7 @@ </histogram> <histogram name="ContentSuggestions.Feed.ContentDuplication2.{Range}" units="%" - expires_after="2023-03-01"> + expires_after="2023-09-01"> <owner>jianli@chromium.org</owner> <owner>feed@chromium.org</owner> <summary> @@ -1227,7 +1227,7 @@ </histogram> <histogram name="ContentSuggestions.Feed.NoticeCardFulfilled2" enum="Boolean" - expires_after="2023-03-01"> + expires_after="2023-09-01"> <owner>vincb@google.com</owner> <owner>feed@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/cros_audio/OWNERS b/tools/metrics/histograms/metadata/cros_audio/OWNERS new file mode 100644 index 0000000..2c65f4fc --- /dev/null +++ b/tools/metrics/histograms/metadata/cros_audio/OWNERS
@@ -0,0 +1,5 @@ +per-file OWNERS=file://tools/metrics/histograms/metadata/METRIC_REVIEWER_OWNERS + +# Prefer sending CLs to the owners listed below. +# Use chromium-metrics-reviews@google.com as a backup. +gavinwill@chromium.org \ No newline at end of file
diff --git a/tools/metrics/histograms/metadata/cros_audio/histograms.xml b/tools/metrics/histograms/metadata/cros_audio/histograms.xml new file mode 100644 index 0000000..df77163 --- /dev/null +++ b/tools/metrics/histograms/metadata/cros_audio/histograms.xml
@@ -0,0 +1,47 @@ +<!-- +Copyright 2023 The Chromium Authors +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> + +<!-- +This file is used to generate a comprehensive list of histograms for +functionality in CrosAudioConfig. + +For best practices on writing histogram descriptions, see +https://chromium.googlesource.com/chromium/src.git/+/HEAD/tools/metrics/histograms/README.md + +Prefer owners from the OWNERS file in this directory. If you need a metrics +reviewer, please send CLs to chromium-metrics-reviews@google.com rather than to +specific individuals. These CLs will be automatically reassigned to a reviewer +within about 5 minutes. This approach helps the metrics team to load-balance +incoming reviews. Googlers can read more about this at go/gwsq-gerrit. +--> + +<histogram-configuration> + +<histograms> + +<histogram name="ChromeOS.CrosAudioConfig.InputMuteStateChange" + enum="AudioMuteButtonAction" expires_after="2024-02-14"> + <owner>gavinwill@chromium.org</owner> + <owner>cros-peripherals@google.com</owner> + <summary> + Recorded when the user changes the input audio mute state from a WebUI, such + as the OS Audio Settings page. + </summary> +</histogram> + +<histogram name="ChromeOS.CrosAudioConfig.OutputMuteStateChange" + enum="AudioMuteButtonAction" expires_after="2024-02-14"> + <owner>gavinwill@chromium.org</owner> + <owner>cros-peripherals@google.com</owner> + <summary> + Recorded when the user changes the output audio mute state from a WebUI, + such as the OS Audio Settings page. + </summary> +</histogram> + +</histograms> + +</histogram-configuration>
diff --git a/tools/metrics/histograms/metadata/memory/histograms.xml b/tools/metrics/histograms/metadata/memory/histograms.xml index c5f9c6f01..9ee34631 100644 --- a/tools/metrics/histograms/metadata/memory/histograms.xml +++ b/tools/metrics/histograms/metadata/memory/histograms.xml
@@ -45,6 +45,22 @@ <variant name=".Utility" summary="a Utility process"/> </variants> +<variants name="UtilityProcessType"> + <variant name="AudioService"> + <owner>olka@chromium.org</owner> + <owner>fhernqvist@google.com</owner> + <owner>tguilbert@chromium.org</owner> + <owner>webrtc-audio-uma@google.com</owner> + </variant> + <variant name="PaintPreviewCompositor"> + <owner>ckitagawa@chromium.org</owner> + <owner>fredmello@chromium.org</owner> + </variant> + <variant name="Utility"> + <owner>jam@chromium.org</owner> + </variant> +</variants> + <histogram name="HeapProfiling.AndroidStackUnwinder" enum="AndroidStackUnwinder" expires_after="2023-07-09"> <owner>joenotcharles@chromium.org</owner> @@ -178,85 +194,6 @@ </summary> </histogram> -<histogram name="Memory.AudioService.PrivateMemoryFootprint" units="MB" - expires_after="2023-07-16"> - <owner>olka@chromium.org</owner> - <owner>fhernqvist@google.com</owner> - <owner>tguilbert@chromium.org</owner> - <owner>webrtc-audio-uma@google.com</owner> - <summary> - A rough estimate of the private memory footprint of the audio service - process. - - Recorded at Poisson sampled time intervals with a mean of 5 minutes on - Android and 30 minutes on other platforms. - - This memory footprint metric cannot be compared across platforms because - each platform relies on platform-level APIs for accounting. As such, though - this attempts to measure private memory footprint as best as possible, it - does not measure the same thing on each platform. We have not found a good - way to compare any system level memory metric across platforms due to the - different nature of memory management on each platform. - </summary> -</histogram> - -<histogram name="Memory.AudioService.PrivateSwapFootprint" units="MB" - expires_after="2023-05-14"> - <owner>olka@chromium.org</owner> - <owner>guidou@chromium.org</owner> - <owner>fhernqvist@google.com</owner> - <owner>tguilbert@chromium.org</owner> - <owner>webrtc-audio-uma@google.com</owner> - <summary> - An amount of private memory of the audio service process placed in swap - (VmSwap). - - Recorded at Poisson sampled time intervals with a mean of 5 minutes on - Android and 30 minutes on other platforms. - </summary> -</histogram> - -<histogram name="Memory.AudioService.ResidentSet" units="MiB" - expires_after="never"> -<!-- expires-never: Generic system health metric used to diagnose various performance issues. --> - - <owner>fdoray@chromium.org</owner> - <owner>webrtc-audio-uma@google.com</owner> - <summary> - The size of the resident memory in a audio service process. This is - influenced by factors we control (e.g. memory that is not accessed can be - swapped) and factors we don't control (e.g. an unrelated process using a lot - of memory can force memory in our process to be swapped). Recorded once on - Windows/Linux/ChromeOS/Android. - - Recorded at Poisson sampled time intervals with a mean of 5 minutes on - Android and 30 minutes on other platforms. - - This resident memory metric cannot be compared across platforms because each - platform relies on platform-level APIs for accounting. As such, though this - attempts to measure private memory footprint as best as possible, it does - not measure the same thing on each platform. We have not found a good way to - compare any system level memory metric across platforms due to the different - nature of memory management on each platform. - </summary> -</histogram> - -<histogram name="Memory.AudioService.SharedMemoryFootprint" units="MB" - expires_after="2023-07-16"> - <owner>olka@chromium.org</owner> - <owner>guidou@chromium.org</owner> - <owner>fhernqvist@google.com</owner> - <owner>tguilbert@chromium.org</owner> - <owner>webrtc-audio-uma@google.com</owner> - <summary> - A rough estimate of the shared memory footprint of the audio service - process. - - Recorded at Poisson sampled time intervals with a mean of 5 minutes on - Android and 30 minutes on other platforms. - </summary> -</histogram> - <histogram name="Memory.BackingStore" units="units" expires_after="M85"> <owner>hajimehoshi@chromium.org</owner> <owner>kenjibaheux@google.com</owner> @@ -1763,75 +1700,6 @@ </summary> </histogram> -<histogram name="Memory.PaintPreviewCompositor.PrivateMemoryFootprint" - units="MB" expires_after="2023-05-27"> - <owner>ckitagawa@chromium.org</owner> - <owner>fredmello@chromium.org</owner> - <summary> - A rough estimate of the private memory footprint of the paint preview - compositor process. - - Recorded at Poisson sampled time intervals with a mean of 5 minutes on - Android and 30 minutes on other platforms. - - This memory footprint metric cannot be compared across platforms because - each platform relies on platform-level APIs for accounting. As such, though - this attempts to measure private memory footprint as best as possible, it - does not measure the same thing on each platform. We have not found a good - way to compare any system level memory metric across platforms due to the - different nature of memory management on each platform. - </summary> -</histogram> - -<histogram name="Memory.PaintPreviewCompositor.PrivateSwapFootprint" units="MB" - expires_after="2023-05-27"> - <owner>ckitagawa@chromium.org</owner> - <owner>fredmello@chromium.org</owner> - <summary> - An amount of private memory of the paint preview compositor process placed - in swap (VmSwap). - - Recorded at Poisson sampled time intervals with a mean of 5 minutes on - Android and 30 minutes on other platforms. - </summary> -</histogram> - -<histogram name="Memory.PaintPreviewCompositor.ResidentSet" units="MiB" - expires_after="2023-05-27"> - <owner>ckitagawa@chromium.org</owner> - <owner>fredmello@chromium.org</owner> - <summary> - The size of the resident memory in a paint preview compositor process. This - is influenced by factors we control (e.g. memory that is not accessed can be - swapped) and factors we don't control (e.g. an unrelated process using a lot - of memory can force memory in our process to be swapped). Recorded once on - Windows/Linux/ChromeOS/Android. - - Recorded at Poisson sampled time intervals with a mean of 5 minutes on - Android and 30 minutes on other platforms. - - This resident memory metric cannot be compared across platforms because each - platform relies on platform-level APIs for accounting. As such, though this - attempts to measure private memory footprint as best as possible, it does - not measure the same thing on each platform. We have not found a good way to - compare any system level memory metric across platforms due to the different - nature of memory management on each platform. - </summary> -</histogram> - -<histogram name="Memory.PaintPreviewCompositor.SharedMemoryFootprint" - units="MB" expires_after="2023-05-27"> - <owner>ckitagawa@chromium.org</owner> - <owner>fredmello@chromium.org</owner> - <summary> - A rough estimate of the shared memory footprint of the paint preview - compositor process. - - Recorded at Poisson sampled time intervals with a mean of 5 minutes on - Android and 30 minutes on other platforms. - </summary> -</histogram> - <histogram name="Memory.ParkableImage.DiskIsUsable.5min" enum="BooleanYesNo" expires_after="2022-12-25"> <owner>thiabaud@google.com</owner> @@ -2805,79 +2673,6 @@ </summary> </histogram> -<histogram name="Memory.Utility.PrivateMemoryFootprint" units="MB" - expires_after="never"> -<!-- expires-never: useful diagnostic metric for changes in - Memory.Total.PrivateMemoryFootprint, which never expires. --> - - <owner>jam@chromium.org</owner> - <summary> - A rough estimate of the private memory footprint of the utility process. - - Recorded at Poisson sampled time intervals with a mean of 5 minutes on - Android and 30 minutes on other platforms. - - This memory footprint metric cannot be compared across platforms because - each platform relies on platform-level APIs for accounting. As such, though - this attempts to measure private memory footprint as best as possible, it - does not measure the same thing on each platform. We have not found a good - way to compare any system level memory metric across platforms due to the - different nature of memory management on each platform. - </summary> -</histogram> - -<histogram name="Memory.Utility.PrivateSwapFootprint" units="MB" - expires_after="2023-03-12"> - <owner>jam@chromium.org</owner> - <summary> - An amount of private memory of the utility process placed in swap (VmSwap). - Available on Android, Linux and ChromeOS. - - Recorded at Poisson sampled time intervals with a mean of 5 minutes on - Android and 30 minutes on other platforms. - - Note: Histogram data may be missing for mid-2020 due to expiry. - </summary> -</histogram> - -<histogram name="Memory.Utility.ResidentSet" units="MiB" expires_after="never"> -<!-- expires-never: Generic system health metric used to diagnose various performance issues. --> - - <owner>fdoray@chromium.org</owner> - <summary> - The size of the resident memory in a utility process. This is influenced by - factors we control (e.g. memory that is not accessed can be swapped) and - factors we don't control (e.g. an unrelated process using a lot of memory - can force memory in our process to be swapped). Recorded on - Windows/Linux/ChromeOS/Android. - - Recorded at Poisson sampled time intervals with a mean of 5 minutes on - Android and 30 minutes on other platforms. - - This resident memory metric cannot be compared across platforms because each - platform relies on platform-level APIs for accounting. As such, though this - attempts to measure private memory footprint as best as possible, it does - not measure the same thing on each platform. We have not found a good way to - compare any system level memory metric across platforms due to the different - nature of memory management on each platform. - </summary> -</histogram> - -<histogram name="Memory.Utility.SharedMemoryFootprint" units="MB" - expires_after="2023-01-10"> - <owner>jam@chromium.org</owner> - <owner>erikchen@chromium.org</owner> - <owner>ssid@chromium.org</owner> - <summary> - A rough estimate of the shared memory footprint of the utility process. - - Recorded at Poisson sampled time intervals with a mean of 5 minutes on - Android and 30 minutes on other platforms. - - Note: Histogram data may be missing between M77 to M87 due to expiry. - </summary> -</histogram> - <histogram name="Memory.UX.Study.1" enum="UXStudy1Arm" expires_after="2023-05-14"> <owner>erikchen@chromium.org</owner> @@ -2958,6 +2753,87 @@ </summary> </histogram> +<histogram name="Memory.{UtilityProcessType}.PrivateMemoryFootprint" units="MB" + expires_after="never"> +<!-- expires-never: useful diagnostic metric for changes in + Memory.Total.PrivateMemoryFootprint, which never expires. --> + + <owner>erikchen@chromium.org</owner> + <owner>ssid@chromium.org</owner> + <summary> + A rough estimate of the private memory footprint of the {UtilityProcessType} + process. + + Recorded at Poisson sampled time intervals with a mean of 5 minutes on + Android and 30 minutes on other platforms. + + This memory footprint metric cannot be compared across platforms because + each platform relies on platform-level APIs for accounting. As such, though + this attempts to measure private memory footprint as best as possible, it + does not measure the same thing on each platform. We have not found a good + way to compare any system level memory metric across platforms due to the + different nature of memory management on each platform. + </summary> + <token key="UtilityProcessType" variants="UtilityProcessType"/> +</histogram> + +<histogram name="Memory.{UtilityProcessType}.PrivateSwapFootprint" units="MB" + expires_after="2023-07-16"> + <owner>erikchen@chromium.org</owner> + <owner>ssid@chromium.org</owner> + <summary> + An amount of private memory of the {UtilityProcessType} process placed in + swap (VmSwap). Available on Android, Linux and ChromeOS. + + Recorded at Poisson sampled time intervals with a mean of 5 minutes on + Android and 30 minutes on other platforms. + + Note: Histogram data may be missing for mid-2020 due to expiry. + </summary> + <token key="UtilityProcessType" variants="UtilityProcessType"/> +</histogram> + +<histogram name="Memory.{UtilityProcessType}.ResidentSet" units="MiB" + expires_after="never"> +<!-- expires-never: Generic system health metric used to diagnose various performance issues. --> + + <owner>fdoray@chromium.org</owner> + <summary> + The size of the resident memory in a {UtilityProcessType} process. This is + influenced by factors we control (e.g. memory that is not accessed can be + swapped) and factors we don't control (e.g. an unrelated process using a lot + of memory can force memory in our process to be swapped). Recorded on + Windows/Linux/ChromeOS/Android. + + Recorded at Poisson sampled time intervals with a mean of 5 minutes on + Android and 30 minutes on other platforms. + + This resident memory metric cannot be compared across platforms because each + platform relies on platform-level APIs for accounting. As such, though this + attempts to measure private memory footprint as best as possible, it does + not measure the same thing on each platform. We have not found a good way to + compare any system level memory metric across platforms due to the different + nature of memory management on each platform. + </summary> + <token key="UtilityProcessType" variants="UtilityProcessType"/> +</histogram> + +<histogram name="Memory.{UtilityProcessType}.SharedMemoryFootprint" units="MB" + expires_after="2023-07-16"> + <owner>erikchen@chromium.org</owner> + <owner>ssid@chromium.org</owner> + <summary> + A rough estimate of the shared memory footprint of the {UtilityProcessType} + process. + + Recorded at Poisson sampled time intervals with a mean of 5 minutes on + Android and 30 minutes on other platforms. + + Note: Histogram data may be missing between M77 to M87 due to expiry. + </summary> + <token key="UtilityProcessType" variants="UtilityProcessType"/> +</histogram> + <histogram name="MemoryAndroid.DeviceMemoryClass" units="units" expires_after="2020-06-07"> <owner>hajimehoshi@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/others/histograms.xml b/tools/metrics/histograms/metadata/others/histograms.xml index 07bf6ab..f079a74 100644 --- a/tools/metrics/histograms/metadata/others/histograms.xml +++ b/tools/metrics/histograms/metadata/others/histograms.xml
@@ -2231,24 +2231,6 @@ </summary> </histogram> -<histogram name="ChildProcess.FieldTrials.CreateFromShmemSuccess" - enum="BooleanSuccess" expires_after="M72"> - <owner>asvitkine@chromium.org</owner> - <summary> - Whether creating field trials from shared memory succeeded. Recorded by each - child process on process startup. - </summary> -</histogram> - -<histogram name="ChildProcess.FieldTrials.CreateFromSwitchSuccess" - enum="BooleanSuccess" expires_after="M72"> - <owner>asvitkine@chromium.org</owner> - <summary> - Whether creating field trials from --force-fieldtrials switch succeeded. - Recorded by each child process on process startup. - </summary> -</histogram> - <histogram name="ChildProcess.Killed2" enum="ProcessType2" expires_after="never"> <!-- expires-never: Critical stability metrics. go/chrome-stability-metrics -->
diff --git a/tools/metrics/histograms/metadata/safe_browsing/histograms.xml b/tools/metrics/histograms/metadata/safe_browsing/histograms.xml index db64c031..fcc9018c 100644 --- a/tools/metrics/histograms/metadata/safe_browsing/histograms.xml +++ b/tools/metrics/histograms/metadata/safe_browsing/histograms.xml
@@ -732,6 +732,21 @@ </summary> </histogram> +<histogram name="SafeBrowsing.ExtensionTelemetry.FileData.CollectionDuration" + units="ms" expires_after="2023-07-23"> + <owner>richche@chromium.org</owner> + <owner>chrome-counter-abuse-alerts@google.com</owner> + <summary> + Extension telemetry includes file data such as file hashes for off-store + extension files. This histogram measures how long it takes to collect file + data for all the offstore extensions installed. It is emitted after each + pass of the collection process completes which occurs periodically (every 2 + hours by default). The histogram is not emitted if there are no off-store + extensions installed or if the collection process is interrupted due to the + browser session ending or disabling Enhanced Safe Browsing for the profile. + </summary> +</histogram> + <histogram name="SafeBrowsing.ExtensionTelemetry.FileData.LargestFileSizeObserved" units="bytes" expires_after="2023-07-23"> @@ -786,6 +801,20 @@ </summary> </histogram> +<histogram + name="SafeBrowsing.ExtensionTelemetry.FileData.NumOffstoreExtensions" + units="extensions" expires_after="2023-07-23"> + <owner>richche@chromium.org</owner> + <owner>chrome-counter-abuse-alerts@google.com</owner> + <summary> + Extension telemetry includes file data such as file hashes for off-store + extension files. This histogram records the number of off-store extensions + installed in a user profile. It is emitted at the start of each pass of the + collection process which occurs periodically (every 2 hours by default). The + histogram is emitted even if there are no off-store extensions installed. + </summary> +</histogram> + <histogram name="SafeBrowsing.ExtensionTelemetry.FileData.ProcessedFileSize" units="bytes" expires_after="2023-07-23"> <owner>richche@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/variations/histograms.xml b/tools/metrics/histograms/metadata/variations/histograms.xml index a14fe737..f484d48 100644 --- a/tools/metrics/histograms/metadata/variations/histograms.xml +++ b/tools/metrics/histograms/metadata/variations/histograms.xml
@@ -22,6 +22,49 @@ <histograms> +<histogram name="ChildProcess.FieldTrials.CreateFromShmemSuccess" + enum="BooleanSuccess" expires_after="2023-07-15"> + <owner>asvitkine@chromium.org</owner> + <owner>src/base/metrics/OWNERS</owner> + <summary> + Whether creating field trials from shared memory succeeded. Recorded by each + child process on process startup. + </summary> +</histogram> + +<histogram name="ChildProcess.FieldTrials.CreateFromSwitchSuccess" + enum="BooleanSuccess" expires_after="2023-07-15"> + <owner>asvitkine@chromium.org</owner> + <owner>src/base/metrics/OWNERS</owner> + <summary> + Whether creating field trials from --force-fieldtrials switch succeeded. + Recorded by each child process on process startup. + </summary> +</histogram> + +<histogram + name="ChildProcess.FieldTrials.GetInitiallyActiveFieldTrials.FromString" + enum="Boolean" expires_after="2023-07-15"> + <owner>asvitkine@chromium.org</owner> + <owner>src/base/metrics/OWNERS</owner> + <summary> + Logged if there is no field trial allocator available when getting the list + of initially active field trials, resulting to a fallback to the command \ + line. Note: False is never logged. + </summary> +</histogram> + +<histogram name="ChildProcess.FieldTrials.PopulateLaunchOptions.CommandLine" + enum="Boolean" expires_after="2023-07-15"> + <owner>asvitkine@chromium.org</owner> + <owner>src/base/metrics/OWNERS</owner> + <summary> + Logged if the command line was populated with field trial information due to + the read-only shared memory handle not being available, when starting a + child process. Note: False is never logged. + </summary> +</histogram> + <histogram name="Variations.AppliedSeed.Size" units="bytes" expires_after="2023-07-30"> <owner>caitlinfischer@google.com</owner>
diff --git a/tools/metrics/histograms/validate_format.py b/tools/metrics/histograms/validate_format.py index 03490aba..c4f774b5 100755 --- a/tools/metrics/histograms/validate_format.py +++ b/tools/metrics/histograms/validate_format.py
@@ -13,9 +13,11 @@ import histogram_paths import merge_xml -# The allowlist of namespaces that are split across multiple files. +# The allowlist of namespaces (histogram prefixes, case insensitive) that are +# split across multiple files. _NAMESPACES_IN_MULTIPLE_FILES = [ - 'ash', 'autocomplete', 'chromeos', 'fcminvalidations', 'graphics', 'launch' + 'ash', 'autocomplete', 'childprocess', 'chromeos', 'fcminvalidations', + 'graphics', 'launch' ]
diff --git a/tools/perf/PRESUBMIT.py b/tools/perf/PRESUBMIT.py index edf0f1d..fc1ce15b 100644 --- a/tools/perf/PRESUBMIT.py +++ b/tools/perf/PRESUBMIT.py
@@ -178,7 +178,7 @@ # Intentionally invalid JSON file. continue try: - input_api.json.load(open(filename)) + input_api.json.load(open(filename, encoding='utf-8')) except ValueError: return [output_api.PresubmitError('Error parsing JSON in %s!' % filename)] return []
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index a00631b5..70f27c01 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,8 +5,8 @@ "full_remote_path": "perfetto-luci-artifacts/1d202f2412734f1e782d991618c7c4a7952e8738/linux-arm64/trace_processor_shell" }, "win": { - "hash": "29b1feda196dd18068e5ccab2b3a638ca9731d4c", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/6a84e7b38165dd5d14af8dc4faa47cad2caf8709/trace_processor_shell.exe" + "hash": "89da53f44f6976e7dd87651d2a2e6f03647078b1", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/7c5fe42e47b51d5f745aa543a76b091bf3e0daa6/trace_processor_shell.exe" }, "linux_arm": { "hash": "0606572451d2b1efd97a9cbc99906d2ca8351d1f",
diff --git a/tools/traffic_annotation/safe_list.txt b/tools/traffic_annotation/safe_list.txt index 0b5816cd..eb8bcc88 100644 --- a/tools/traffic_annotation/safe_list.txt +++ b/tools/traffic_annotation/safe_list.txt
@@ -192,8 +192,8 @@ missing_new_fields,components/captive_portal/content/captive_portal_service.cc missing_new_fields,components/commerce/core/account_checker.cc missing_new_fields,components/commerce/core/subscriptions/subscriptions_server_proxy.cc +missing_new_fields,components/content_relationship_verification/digital_asset_links_handler.cc missing_new_fields,components/contextual_search/core/browser/contextual_search_delegate_impl.cc -missing_new_fields,components/digital_asset_links/digital_asset_links_handler.cc missing_new_fields,components/dom_distiller/core/distiller_url_fetcher.cc missing_new_fields,components/domain_reliability/uploader.cc missing_new_fields,components/download/internal/common/download_item_impl.cc
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml index b4531924..275c548 100644 --- a/tools/traffic_annotation/summary/annotations.xml +++ b/tools/traffic_annotation/summary/annotations.xml
@@ -61,7 +61,7 @@ <item id="devtools_network_resource" added_in_milestone="62" content_hash_code="01f4a4af" os_list="linux,windows,chromeos" file_path="chrome/browser/devtools/devtools_ui_bindings.cc" /> <item id="devtools_proxy_config" added_in_milestone="85" content_hash_code="01e83c36" os_list="linux,windows,chromeos,android" file_path="content/browser/devtools/protocol/target_handler.cc" /> <item id="dial_url_fetcher" added_in_milestone="67" content_hash_code="07bd0650" os_list="linux,windows,chromeos" file_path="chrome/browser/media/router/discovery/dial/dial_url_fetcher.cc" /> - <item id="digital_asset_links" added_in_milestone="90" content_hash_code="00ced49e" os_list="linux,windows,chromeos,android" file_path="components/digital_asset_links/digital_asset_links_handler.cc" /> + <item id="digital_asset_links" added_in_milestone="90" content_hash_code="00ced49e" os_list="linux,windows,chromeos,android" file_path="components/content_relationship_verification/digital_asset_links_handler.cc" /> <item id="direct_sockets" added_in_milestone="88" content_hash_code="03dc0aad" os_list="linux,windows,chromeos" file_path="content/browser/direct_sockets/direct_sockets_service_impl.cc" /> <item id="dns_over_https" added_in_milestone="66" content_hash_code="02b087b6" os_list="linux,windows,chromeos,android" file_path="net/dns/dns_transaction.cc" /> <item id="dns_transaction" added_in_milestone="65" content_hash_code="07e14f9f" os_list="linux,windows,chromeos,android" file_path="net/dns/dns_transaction.cc" /> @@ -361,7 +361,7 @@ <item id="printing_server_printers_query" added_in_milestone="106" content_hash_code="06f4759c" os_list="chromeos" file_path="chrome/browser/ash/printing/server_printers_fetcher.cc" /> <item id="download_bubble_retry_download" added_in_milestone="105" content_hash_code="000b1439" os_list="linux,windows,chromeos" file_path="chrome/browser/download/bubble/download_bubble_controller.cc" /> <item id="wilco_dtc_supportd" added_in_milestone="108" content_hash_code="01050d07" os_list="chromeos" file_path="chrome/browser/ash/wilco_dtc_supportd/wilco_dtc_supportd_web_request_service.cc" /> - <item id="quick_answers_loader" added_in_milestone="105" content_hash_code="070b3239" os_list="chromeos" file_path="chromeos/components/quick_answers/result_loader.cc" /> + <item id="quick_answers_loader" added_in_milestone="105" content_hash_code="06f129c2" os_list="chromeos" file_path="chromeos/components/quick_answers/result_loader.cc" /> <item id="chrome_search_suggest_service" added_in_milestone="105" content_hash_code="04d973c6" os_list="linux,windows,android,chromeos" file_path="components/search/start_suggest_service.cc" /> <item id="coupon_persisted_tab_data" added_in_milestone="105" content_hash_code="006dcd97" os_list="android" file_path="chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/CouponPersistedTabData.java" /> <item id="speculation_rules_prefetch_probe" added_in_milestone="105" content_hash_code="04341e21" os_list="linux,windows,android,chromeos" file_path="content/browser/preloading/prefetch/prefetch_origin_prober.cc" />
diff --git a/ui/accessibility/PRESUBMIT.py b/ui/accessibility/PRESUBMIT.py index 16ebec1..19231ed 100644 --- a/ui/accessibility/PRESUBMIT.py +++ b/ui/accessibility/PRESUBMIT.py
@@ -34,7 +34,7 @@ def GetEnumsFromFile(fullpath, get_raw_enum_value=False): enum_name = None enums = {} - for line in open(fullpath).readlines(): + for line in open(fullpath, encoding='utf-8').readlines(): # Strip out comments line = re.sub('//.*', '', line) @@ -222,7 +222,7 @@ # header) def GetConstexprFromFile(fullpath): values = [] - for line in open(fullpath).readlines(): + for line in open(fullpath, encoding='utf-8').readlines(): # Strip out comments line = re.sub('//.*', '', line) @@ -242,7 +242,7 @@ def GetAccessibilityModesFromFile(fullpath): values = [] inside = False - for line in open(fullpath).readlines(): + for line in open(fullpath, encoding='utf-8').readlines(): if not inside: # Look for the block of code that defines the AXMode enum. m = re.search('^enum AxMode {$', line)
diff --git a/ui/accessibility/ax_enum_util.cc b/ui/accessibility/ax_enum_util.cc index d5a30a6..41f0ff4 100644 --- a/ui/accessibility/ax_enum_util.cc +++ b/ui/accessibility/ax_enum_util.cc
@@ -1493,6 +1493,8 @@ return ""; case ax::mojom::IsPopup::kAuto: return "auto"; + case ax::mojom::IsPopup::kHint: + return "hint"; case ax::mojom::IsPopup::kManual: return "manual"; }
diff --git a/ui/accessibility/ax_enums.mojom b/ui/accessibility/ax_enums.mojom index 6e786a5c..8811e81 100644 --- a/ui/accessibility/ax_enums.mojom +++ b/ui/accessibility/ax_enums.mojom
@@ -1176,6 +1176,7 @@ kNone = 0, kManual, kAuto, + kHint, }; enum InvalidState {
diff --git a/ui/accessibility/ax_node_data.cc b/ui/accessibility/ax_node_data.cc index 2cfa4d6..a428deb 100644 --- a/ui/accessibility/ax_node_data.cc +++ b/ui/accessibility/ax_node_data.cc
@@ -1579,6 +1579,9 @@ case ax::mojom::IsPopup::kAuto: result += " ispopup=auto"; break; + case ax::mojom::IsPopup::kHint: + result += " ispopup=hint"; + break; case ax::mojom::IsPopup::kManual: result += " ispopup=manual"; break;
diff --git a/ui/accessibility/platform/ax_platform_node_base.cc b/ui/accessibility/platform/ax_platform_node_base.cc index d3b8a6b5..548efed 100644 --- a/ui/accessibility/platform/ax_platform_node_base.cc +++ b/ui/accessibility/platform/ax_platform_node_base.cc
@@ -1355,6 +1355,9 @@ case ax::mojom::IsPopup::kAuto: AddAttributeToList("ispopup", "auto", attributes); break; + case ax::mojom::IsPopup::kHint: + AddAttributeToList("ispopup", "hint", attributes); + break; } }
diff --git a/ui/color/color_id.h b/ui/color/color_id.h index 66af287..a0214ec 100644 --- a/ui/color/color_id.h +++ b/ui/color/color_id.h
@@ -368,6 +368,7 @@ E_CPONLY(kColorToggleButtonThumbOffDisabled) \ E_CPONLY(kColorToggleButtonThumbOn) \ E_CPONLY(kColorToggleButtonThumbOnDisabled) \ + E_CPONLY(kColorToggleButtonThumbOnHoverPressed) \ E_CPONLY(kColorToggleButtonThumbOnIcon) \ E_CPONLY(kColorToggleButtonTrackOff) \ E_CPONLY(kColorToggleButtonTrackOn) \
diff --git a/ui/color/material_ui_color_mixer.cc b/ui/color/material_ui_color_mixer.cc index 6ce94b9..c2defe01 100644 --- a/ui/color/material_ui_color_mixer.cc +++ b/ui/color/material_ui_color_mixer.cc
@@ -70,6 +70,7 @@ mixer[kColorToggleButtonThumbOffDisabled] = {kColorSysStateDisabled}; mixer[kColorToggleButtonThumbOn] = {kColorSysOnPrimary}; mixer[kColorToggleButtonThumbOnDisabled] = {kColorSysSurface}; + mixer[kColorToggleButtonThumbOnHoverPressed] = {kColorSysPrimaryContainer}; mixer[kColorToggleButtonThumbOnIcon] = {kColorSysOnPrimaryContainer}; mixer[kColorToggleButtonTrackOff] = {kColorSysSurfaceVariant}; mixer[kColorToggleButtonTrackOn] = {kColorSysPrimary};
diff --git a/ui/events/ozone/evdev/BUILD.gn b/ui/events/ozone/evdev/BUILD.gn index adb9c39..31296ee 100644 --- a/ui/events/ozone/evdev/BUILD.gn +++ b/ui/events/ozone/evdev/BUILD.gn
@@ -195,6 +195,7 @@ visibility += [ "//ash/webui/diagnostics_ui/*", "//ui/chromeos/*", + "//ui/events/*", "//ui/ozone/*", ] }
diff --git a/ui/events/ozone/evdev/input_controller_evdev.cc b/ui/events/ozone/evdev/input_controller_evdev.cc index f9af545..085f306 100644 --- a/ui/events/ozone/evdev/input_controller_evdev.cc +++ b/ui/events/ozone/evdev/input_controller_evdev.cc
@@ -16,6 +16,7 @@ #include "ui/events/devices/device_data_manager.h" #include "ui/events/devices/stylus_state.h" #include "ui/events/ozone/evdev/input_device_factory_evdev_proxy.h" +#include "ui/events/ozone/evdev/input_device_settings_evdev.h" #include "ui/events/ozone/evdev/keyboard_evdev.h" #include "ui/events/ozone/evdev/mouse_button_map_evdev.h" @@ -154,27 +155,28 @@ } void InputControllerEvdev::SetTouchpadSensitivity(int value) { - input_device_settings_.touchpad_sensitivity = value; + input_device_settings_.GetTouchpadSettings().sensitivity = value; ScheduleUpdateDeviceSettings(); } void InputControllerEvdev::SetTouchpadScrollSensitivity(int value) { - input_device_settings_.touchpad_scroll_sensitivity = value; + input_device_settings_.GetTouchpadSettings().scroll_sensitivity = value; ScheduleUpdateDeviceSettings(); } void InputControllerEvdev::SetTouchpadHapticFeedback(bool enabled) { - input_device_settings_.touchpad_haptic_feedback_enabled = enabled; + input_device_settings_.GetTouchpadSettings().haptic_feedback_enabled = + enabled; ScheduleUpdateDeviceSettings(); } void InputControllerEvdev::SetTouchpadHapticClickSensitivity(int value) { - input_device_settings_.touchpad_haptic_click_sensitivity = value; + input_device_settings_.GetTouchpadSettings().haptic_click_sensitivity = value; ScheduleUpdateDeviceSettings(); } void InputControllerEvdev::SetTapToClick(bool enabled) { - input_device_settings_.tap_to_click_enabled = enabled; + input_device_settings_.GetTouchpadSettings().tap_to_click_enabled = enabled; ScheduleUpdateDeviceSettings(); } @@ -184,27 +186,27 @@ } void InputControllerEvdev::SetTapDragging(bool enabled) { - input_device_settings_.tap_dragging_enabled = enabled; + input_device_settings_.GetTouchpadSettings().tap_dragging_enabled = enabled; ScheduleUpdateDeviceSettings(); } void InputControllerEvdev::SetNaturalScroll(bool enabled) { - input_device_settings_.natural_scroll_enabled = enabled; + input_device_settings_.GetTouchpadSettings().natural_scroll_enabled = enabled; ScheduleUpdateDeviceSettings(); } void InputControllerEvdev::SetMouseSensitivity(int value) { - input_device_settings_.mouse_sensitivity = value; + input_device_settings_.GetMouseSettings().sensitivity = value; ScheduleUpdateDeviceSettings(); } void InputControllerEvdev::SetMouseScrollSensitivity(int value) { - input_device_settings_.mouse_scroll_sensitivity = value; + input_device_settings_.GetMouseSettings().scroll_sensitivity = value; ScheduleUpdateDeviceSettings(); } void InputControllerEvdev::SetPointingStickSensitivity(int value) { - input_device_settings_.pointing_stick_sensitivity = value; + input_device_settings_.GetPointingStickSettings().sensitivity = value; ScheduleUpdateDeviceSettings(); } @@ -213,7 +215,8 @@ stored_acceleration_settings_->pointing_stick = enabled; return; } - input_device_settings_.pointing_stick_acceleration_enabled = enabled; + input_device_settings_.GetPointingStickSettings().acceleration_enabled = + enabled; ScheduleUpdateDeviceSettings(); } @@ -238,7 +241,7 @@ } void InputControllerEvdev::SetMouseReverseScroll(bool enabled) { - input_device_settings_.mouse_reverse_scroll_enabled = enabled; + input_device_settings_.GetMouseSettings().reverse_scroll_enabled = enabled; ScheduleUpdateDeviceSettings(); } @@ -247,7 +250,7 @@ stored_acceleration_settings_->mouse = enabled; return; } - input_device_settings_.mouse_acceleration_enabled = enabled; + input_device_settings_.GetMouseSettings().acceleration_enabled = enabled; ScheduleUpdateDeviceSettings(); } @@ -257,11 +260,12 @@ stored_acceleration_settings_ = std::make_unique<StoredAccelerationSettings>(); stored_acceleration_settings_->mouse = - input_device_settings_.mouse_acceleration_enabled; + input_device_settings_.GetMouseSettings().acceleration_enabled; stored_acceleration_settings_->pointing_stick = - input_device_settings_.pointing_stick_acceleration_enabled; - input_device_settings_.mouse_acceleration_enabled = false; - input_device_settings_.pointing_stick_acceleration_enabled = false; + input_device_settings_.GetPointingStickSettings().acceleration_enabled; + input_device_settings_.GetMouseSettings().acceleration_enabled = false; + input_device_settings_.GetPointingStickSettings().acceleration_enabled = + false; ScheduleUpdateDeviceSettings(); } @@ -272,17 +276,19 @@ } void InputControllerEvdev::SetMouseScrollAcceleration(bool enabled) { - input_device_settings_.mouse_scroll_acceleration_enabled = enabled; + input_device_settings_.GetMouseSettings().scroll_acceleration_enabled = + enabled; ScheduleUpdateDeviceSettings(); } void InputControllerEvdev::SetTouchpadAcceleration(bool enabled) { - input_device_settings_.touchpad_acceleration_enabled = enabled; + input_device_settings_.GetTouchpadSettings().acceleration_enabled = enabled; ScheduleUpdateDeviceSettings(); } void InputControllerEvdev::SetTouchpadScrollAcceleration(bool enabled) { - input_device_settings_.touchpad_scroll_acceleration_enabled = enabled; + input_device_settings_.GetTouchpadSettings().scroll_acceleration_enabled = + enabled; ScheduleUpdateDeviceSettings(); }
diff --git a/ui/events/ozone/evdev/input_controller_evdev_unittest.cc b/ui/events/ozone/evdev/input_controller_evdev_unittest.cc index b3e8e4ad..640da90 100644 --- a/ui/events/ozone/evdev/input_controller_evdev_unittest.cc +++ b/ui/events/ozone/evdev/input_controller_evdev_unittest.cc
@@ -5,6 +5,7 @@ #include "ui/events/ozone/evdev/input_controller_evdev.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/events/ozone/evdev/input_device_settings_evdev.h" namespace ui { @@ -13,21 +14,24 @@ controller.SetMouseAcceleration(true); controller.SetPointingStickAcceleration(true); - EXPECT_TRUE(controller.input_device_settings_.mouse_acceleration_enabled); - EXPECT_TRUE( - controller.input_device_settings_.pointing_stick_acceleration_enabled); + EXPECT_TRUE(controller.input_device_settings_.GetMouseSettings() + .acceleration_enabled); + EXPECT_TRUE(controller.input_device_settings_.GetPointingStickSettings() + .acceleration_enabled); // Suspending should disable the acceleration temporarily. controller.SuspendMouseAcceleration(); - EXPECT_FALSE(controller.input_device_settings_.mouse_acceleration_enabled); - EXPECT_FALSE( - controller.input_device_settings_.pointing_stick_acceleration_enabled); + EXPECT_FALSE(controller.input_device_settings_.GetMouseSettings() + .acceleration_enabled); + EXPECT_FALSE(controller.input_device_settings_.GetPointingStickSettings() + .acceleration_enabled); // Resuming should enable it again. controller.EndMouseAccelerationSuspension(); - EXPECT_TRUE(controller.input_device_settings_.mouse_acceleration_enabled); - EXPECT_TRUE( - controller.input_device_settings_.pointing_stick_acceleration_enabled); + EXPECT_TRUE(controller.input_device_settings_.GetMouseSettings() + .acceleration_enabled); + EXPECT_TRUE(controller.input_device_settings_.GetPointingStickSettings() + .acceleration_enabled); } TEST(InputControllerEvdevTest, AccelerationChangeDuringSuspension) { @@ -37,24 +41,27 @@ // Suspending should disable the acceleration temporarily. controller.SuspendMouseAcceleration(); - EXPECT_FALSE(controller.input_device_settings_.mouse_acceleration_enabled); - EXPECT_FALSE( - controller.input_device_settings_.pointing_stick_acceleration_enabled); + EXPECT_FALSE(controller.input_device_settings_.GetMouseSettings() + .acceleration_enabled); + EXPECT_FALSE(controller.input_device_settings_.GetPointingStickSettings() + .acceleration_enabled); // Settings changes while suspended should not take effect immediately... controller.SetMouseAcceleration(true); controller.SetPointingStickAcceleration(true); - EXPECT_FALSE(controller.input_device_settings_.mouse_acceleration_enabled); - EXPECT_FALSE( - controller.input_device_settings_.pointing_stick_acceleration_enabled); + EXPECT_FALSE(controller.input_device_settings_.GetMouseSettings() + .acceleration_enabled); + EXPECT_FALSE(controller.input_device_settings_.GetPointingStickSettings() + .acceleration_enabled); // ...instead being applied when the suspension ends. controller.SetMouseAcceleration(false); controller.SetPointingStickAcceleration(false); controller.EndMouseAccelerationSuspension(); - EXPECT_FALSE(controller.input_device_settings_.mouse_acceleration_enabled); - EXPECT_FALSE( - controller.input_device_settings_.pointing_stick_acceleration_enabled); + EXPECT_FALSE(controller.input_device_settings_.GetMouseSettings() + .acceleration_enabled); + EXPECT_FALSE(controller.input_device_settings_.GetPointingStickSettings() + .acceleration_enabled); } } // namespace ui
diff --git a/ui/events/ozone/evdev/input_device_factory_evdev.cc b/ui/events/ozone/evdev/input_device_factory_evdev.cc index eb83a5d..bc2b5ab 100644 --- a/ui/events/ozone/evdev/input_device_factory_evdev.cc +++ b/ui/events/ozone/evdev/input_device_factory_evdev.cc
@@ -26,6 +26,7 @@ #include "ui/events/ozone/evdev/event_converter_evdev_impl.h" #include "ui/events/ozone/evdev/event_device_info.h" #include "ui/events/ozone/evdev/gamepad_event_converter_evdev.h" +#include "ui/events/ozone/evdev/input_device_settings_evdev.h" #include "ui/events/ozone/evdev/keyboard_imposter_checker_evdev.h" #include "ui/events/ozone/evdev/microphone_mute_switch_event_converter_evdev.h" #include "ui/events/ozone/evdev/stylus_button_event_converter_evdev.h" @@ -300,38 +301,46 @@ SetIntPropertyForOneType( DT_TOUCHPAD, "Haptic Button Sensitivity", - input_device_settings_.touchpad_haptic_click_sensitivity); - SetIntPropertyForOneType(DT_TOUCHPAD, "Pointer Sensitivity", - input_device_settings_.touchpad_sensitivity); - SetIntPropertyForOneType(DT_TOUCHPAD, "Scroll Sensitivity", - input_device_settings_.touchpad_scroll_sensitivity); + input_device_settings_.GetTouchpadSettings().haptic_click_sensitivity); + SetIntPropertyForOneType( + DT_TOUCHPAD, "Pointer Sensitivity", + input_device_settings_.GetTouchpadSettings().sensitivity); + SetIntPropertyForOneType( + DT_TOUCHPAD, "Scroll Sensitivity", + input_device_settings_.GetTouchpadSettings().scroll_sensitivity); SetBoolPropertyForOneType( DT_TOUCHPAD, "Pointer Acceleration", - input_device_settings_.touchpad_acceleration_enabled); + input_device_settings_.GetTouchpadSettings().acceleration_enabled); SetBoolPropertyForOneType( DT_TOUCHPAD, "Scroll Acceleration", - input_device_settings_.touchpad_scroll_acceleration_enabled); + input_device_settings_.GetTouchpadSettings().scroll_acceleration_enabled); - SetBoolPropertyForOneType(DT_TOUCHPAD, "Tap Enable", - input_device_settings_.tap_to_click_enabled); + SetBoolPropertyForOneType( + DT_TOUCHPAD, "Tap Enable", + input_device_settings_.GetTouchpadSettings().tap_to_click_enabled); SetBoolPropertyForOneType(DT_TOUCHPAD, "T5R2 Three Finger Click Enable", input_device_settings_.three_finger_click_enabled); - SetBoolPropertyForOneType(DT_TOUCHPAD, "Tap Drag Enable", - input_device_settings_.tap_dragging_enabled); + SetBoolPropertyForOneType( + DT_TOUCHPAD, "Tap Drag Enable", + input_device_settings_.GetTouchpadSettings().tap_dragging_enabled); - SetBoolPropertyForOneType(DT_MULTITOUCH, "Australian Scrolling", - input_device_settings_.natural_scroll_enabled); + SetBoolPropertyForOneType( + DT_MULTITOUCH, "Australian Scrolling", + input_device_settings_.GetTouchpadSettings().natural_scroll_enabled); - SetIntPropertyForOneType(DT_MOUSE, "Pointer Sensitivity", - input_device_settings_.mouse_sensitivity); - SetBoolPropertyForOneType(DT_MOUSE, "Pointer Acceleration", - input_device_settings_.mouse_acceleration_enabled); + SetIntPropertyForOneType( + DT_MOUSE, "Pointer Sensitivity", + input_device_settings_.GetMouseSettings().sensitivity); + SetBoolPropertyForOneType( + DT_MOUSE, "Pointer Acceleration", + input_device_settings_.GetMouseSettings().acceleration_enabled); ApplyRelativePointingDeviceSettings(DT_MOUSE); - SetIntPropertyForOneType(DT_POINTING_STICK, "Pointer Sensitivity", - input_device_settings_.pointing_stick_sensitivity); + SetIntPropertyForOneType( + DT_POINTING_STICK, "Pointer Sensitivity", + input_device_settings_.GetPointingStickSettings().sensitivity); SetBoolPropertyForOneType( DT_POINTING_STICK, "Pointer Acceleration", - input_device_settings_.pointing_stick_acceleration_enabled); + input_device_settings_.GetPointingStickSettings().acceleration_enabled); ApplyRelativePointingDeviceSettings(DT_POINTING_STICK); SetBoolPropertyForOneType(DT_TOUCHPAD, "Tap Paused", @@ -372,14 +381,17 @@ void InputDeviceFactoryEvdev::ApplyRelativePointingDeviceSettings( EventDeviceType type) { - SetIntPropertyForOneType(type, "Mouse Scroll Sensitivity", - input_device_settings_.mouse_scroll_sensitivity); - SetBoolPropertyForOneType( - type, "Mouse Scroll Acceleration", - input_device_settings_.mouse_scroll_acceleration_enabled); - SetBoolPropertyForOneType( - type, "Mouse Reverse Scrolling", - input_device_settings_.mouse_reverse_scroll_enabled); + if (type == DT_MOUSE) { + SetIntPropertyForOneType( + type, "Mouse Scroll Sensitivity", + input_device_settings_.GetMouseSettings().scroll_sensitivity); + SetBoolPropertyForOneType( + type, "Mouse Scroll Acceleration", + input_device_settings_.GetMouseSettings().scroll_acceleration_enabled); + SetBoolPropertyForOneType( + type, "Mouse Reverse Scrolling", + input_device_settings_.GetMouseSettings().reverse_scroll_enabled); + } SetBoolPropertyForOneType(type, "Mouse High Resolution Scrolling", true); SetBoolPropertyForOneType(type, "Output Mouse Wheel Gestures", true); }
diff --git a/ui/events/ozone/evdev/input_device_settings_evdev.cc b/ui/events/ozone/evdev/input_device_settings_evdev.cc index fb87990c..fe554b5 100644 --- a/ui/events/ozone/evdev/input_device_settings_evdev.cc +++ b/ui/events/ozone/evdev/input_device_settings_evdev.cc
@@ -8,16 +8,98 @@ #include "ui/events/ozone/features.h" namespace ui { +namespace { +// Used to denote the global instance of settings within the maps which is used +// when per device settings are disabled. +constexpr int kSharedSettingsDeviceId = -1; +} // namespace InputDeviceSettingsEvdev::InputDeviceSettingsEvdev() { touch_event_logging_enabled = base::FeatureList::IsEnabled(ui::kEnableInputEventLogging); } - InputDeviceSettingsEvdev::InputDeviceSettingsEvdev( - const InputDeviceSettingsEvdev& other) = default; + const InputDeviceSettingsEvdev& input_device_settings) = default; +InputDeviceSettingsEvdev::~InputDeviceSettingsEvdev() = default; -InputDeviceSettingsEvdev::~InputDeviceSettingsEvdev() { +TouchpadSettingsEvdev& InputDeviceSettingsEvdev::GetTouchpadSettings() { + return touchpad_settings_[kSharedSettingsDeviceId]; } +MouseSettingsEvdev& InputDeviceSettingsEvdev::GetMouseSettings() { + return mouse_settings_[kSharedSettingsDeviceId]; +} + +PointingStickSettingsEvdev& +InputDeviceSettingsEvdev::GetPointingStickSettings() { + return pointing_stick_settings_[kSharedSettingsDeviceId]; +} + +const TouchpadSettingsEvdev& InputDeviceSettingsEvdev::GetTouchpadSettings() + const { + return touchpad_settings_.at(kSharedSettingsDeviceId); +} + +const MouseSettingsEvdev& InputDeviceSettingsEvdev::GetMouseSettings() const { + return mouse_settings_.at(kSharedSettingsDeviceId); +} + +const PointingStickSettingsEvdev& +InputDeviceSettingsEvdev::GetPointingStickSettings() const { + return pointing_stick_settings_.at(kSharedSettingsDeviceId); +} + +TouchpadSettingsEvdev& InputDeviceSettingsEvdev::GetTouchpadSettings( + int device_id) { + if (!enable_per_device_settings) { + return GetTouchpadSettings(); + } + return touchpad_settings_[device_id]; +} + +MouseSettingsEvdev& InputDeviceSettingsEvdev::GetMouseSettings(int device_id) { + if (!enable_per_device_settings) { + return GetMouseSettings(); + } + + return mouse_settings_[device_id]; +} + +PointingStickSettingsEvdev& InputDeviceSettingsEvdev::GetPointingStickSettings( + int device_id) { + if (!enable_per_device_settings) { + return GetPointingStickSettings(); + } + return pointing_stick_settings_[device_id]; +} + +const TouchpadSettingsEvdev& InputDeviceSettingsEvdev::GetTouchpadSettings( + int device_id) const { + if (!enable_per_device_settings) { + return GetTouchpadSettings(); + } + return touchpad_settings_.at(device_id); +} + +const MouseSettingsEvdev& InputDeviceSettingsEvdev::GetMouseSettings( + int device_id) const { + if (!enable_per_device_settings) { + return GetMouseSettings(); + } + return mouse_settings_.at(device_id); +} + +const PointingStickSettingsEvdev& +InputDeviceSettingsEvdev::GetPointingStickSettings(int device_id) const { + if (!enable_per_device_settings) { + return GetPointingStickSettings(); + } + return pointing_stick_settings_.at(device_id); +} + +TouchpadSettingsEvdev::TouchpadSettingsEvdev() = default; +TouchpadSettingsEvdev::TouchpadSettingsEvdev( + const TouchpadSettingsEvdev& touchpad_settings_) = default; +TouchpadSettingsEvdev::~TouchpadSettingsEvdev() = default; + } // namespace ui
diff --git a/ui/events/ozone/evdev/input_device_settings_evdev.h b/ui/events/ozone/evdev/input_device_settings_evdev.h index cf8a0a8..55c5fdf 100644 --- a/ui/events/ozone/evdev/input_device_settings_evdev.h +++ b/ui/events/ozone/evdev/input_device_settings_evdev.h
@@ -7,45 +7,87 @@ #include <vector> +#include "base/component_export.h" +#include "base/containers/flat_map.h" + namespace ui { enum class DomCode; -struct InputDeviceSettingsEvdev { - InputDeviceSettingsEvdev(); - InputDeviceSettingsEvdev(const InputDeviceSettingsEvdev& other); - ~InputDeviceSettingsEvdev(); +constexpr int kDefaultSensitivity = 3; - static const int kDefaultSensitivity = 3; +struct MouseSettingsEvdev { + // The initial settings are not critical since they will be shortly be changed + // to the user's preferences or the application's own defaults. + bool reverse_scroll_enabled = false; + bool acceleration_enabled = true; + bool scroll_acceleration_enabled = true; + int sensitivity = kDefaultSensitivity; + int scroll_sensitivity = kDefaultSensitivity; +}; + +struct TouchpadSettingsEvdev { + TouchpadSettingsEvdev(); + TouchpadSettingsEvdev(const TouchpadSettingsEvdev&); + ~TouchpadSettingsEvdev(); // The initial settings are not critical since they will be shortly be changed // to the user's preferences or the application's own defaults. bool tap_to_click_enabled = true; - bool three_finger_click_enabled = false; bool tap_dragging_enabled = false; bool natural_scroll_enabled = false; + bool acceleration_enabled = true; + bool scroll_acceleration_enabled = true; + bool haptic_feedback_enabled = true; + int sensitivity = kDefaultSensitivity; + int scroll_sensitivity = kDefaultSensitivity; + int haptic_click_sensitivity = kDefaultSensitivity; +}; + +struct PointingStickSettingsEvdev { + // The initial settings are not critical since they will be shortly be changed + // to the user's preferences or the application's own defaults. + bool acceleration_enabled = true; + int sensitivity = kDefaultSensitivity; +}; + +struct COMPONENT_EXPORT(EVDEV) InputDeviceSettingsEvdev { + InputDeviceSettingsEvdev(); + InputDeviceSettingsEvdev(const InputDeviceSettingsEvdev&); + ~InputDeviceSettingsEvdev(); + + TouchpadSettingsEvdev& GetTouchpadSettings(); + TouchpadSettingsEvdev& GetTouchpadSettings(int device_id); + const TouchpadSettingsEvdev& GetTouchpadSettings() const; + const TouchpadSettingsEvdev& GetTouchpadSettings(int device_id) const; + + MouseSettingsEvdev& GetMouseSettings(); + MouseSettingsEvdev& GetMouseSettings(int device_id); + const MouseSettingsEvdev& GetMouseSettings() const; + const MouseSettingsEvdev& GetMouseSettings(int device_id) const; + + PointingStickSettingsEvdev& GetPointingStickSettings(); + PointingStickSettingsEvdev& GetPointingStickSettings(int device_id); + const PointingStickSettingsEvdev& GetPointingStickSettings() const; + const PointingStickSettingsEvdev& GetPointingStickSettings( + int device_id) const; + + bool enable_per_device_settings = false; + // Pausing of tap to click applies to all touchpad devices. bool tap_to_click_paused = false; + // Three finger click applies to all touchpad devices. + bool three_finger_click_enabled = false; bool touch_event_logging_enabled = false; - bool mouse_reverse_scroll_enabled = false; - bool mouse_acceleration_enabled = true; - bool mouse_scroll_acceleration_enabled = true; - bool pointing_stick_acceleration_enabled = true; - bool touchpad_acceleration_enabled = true; - bool touchpad_scroll_acceleration_enabled = true; - bool touchpad_haptic_feedback_enabled = true; - - int touchpad_sensitivity = kDefaultSensitivity; - int touchpad_scroll_sensitivity = kDefaultSensitivity; - int touchpad_haptic_click_sensitivity = kDefaultSensitivity; - int mouse_sensitivity = kDefaultSensitivity; - int mouse_scroll_sensitivity = kDefaultSensitivity; - int pointing_stick_sensitivity = kDefaultSensitivity; - bool enable_devices = true; // If false, all input is disabled. bool enable_internal_touchpad = true; bool enable_touch_screens = true; bool enable_internal_keyboard_filter = false; std::vector<DomCode> internal_keyboard_allowed_keys; + + private: + base::flat_map<int, TouchpadSettingsEvdev> touchpad_settings_; + base::flat_map<int, MouseSettingsEvdev> mouse_settings_; + base::flat_map<int, PointingStickSettingsEvdev> pointing_stick_settings_; }; } // namespace ui
diff --git a/ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.cc b/ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.cc index a6e9ea2a..c41cad1 100644 --- a/ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.cc +++ b/ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.cc
@@ -137,12 +137,13 @@ void EventReaderLibevdevCros::ApplyDeviceSettings( const InputDeviceSettingsEvdev& settings) { + const auto& touchpad_settings = settings.GetTouchpadSettings(); if (haptic_touchpad_handler_) { haptic_touchpad_handler_->SetClickStrength( static_cast<HapticTouchpadEffectStrength>( - settings.touchpad_haptic_click_sensitivity)); + touchpad_settings.haptic_click_sensitivity)); } - haptic_feedback_enabled_ = settings.touchpad_haptic_feedback_enabled; + haptic_feedback_enabled_ = touchpad_settings.haptic_feedback_enabled; } bool EventReaderLibevdevCros::HasCapsLockLed() const {
diff --git a/ui/events/ozone/evdev/libinput_event_converter.cc b/ui/events/ozone/evdev/libinput_event_converter.cc index 4cea9c5..00e20bd 100644 --- a/ui/events/ozone/evdev/libinput_event_converter.cc +++ b/ui/events/ozone/evdev/libinput_event_converter.cc
@@ -111,9 +111,10 @@ void LibInputEventConverter::LibInputDevice::ApplySettings( const InputDeviceSettingsEvdev& settings) const { - SetNaturalScrollEnabled(settings.natural_scroll_enabled); - SetSensitivity(settings.touchpad_sensitivity); - SetTapToClickEnabled(settings.tap_to_click_enabled); + const auto& touchpad_settings = settings.GetTouchpadSettings(); + SetNaturalScrollEnabled(touchpad_settings.natural_scroll_enabled); + SetSensitivity(touchpad_settings.sensitivity); + SetTapToClickEnabled(touchpad_settings.tap_to_click_enabled); } // Get a comma-separated string of the device's capabilities
diff --git a/ui/ozone/platform/drm/BUILD.gn b/ui/ozone/platform/drm/BUILD.gn index 41d149e..95338b1d 100644 --- a/ui/ozone/platform/drm/BUILD.gn +++ b/ui/ozone/platform/drm/BUILD.gn
@@ -200,6 +200,8 @@ "gpu/drm_overlay_validator_unittest.cc", "gpu/drm_thread_unittest.cc", "gpu/drm_window_unittest.cc", + "gpu/fake_drm_device_generator.cc", + "gpu/fake_drm_device_generator.h", "gpu/hardware_display_controller_unittest.cc", "gpu/hardware_display_plane_manager_unittest.cc", "gpu/mock_drm_device.cc",
diff --git a/ui/ozone/platform/drm/gpu/drm_thread_unittest.cc b/ui/ozone/platform/drm/gpu/drm_thread_unittest.cc index df68442..e54d554 100644 --- a/ui/ozone/platform/drm/gpu/drm_thread_unittest.cc +++ b/ui/ozone/platform/drm/gpu/drm_thread_unittest.cc
@@ -9,24 +9,11 @@ #include "base/test/task_environment.h" #include "mojo/public/cpp/bindings/remote.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/gfx/linux/test/mock_gbm_device.h" -#include "ui/ozone/platform/drm/gpu/drm_device_generator.h" -#include "ui/ozone/platform/drm/gpu/mock_drm_device.h" - +#include "ui/ozone/platform/drm/gpu/fake_drm_device_generator.h" namespace ui { namespace { -class FakeDrmDeviceGenerator : public DrmDeviceGenerator { - // DrmDeviceGenerator: - scoped_refptr<DrmDevice> CreateDevice(const base::FilePath& path, - base::ScopedFD fd, - bool is_primary_device) override { - auto gbm_device = std::make_unique<MockGbmDevice>(); - return base::MakeRefCounted<MockDrmDevice>(std::move(gbm_device)); - } -}; - void StubTask() {} void StubTaskWithDoneFeedback(bool* done) {
diff --git a/ui/ozone/platform/drm/gpu/fake_drm_device_generator.cc b/ui/ozone/platform/drm/gpu/fake_drm_device_generator.cc new file mode 100644 index 0000000..f7d8f16 --- /dev/null +++ b/ui/ozone/platform/drm/gpu/fake_drm_device_generator.cc
@@ -0,0 +1,23 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/ozone/platform/drm/gpu/fake_drm_device_generator.h" + +#include "ui/gfx/linux/test/mock_gbm_device.h" +#include "ui/ozone/platform/drm/gpu/mock_drm_device.h" + +namespace ui { +scoped_refptr<DrmDevice> FakeDrmDeviceGenerator::CreateDevice( + const base::FilePath& path, + base::ScopedFD fd, + bool is_primary_device) { + auto gbm_device = std::make_unique<MockGbmDevice>(); + if (path.empty()) + return base::MakeRefCounted<MockDrmDevice>(std::move(gbm_device)); + + return base::MakeRefCounted<MockDrmDevice>( + std::move(path), std::move(gbm_device), is_primary_device); +} + +} // namespace ui
diff --git a/ui/ozone/platform/drm/gpu/fake_drm_device_generator.h b/ui/ozone/platform/drm/gpu/fake_drm_device_generator.h new file mode 100644 index 0000000..f383fdf --- /dev/null +++ b/ui/ozone/platform/drm/gpu/fake_drm_device_generator.h
@@ -0,0 +1,27 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_OZONE_PLATFORM_DRM_GPU_FAKE_DRM_DEVICE_GENERATOR_H_ +#define UI_OZONE_PLATFORM_DRM_GPU_FAKE_DRM_DEVICE_GENERATOR_H_ + +#include "ui/ozone/platform/drm/gpu/drm_device_generator.h" + +#include "base/files/file_path.h" +#include "base/files/scoped_file.h" +#include "base/memory/scoped_refptr.h" + +namespace ui { + +class DrmDevice; + +class FakeDrmDeviceGenerator : public DrmDeviceGenerator { + // DrmDeviceGenerator: + scoped_refptr<DrmDevice> CreateDevice(const base::FilePath& path, + base::ScopedFD fd, + bool is_primary_device) override; +}; + +} // namespace ui + +#endif // UI_OZONE_PLATFORM_DRM_GPU_FAKE_DRM_DEVICE_GENERATOR_H_
diff --git a/ui/ozone/platform/drm/gpu/mock_drm_device.cc b/ui/ozone/platform/drm/gpu/mock_drm_device.cc index d6996ba..120a4c62 100644 --- a/ui/ozone/platform/drm/gpu/mock_drm_device.cc +++ b/ui/ozone/platform/drm/gpu/mock_drm_device.cc
@@ -48,6 +48,8 @@ // pageflip, or other atomic property changes that do not require modesetting. constexpr uint32_t kSeamlessModesetFlags = 0; +const std::vector<uint32_t> kBlobProperyIds = {kEdidBlobPropId}; + const std::map<uint32_t, std::string> kCrtcRequiredPropertyNames = { {kActivePropId, "ACTIVE"}, {kModePropId, "MODE_ID"}, @@ -67,6 +69,7 @@ const std::map<uint32_t, std::string> kConnectorRequiredPropertyNames = { {kCrtcIdPropId, "CRTC_ID"}, {kLinkStatusPropId, "link-status"}, + {kEdidBlobPropId, "EDID"}, }; const std::map<uint32_t, std::string> kPlaneRequiredPropertyNames = { @@ -137,6 +140,10 @@ return ++value_generator; } +bool IsPropertyValueBlob(uint32_t prop_id) { + return base::Contains(kBlobProperyIds, prop_id); +} + } // namespace MockDrmDevice::CrtcProperties::CrtcProperties() = default; @@ -148,6 +155,11 @@ const ConnectorProperties&) = default; MockDrmDevice::ConnectorProperties::~ConnectorProperties() = default; +MockDrmDevice::EncoderProperties::EncoderProperties() = default; +MockDrmDevice::EncoderProperties::EncoderProperties(const EncoderProperties&) = + default; +MockDrmDevice::EncoderProperties::~EncoderProperties() = default; + MockDrmDevice::PlaneProperties::PlaneProperties() = default; MockDrmDevice::PlaneProperties::PlaneProperties(const PlaneProperties&) = default; @@ -232,12 +244,10 @@ return state; } -std::pair<MockDrmDevice::CrtcProperties&, MockDrmDevice::ConnectorProperties&> -MockDrmDevice::MockDrmState::AddCrtcAndConnector() { +MockDrmDevice::ConnectorProperties& +MockDrmDevice::MockDrmState::AddConnector() { uint32_t next_connector_id = GetNextId(connector_properties, kConnectorIdBase); - uint32_t next_crtc_id = GetNextId(crtc_properties, kCrtcIdBase); - auto& connector_property = connector_properties.emplace_back(); connector_property.id = next_connector_id; for (const auto& pair : kConnectorRequiredPropertyNames) { @@ -246,6 +256,19 @@ property_names.emplace(pair.first, pair.second); } + return {connector_property}; +} + +MockDrmDevice::EncoderProperties& MockDrmDevice::MockDrmState::AddEncoder() { + uint32_t next_encoder_id = GetNextId(crtc_properties, kEncoderIdBase); + auto& encoder_property = encoder_properties.emplace_back(); + encoder_property.id = next_encoder_id; + + return {encoder_property}; +} + +MockDrmDevice::CrtcProperties& MockDrmDevice::MockDrmState::AddCrtc() { + uint32_t next_crtc_id = GetNextId(crtc_properties, kCrtcIdBase); auto& crtc_property = crtc_properties.emplace_back(); crtc_property.id = next_crtc_id; for (const auto& pair : kCrtcRequiredPropertyNames) { @@ -254,7 +277,12 @@ property_names.emplace(pair.first, pair.second); } - return {crtc_property, connector_property}; + return {crtc_property}; +} + +std::pair<MockDrmDevice::CrtcProperties&, MockDrmDevice::ConnectorProperties&> +MockDrmDevice::MockDrmState::AddCrtcAndConnector() { + return {AddCrtc(), AddConnector()}; } MockDrmDevice::PlaneProperties& MockDrmDevice::MockDrmState::AddPlane( @@ -295,18 +323,17 @@ : DrmDevice(base::FilePath(), base::ScopedFD(), true /* is_primary_device */, - std::move(gbm_device)), - set_crtc_call_count_(0), - add_framebuffer_call_count_(0), - remove_framebuffer_call_count_(0), - page_flip_call_count_(0), - overlay_clear_call_count_(0), - allocate_buffer_count_(0), - set_crtc_expectation_(true), - add_framebuffer_expectation_(true), - page_flip_expectation_(true), - create_dumb_buffer_expectation_(true), - current_framebuffer_(0) { + std::move(gbm_device)) { + plane_manager_ = std::make_unique<HardwareDisplayPlaneManagerLegacy>(this); +} + +MockDrmDevice::MockDrmDevice(const base::FilePath& path, + std::unique_ptr<GbmDevice> gbm_device, + bool is_primary_device) + : DrmDevice(std::move(path), + base::ScopedFD(), + is_primary_device, + std::move(gbm_device)) { plane_manager_ = std::make_unique<HardwareDisplayPlaneManagerLegacy>(this); } @@ -340,24 +367,48 @@ return blob; } -void MockDrmDevice::InitializeState(const MockDrmState& state, - bool use_atomic) { +void MockDrmDevice::InitializeState(MockDrmState& state, bool use_atomic) { CHECK(InitializeStateWithResult(state, use_atomic)); } -bool MockDrmDevice::InitializeStateWithResult(const MockDrmState& state, +bool MockDrmDevice::InitializeStateWithResult(MockDrmState& state, bool use_atomic) { - UpdateStateBesidesPlaneManager(state); - if (use_atomic) { plane_manager_ = std::make_unique<HardwareDisplayPlaneManagerAtomic>(this); } else { plane_manager_ = std::make_unique<HardwareDisplayPlaneManagerLegacy>(this); } + MaybeSetEdidBlobsForConnectors(state); + UpdateStateBesidesPlaneManager(state); + return plane_manager_->Initialize(); } +void MockDrmDevice::MaybeSetEdidBlobsForConnectors(MockDrmState& state) { + for (auto& mock_connector : state.connector_properties) { + const std::vector<uint8_t> edid_blob = mock_connector.edid_blob; + if (edid_blob.empty()) { + continue; + } + + DrmWrapper::Property* mock_blob_prop = + FindObjectById(kEdidBlobPropId, mock_connector.properties); + DCHECK(mock_blob_prop); + // Update the mock EDID property's value to the EDID blob's ID. + mock_blob_prop->value = GetNextId(state.blobs, kBaseBlobId); + state.blobs.push_back(*mock_blob_prop); + + ScopedDrmPropertyBlobPtr drm_prop_blob( + DrmAllocator<drmModePropertyBlobRes>()); + drm_prop_blob->id = mock_blob_prop->value; + drm_prop_blob->length = mock_connector.edid_blob.size(); + drm_prop_blob->data = drmMalloc(drm_prop_blob->length); + memcpy(drm_prop_blob->data, edid_blob.data(), edid_blob.size()); + SetPropertyBlob(std::move(drm_prop_blob)); + } +} + void MockDrmDevice::UpdateStateBesidesPlaneManager(const MockDrmState& state) { drm_state_ = state; } @@ -424,7 +475,15 @@ } ScopedDrmCrtcPtr MockDrmDevice::GetCrtc(uint32_t crtc_id) const { - return ScopedDrmCrtcPtr(DrmAllocator<drmModeCrtc>()); + const CrtcProperties* mock_crtc = + FindObjectById(crtc_id, drm_state_.crtc_properties); + if (!mock_crtc) + return nullptr; + + ScopedDrmCrtcPtr crtc(DrmAllocator<drmModeCrtc>()); + crtc->crtc_id = mock_crtc->id; + + return crtc; } bool MockDrmDevice::SetCrtc(uint32_t crtc_id, @@ -443,7 +502,59 @@ } ScopedDrmConnectorPtr MockDrmDevice::GetConnector(uint32_t connector_id) const { - return ScopedDrmConnectorPtr(DrmAllocator<drmModeConnector>()); + const ConnectorProperties* mock_connector = + FindObjectById(connector_id, drm_state_.connector_properties); + if (!mock_connector) + return nullptr; + + ScopedDrmConnectorPtr connector(DrmAllocator<drmModeConnector>()); + connector->connector_id = mock_connector->id; + connector->connection = + mock_connector->connection ? DRM_MODE_CONNECTED : DRM_MODE_DISCONNECTED; + + // Copy props. + const uint32_t count_props = mock_connector->properties.size(); + connector->count_props = count_props; + connector->props = DrmAllocator<uint32_t>(count_props); + connector->prop_values = DrmAllocator<uint64_t>(count_props); + for (uint32_t i = 0; i < count_props; ++i) { + connector->props[i] = mock_connector->properties[i].id; + connector->prop_values[i] = mock_connector->properties[i].value; + } + + // Copy modes. + const uint32_t count_modes = mock_connector->modes.size(); + connector->count_modes = count_modes; + connector->modes = DrmAllocator<drmModeModeInfo>(count_modes); + for (uint32_t i = 0; i < count_modes; ++i) { + const gfx::Size resoluton = mock_connector->modes[i].first; + const uint32_t vrefresh = mock_connector->modes[i].second; + connector->modes[i].hdisplay = resoluton.width(); + connector->modes[i].vdisplay = resoluton.height(); + connector->modes[i].vrefresh = vrefresh; + } + + // Copy associated encoders. + const uint32_t count_encoders = mock_connector->encoders.size(); + connector->count_encoders = count_encoders; + connector->encoders = DrmAllocator<uint32_t>(count_encoders); + for (uint32_t i = 0; i < count_encoders; ++i) + connector->encoders[i] = mock_connector->encoders[i]; + + return connector; +} + +ScopedDrmEncoderPtr MockDrmDevice::GetEncoder(uint32_t encoder_id) const { + const EncoderProperties* mock_encoder = + FindObjectById(encoder_id, drm_state_.encoder_properties); + if (!mock_encoder) + return nullptr; + + ScopedDrmEncoderPtr encoder(DrmAllocator<drmModeEncoder>()); + encoder->encoder_id = mock_encoder->id; + encoder->possible_crtcs = mock_encoder->possible_crtcs; + + return encoder; } bool MockDrmDevice::AddFramebuffer2(uint32_t width, @@ -525,6 +636,9 @@ ScopedDrmPropertyPtr property(DrmAllocator<drmModePropertyRes>()); property->prop_id = id; strcpy(property->name, it->second.c_str()); + if (IsPropertyValueBlob(property->prop_id)) + property->flags = DRM_MODE_PROP_BLOB; + return property; } @@ -567,7 +681,24 @@ ScopedDrmPropertyBlobPtr MockDrmDevice::GetPropertyBlob( drmModeConnector* connector, const char* name) const { - return ScopedDrmPropertyBlobPtr(DrmAllocator<drmModePropertyBlobRes>()); + const ConnectorProperties* mock_connector = + FindObjectById(connector->connector_id, drm_state_.connector_properties); + if (!mock_connector) + return nullptr; + + ScopedDrmPropertyBlobPtr blob(DrmAllocator<drmModePropertyBlobRes>()); + for (const auto& prop : mock_connector->properties) { + auto prop_name_it = drm_state_.property_names.find(prop.id); + if (prop_name_it == drm_state_.property_names.end()) + continue; + + if (prop_name_it->second.compare(name) != 0) + continue; + + return GetPropertyBlob(prop.value); + } + + return nullptr; } bool MockDrmDevice::SetObjectProperty(uint32_t object_id,
diff --git a/ui/ozone/platform/drm/gpu/mock_drm_device.h b/ui/ozone/platform/drm/gpu/mock_drm_device.h index b137432..d891b44 100644 --- a/ui/ozone/platform/drm/gpu/mock_drm_device.h +++ b/ui/ozone/platform/drm/gpu/mock_drm_device.h
@@ -30,6 +30,8 @@ namespace ui { +using ResolutionAndRefreshRate = std::pair<gfx::Size, uint32_t>; + template <class Object> Object* DrmAllocator(size_t num_of_objects = 1) { return static_cast<Object*>(drmMalloc(num_of_objects * sizeof(Object))); @@ -40,10 +42,12 @@ constexpr uint32_t kCrtcIdBase = 200; constexpr uint32_t kConnectorIdBase = 300; constexpr uint32_t kInFormatsBlobIdBase = 400; +constexpr uint32_t kEncoderIdBase = 500; // Required Connector Property IDs: constexpr uint32_t kCrtcIdPropId = 1000; constexpr uint32_t kLinkStatusPropId = 1001; +constexpr uint32_t kEdidBlobPropId = 1002; // Required CRTC Property IDs: constexpr uint32_t kActivePropId = 2000; @@ -78,6 +82,9 @@ constexpr uint32_t kPlaneCtmId = 5002; constexpr uint32_t kRotationPropId = 5003; +// Blob IDs: +constexpr uint32_t kBaseBlobId = 6000; + // The real DrmDevice makes actual DRM calls which we can't use in unit tests. class MockDrmDevice : public DrmDevice { public: @@ -97,10 +104,23 @@ ~ConnectorProperties(); uint32_t id; + bool connection; + std::vector<ResolutionAndRefreshRate> modes; + std::vector<uint32_t> encoders; + std::vector<uint8_t> edid_blob; std::vector<DrmWrapper::Property> properties; }; + struct EncoderProperties { + EncoderProperties(); + EncoderProperties(const EncoderProperties&); + ~EncoderProperties(); + + uint32_t id; + uint32_t possible_crtcs; + }; + struct PlaneProperties { PlaneProperties(); PlaneProperties(const PlaneProperties&); @@ -137,6 +157,9 @@ size_t planes_per_crtc, size_t movable_planes = 0u); + ConnectorProperties& AddConnector(); + EncoderProperties& AddEncoder(); + CrtcProperties& AddCrtc(); std::pair<CrtcProperties&, ConnectorProperties&> AddCrtcAndConnector(); PlaneProperties& AddPlane(uint32_t crtc_id, uint32_t type); PlaneProperties& AddPlane(const std::vector<uint32_t>& crtc_ids, @@ -144,11 +167,16 @@ std::vector<CrtcProperties> crtc_properties; std::vector<ConnectorProperties> connector_properties; + std::vector<EncoderProperties> encoder_properties; std::vector<PlaneProperties> plane_properties; + std::vector<DrmWrapper::Property> blobs; std::map<uint32_t, std::string> property_names; }; explicit MockDrmDevice(std::unique_ptr<GbmDevice> gbm_device); + explicit MockDrmDevice(const base::FilePath& path, + std::unique_ptr<GbmDevice> gbm_device, + bool is_primary_device); MockDrmDevice(const MockDrmDevice&) = delete; MockDrmDevice& operator=(const MockDrmDevice&) = delete; @@ -205,8 +233,12 @@ return it != crtc_cursor_map_.end() ? it->second : 0; } - void InitializeState(const MockDrmState& state, bool use_atomic); - bool InitializeStateWithResult(const MockDrmState& state, bool use_atomic); + void InitializeState(MockDrmState& state, bool use_atomic); + bool InitializeStateWithResult(MockDrmState& state, bool use_atomic); + + // Sets EDID blobs as property blobs so they can be fetched when needed via + // GetPropertyBlob(). + void MaybeSetEdidBlobsForConnectors(MockDrmState& state); void UpdateStateBesidesPlaneManager(const MockDrmState& state); @@ -253,6 +285,7 @@ const drmModeModeInfo& mode) override; bool DisableCrtc(uint32_t crtc_id) override; ScopedDrmConnectorPtr GetConnector(uint32_t connector_id) const override; + ScopedDrmEncoderPtr GetEncoder(uint32_t encoder_id) const override; bool AddFramebuffer2(uint32_t width, uint32_t height, uint32_t format, @@ -326,12 +359,12 @@ bool ValidatePropertyValue(uint32_t id, uint64_t value); - int set_crtc_call_count_; - int add_framebuffer_call_count_; - int remove_framebuffer_call_count_; - int page_flip_call_count_; - int overlay_clear_call_count_; - int allocate_buffer_count_; + int set_crtc_call_count_ = 0; + int add_framebuffer_call_count_ = 0; + int remove_framebuffer_call_count_ = 0; + int page_flip_call_count_ = 0; + int overlay_clear_call_count_ = 0; + int allocate_buffer_count_ = 0; int test_modeset_count_ = 0; int commit_modeset_count_ = 0; int seamless_modeset_count_ = 0; @@ -341,15 +374,15 @@ int last_planes_committed_count_ = 0; int modeset_sequence_id_ = 0; - bool set_crtc_expectation_; - bool add_framebuffer_expectation_; - bool page_flip_expectation_; - bool create_dumb_buffer_expectation_; + bool set_crtc_expectation_ = true; + bool add_framebuffer_expectation_ = true; + bool page_flip_expectation_ = true; + bool create_dumb_buffer_expectation_ = true; bool legacy_gamma_ramp_expectation_ = false; bool commit_expectation_ = true; bool modeset_with_overlays_expectation_ = true; - uint32_t current_framebuffer_; + uint32_t current_framebuffer_ = 0; absl::optional<std::string> driver_name_ = "mock";
diff --git a/ui/views/controls/button/checkbox.cc b/ui/views/controls/button/checkbox.cc index 7d16ae2..5525a2a 100644 --- a/ui/views/controls/button/checkbox.cc +++ b/ui/views/controls/button/checkbox.cc
@@ -183,7 +183,11 @@ SkPath Checkbox::GetFocusRingPath() const { SkPath path; gfx::Rect bounds = image()->GetMirroredContentsBounds(); - bounds.Inset(1); + // Don't add extra insets in the ChromeRefresh case so that the focus ring can + // be drawn in the ChromeRefresh style. + if (!features::IsChromeRefresh2023()) { + bounds.Inset(1); + } path.addRect(RectToSkRect(bounds)); return path; }
diff --git a/ui/webui/resources/cr_elements/cr_checkbox/cr_checkbox.html b/ui/webui/resources/cr_elements/cr_checkbox/cr_checkbox.html index de88e391..8d832bd 100644 --- a/ui/webui/resources/cr_elements/cr_checkbox/cr_checkbox.html +++ b/ui/webui/resources/cr_elements/cr_checkbox/cr_checkbox.html
@@ -114,7 +114,8 @@ } :host-context([chrome-refresh-2023]) #checkbox:focus-visible { - border: 2px solid var(--cr-focus-outline-color); + border: none; + outline: 2px solid var(--cr-focus-outline-color); } #checkmark { @@ -140,8 +141,7 @@ :host-context([chrome-refresh-2023]):host([checked]) #checkbox:focus-visible { background-clip: padding-box; - border-color: transparent; - outline: 2px solid var(--cr-focus-outline-color); + border: 2px solid transparent; } paper-ripple {
diff --git a/ui/webui/resources/cr_elements/cr_toggle/cr_toggle.html b/ui/webui/resources/cr_elements/cr_toggle/cr_toggle.html index 5413e78..8d3b34e 100644 --- a/ui/webui/resources/cr_elements/cr_toggle/cr_toggle.html +++ b/ui/webui/resources/cr_elements/cr_toggle/cr_toggle.html
@@ -201,6 +201,13 @@ --cr-toggle-knob-diameter_: 14px; } + :host-context([chrome-refresh-2023]):host([checked]:active) #knob, + :host-context([chrome-refresh-2023]):host([checked]:hover) #knob { + --cr-toggle-checked-button-color: + var(--color-toggle-button-thumb-on-hover-pressed, + var(--cr-fallback-color-primary-container)); + } + :host-context([chrome-refresh-2023]):host(:hover) #knob::before { background-color: var(--cr-hover-background-color); border-radius: 50%; @@ -213,7 +220,6 @@ width: var(--cr-toggle-ripple-diameter); } - paper-ripple { --paper-ripple-opacity: 1; color: var(--cr-toggle-unchecked-ripple-color);
diff --git a/weblayer/BUILD.gn b/weblayer/BUILD.gn index 3e43348..67d1f5bd 100644 --- a/weblayer/BUILD.gn +++ b/weblayer/BUILD.gn
@@ -413,6 +413,7 @@ "//components/content_capture/browser", "//components/content_capture/common", "//components/content_capture/renderer", + "//components/content_relationship_verification", "//components/content_settings/browser", "//components/content_settings/common:mojom", "//components/content_settings/common:mojom", @@ -421,7 +422,6 @@ "//components/crash/content/browser", "//components/crash/core/app", "//components/crash/core/common", - "//components/digital_asset_links", "//components/download/content/factory", "//components/download/content/public", "//components/download/public/background_service:public",
diff --git a/weblayer/browser/DEPS b/weblayer/browser/DEPS index a64f693..51f6bf2 100644 --- a/weblayer/browser/DEPS +++ b/weblayer/browser/DEPS
@@ -21,7 +21,7 @@ "+components/content_settings/core/common", "+components/crash/content/browser", "+components/crash/core/common", - "+components/digital_asset_links", + "+components/content_relationship_verification", "+components/download/content/factory", "+components/download/content/public", "+components/download/public/background_service",
diff --git a/weblayer/browser/java/BUILD.gn b/weblayer/browser/java/BUILD.gn index e8fefc86..47c2b9b 100644 --- a/weblayer/browser/java/BUILD.gn +++ b/weblayer/browser/java/BUILD.gn
@@ -231,11 +231,11 @@ "//components/browser_ui/widget/android:java", "//components/component_updater/android:embedded_component_loader_java", "//components/content_capture/android:java", + "//components/content_relationship_verification/android:java", "//components/content_settings/android:content_settings_enums_java", "//components/content_settings/android:java", "//components/crash/android:handler_java", "//components/crash/android:java", - "//components/digital_asset_links/android:java", "//components/download/internal/background_service:internal_java", "//components/download/internal/common:internal_java", "//components/download/network:network_java", @@ -424,9 +424,9 @@ "//base:base_java", "//base:base_java_test_support", "//base:base_junit_test_support", - "//components/digital_asset_links:java", - "//components/digital_asset_links/android:java", - "//components/digital_asset_links/android:junit_test_support", + "//components/content_relationship_verification:java", + "//components/content_relationship_verification/android:java", + "//components/content_relationship_verification/android:junit_test_support", "//components/embedder_support/android:util_java", "//components/payments/content/android:java", "//components/payments/content/android:junit_test_support",
diff --git a/weblayer/browser/java/DEPS b/weblayer/browser/java/DEPS index e4cb03bf..ff5151a4 100644 --- a/weblayer/browser/java/DEPS +++ b/weblayer/browser/java/DEPS
@@ -6,7 +6,7 @@ "+components/content_capture/android", "+components/content_settings/android/java", "+components/crash/android/java", - "+components/digital_asset_links/android/java", + "+components/content_relationship_verification/android/java", "+components/external_intents", "+components/infobars/android", "+components/location/android/java/src/org/chromium/components/location",
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/WebLayerOriginVerificationScheduler.java b/weblayer/browser/java/org/chromium/weblayer_private/WebLayerOriginVerificationScheduler.java index 96c7213..55a9dc8 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/WebLayerOriginVerificationScheduler.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/WebLayerOriginVerificationScheduler.java
@@ -8,9 +8,9 @@ import org.chromium.base.Callback; import org.chromium.base.ThreadUtils; -import org.chromium.components.digital_asset_links.OriginVerificationScheduler; -import org.chromium.components.digital_asset_links.OriginVerifier; -import org.chromium.components.digital_asset_links.OriginVerifierHelper; +import org.chromium.components.content_relationship_verification.OriginVerificationScheduler; +import org.chromium.components.content_relationship_verification.OriginVerifier; +import org.chromium.components.content_relationship_verification.OriginVerifierHelper; import org.chromium.components.embedder_support.util.Origin; import org.chromium.content_public.browser.BrowserContextHandle;
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/WebLayerOriginVerifier.java b/weblayer/browser/java/org/chromium/weblayer_private/WebLayerOriginVerifier.java index 8b24093..04709e7 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/WebLayerOriginVerifier.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/WebLayerOriginVerifier.java
@@ -12,8 +12,8 @@ import androidx.annotation.VisibleForTesting; import org.chromium.base.ContextUtils; -import org.chromium.components.digital_asset_links.OriginVerifier; -import org.chromium.components.digital_asset_links.Relationship; +import org.chromium.components.content_relationship_verification.OriginVerifier; +import org.chromium.components.content_relationship_verification.Relationship; import org.chromium.components.embedder_support.util.Origin; import org.chromium.components.embedder_support.util.UrlConstants; import org.chromium.content_public.browser.BrowserContextHandle;
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/WebLayerOriginVerifierTest.java b/weblayer/browser/java/org/chromium/weblayer_private/WebLayerOriginVerifierTest.java index 0a1f24f..a73b234 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/WebLayerOriginVerifierTest.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/WebLayerOriginVerifierTest.java
@@ -25,11 +25,11 @@ import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.JniMocker; -import org.chromium.components.digital_asset_links.OriginVerifier; -import org.chromium.components.digital_asset_links.OriginVerifier.OriginVerificationListener; -import org.chromium.components.digital_asset_links.OriginVerifierJni; -import org.chromium.components.digital_asset_links.OriginVerifierUnitTestSupport; -import org.chromium.components.digital_asset_links.RelationshipCheckResult; +import org.chromium.components.content_relationship_verification.OriginVerifier; +import org.chromium.components.content_relationship_verification.OriginVerifier.OriginVerificationListener; +import org.chromium.components.content_relationship_verification.OriginVerifierJni; +import org.chromium.components.content_relationship_verification.OriginVerifierUnitTestSupport; +import org.chromium.components.content_relationship_verification.RelationshipCheckResult; import org.chromium.components.embedder_support.util.Origin; import org.chromium.content_public.browser.BrowserContextHandle; import org.chromium.content_public.browser.test.util.TestThreadUtils;
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/WebLayerVerificationResultStore.java b/weblayer/browser/java/org/chromium/weblayer_private/WebLayerVerificationResultStore.java index fc79933..8dbe48c 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/WebLayerVerificationResultStore.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/WebLayerVerificationResultStore.java
@@ -4,7 +4,7 @@ package org.chromium.weblayer_private; -import org.chromium.components.digital_asset_links.VerificationResultStore; +import org.chromium.components.content_relationship_verification.VerificationResultStore; import java.util.Collections; import java.util.HashSet;
diff --git a/weblayer/browser/navigation_controller_impl.cc b/weblayer/browser/navigation_controller_impl.cc index 585b96a..3d29e46 100644 --- a/weblayer/browser/navigation_controller_impl.cc +++ b/weblayer/browser/navigation_controller_impl.cc
@@ -12,7 +12,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/task/sequenced_task_runner.h" #include "build/build_config.h" -#include "components/digital_asset_links/response_header_verifier.h" +#include "components/content_relationship_verification/response_header_verifier.h" #include "content/public/browser/navigation_controller.h" #include "content/public/browser/navigation_entry.h" #include "content/public/browser/navigation_handle.h" @@ -563,10 +563,10 @@ !navigation_handle->IsErrorPage()) { if (!navigation_handle->IsSameDocument()) { navigation->set_consenting_content( - digital_asset_links::ResponseHeaderVerifier::Verify( + content_relationship_verification::ResponseHeaderVerifier::Verify( tab_->browser()->GetPackageName(), navigation->GetNormalizedHeader( - digital_asset_links::kEmbedderAncestorHeader))); + content_relationship_verification::kEmbedderAncestorHeader))); } #if BUILDFLAG(IS_ANDROID) if (java_controller_) {
diff --git a/weblayer/browser/popup_navigation_delegate_impl.cc b/weblayer/browser/popup_navigation_delegate_impl.cc index 9becc401..6812e86 100644 --- a/weblayer/browser/popup_navigation_delegate_impl.cc +++ b/weblayer/browser/popup_navigation_delegate_impl.cc
@@ -33,7 +33,7 @@ return original_user_gesture_; } -const GURL& PopupNavigationDelegateImpl::GetURL() { +GURL PopupNavigationDelegateImpl::GetURL() { return params_.url; }
diff --git a/weblayer/browser/popup_navigation_delegate_impl.h b/weblayer/browser/popup_navigation_delegate_impl.h index b5651125..f745a03 100644 --- a/weblayer/browser/popup_navigation_delegate_impl.h +++ b/weblayer/browser/popup_navigation_delegate_impl.h
@@ -22,7 +22,7 @@ // blocked_content::PopupNavigationDelegate: content::RenderFrameHost* GetOpener() override; bool GetOriginalUserGesture() override; - const GURL& GetURL() override; + GURL GetURL() override; NavigateResult NavigateWithGesture( const blink::mojom::WindowFeatures& window_features, absl::optional<WindowOpenDisposition> updated_disposition) override;