diff --git a/DEPS b/DEPS index b75b5266..4f095c35 100644 --- a/DEPS +++ b/DEPS
@@ -276,11 +276,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'src_internal_revision': 'eaf7cb0f029bc20da46743fa0a0d8de6400b3dd4', + 'src_internal_revision': 'd3ffbdadbfe9840b0f0059171663afee4fb9fca7', # 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': 'e7b8d078851fd505475fe74359e31a421e6968ea', + 'skia_revision': '123e9e755027e173fc3dc63ea0a9fd28d1dc81ce', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. @@ -288,7 +288,7 @@ # 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': 'f094a81e4bd591801933a7ff08c093c4da5228cc', + 'angle_revision': '6551324044bc6a476d2d5ad372d34f49f6cba25e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -296,11 +296,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': '3cd0a262ce17171069d69eb839a0ab9f284c329c', + 'pdfium_revision': 'aacaea19d27cf8eca108348fe1e94dc03fc4aee8', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling BoringSSL # and whatever else without interference from each other. - 'boringssl_revision': '305e5c570be4b142e8590d37dd9136b60f12b9bc', + 'boringssl_revision': '571a7432a19592c620fa316abde47770dad4f82b', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Fuchsia sdk # and whatever else without interference from each other. @@ -352,7 +352,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling chromium_variations # and whatever else without interference from each other. - 'chromium_variations_revision': 'ad31f7ef5295293b73ada2c9da59fb550429061e', + 'chromium_variations_revision': 'c9db27d92e6a8f2428ca22f77ecc7942b35902f2', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling CrossBench # and whatever else without interference from each other. @@ -372,7 +372,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling devtools-frontend # and whatever else without interference from each other. - 'devtools_frontend_revision': 'f606d0ba4b8e681aab76ac63a1b643366de1aaa2', + 'devtools_frontend_revision': '0783a8d746d9264a8ee949cca7549ddff26d49cb', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libprotobuf-mutator # and whatever else without interference from each other. @@ -468,7 +468,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. - 'libcxxabi_revision': 'cbada99a33f015cb8333d63a88ff0c10cbbc6f38', + 'libcxxabi_revision': '8205ccf0f23545ebcd8846363ea1d29e77917a22', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -496,7 +496,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling llvm-libc # and whatever else without interference from each other. - 'llvm_libc_revision': '96cdfc15f0f8fc44cf40bd264278c09a5c243819', + 'llvm_libc_revision': 'b90022fc6a2c5309fae1a48d6db26bcd655cdb37', # If you change this, also update the libc++ revision in # //buildtools/deps_revisions.gni. @@ -1439,7 +1439,7 @@ 'src/clank': { 'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' + - '55a05617506990654db113866e78b0480b9b10f3', + 'c1dc9b6b30f065a36bba170249ef302124342b45', 'condition': 'checkout_android and checkout_src_internal', }, @@ -1598,7 +1598,7 @@ 'packages': [ { 'package': 'chromium/third_party/androidx', - 'version': '-w0Cd0kSVIwt62F0RV25hDfgYnx-WvsWUvh4_FOYZ50C', + 'version': 'WLOmaDhYcPWmWHNJbd89EFU3wpm3muMPkbkqKVANIT0C', }, ], 'condition': 'checkout_android and non_git_source', @@ -1934,7 +1934,7 @@ 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '4c54361841933e29ec19a3104e4f11f0e898674a', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '9a9142793a90d65cd1424f6826be89ec15bfa233', 'src/third_party/devtools-frontend/src': Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), @@ -2436,7 +2436,7 @@ Var('pdfium_git') + '/pdfium.git' + '@' + Var('pdfium_revision'), 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + 'efc96bb32403e5bd6200905cfb2b855d6e33959a', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '17e065a2f2b5997ed31042edbc7a73e639fe6bd3', 'src/base/tracing/test/data': { 'bucket': 'perfetto',
diff --git a/android_webview/browser/aw_field_trials.cc b/android_webview/browser/aw_field_trials.cc index 1ca5b37..14fa191c 100644 --- a/android_webview/browser/aw_field_trials.cc +++ b/android_webview/browser/aw_field_trials.cc
@@ -93,9 +93,11 @@ aw_feature_overrides.DisableFeature( net::features::kThirdPartyStoragePartitioning); +#if BUILDFLAG(ENABLE_VALIDATING_COMMAND_DECODER) // Disable the passthrough on WebView. aw_feature_overrides.DisableFeature( ::features::kDefaultPassthroughCommandDecoder); +#endif // HDR does not support webview yet. See crbug.com/1493153 for an explanation. aw_feature_overrides.DisableFeature(ui::kAndroidHDR);
diff --git a/android_webview/java/src/org/chromium/android_webview/AwLocaleConfig.java b/android_webview/java/src/org/chromium/android_webview/AwLocaleConfig.java index c61cc7919..7ed624c5 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwLocaleConfig.java +++ b/android_webview/java/src/org/chromium/android_webview/AwLocaleConfig.java
@@ -4,10 +4,13 @@ package org.chromium.android_webview; +import org.chromium.build.annotations.NullMarked; + /** * Simple class that provides access to the array of uncompressed pak locales. See * //android_webview/BUILD.gn for more details. */ +@NullMarked public final class AwLocaleConfig { private AwLocaleConfig() {}
diff --git a/android_webview/lib/BUILD.gn b/android_webview/lib/BUILD.gn index 127aa56..0e38f632 100644 --- a/android_webview/lib/BUILD.gn +++ b/android_webview/lib/BUILD.gn
@@ -33,7 +33,6 @@ "//components/spellcheck:buildflags", "//components/stylus_handwriting/android:android", "//components/variations", - "//components/variations:variations_associated_data", "//components/version_info", "//components/version_info/android:channel_getter", "//components/viz/common",
diff --git a/android_webview/test/data/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt b/android_webview/test/data/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt index 05faf7e..456fe572 100644 --- a/android_webview/test/data/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt +++ b/android_webview/test/data/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -115,6 +115,16 @@ getter currentTime getter duration method constructor +interface AsyncDisposableStack + attribute @@toStringTag + getter disposed + method Symbol(Symbol.asyncDispose) + method adopt + method constructor + method defer + method disposeAsync + method move + method use interface Attr : Node attribute @@toStringTag getter localName @@ -1588,6 +1598,16 @@ getter beta getter gamma method constructor +interface DisposableStack + attribute @@toStringTag + getter disposed + method Symbol(Symbol.dispose) + method adopt + method constructor + method defer + method dispose + method move + method use interface Document : Node static method parseHTMLUnsafe attribute @@toStringTag @@ -8435,6 +8455,10 @@ method unwrapKey method verify method wrapKey +interface SuppressedError : Error + attribute message + attribute name + method constructor interface SyncManager attribute @@toStringTag method constructor
diff --git a/android_webview/test/data/web_tests/webexposed/global-interface-listing-expected.txt b/android_webview/test/data/web_tests/webexposed/global-interface-listing-expected.txt index f09a82f..a8388a0d5 100644 --- a/android_webview/test/data/web_tests/webexposed/global-interface-listing-expected.txt +++ b/android_webview/test/data/web_tests/webexposed/global-interface-listing-expected.txt
@@ -238,6 +238,16 @@ getter duration method constructor method getCurrentTime +interface AsyncDisposableStack + attribute @@toStringTag + getter disposed + method Symbol(Symbol.asyncDispose) + method adopt + method constructor + method defer + method disposeAsync + method move + method use interface Attr : Node attribute @@toStringTag getter localName @@ -1882,6 +1892,16 @@ getter type method constructor method toString +interface DisposableStack + attribute @@toStringTag + getter disposed + method Symbol(Symbol.dispose) + method adopt + method constructor + method defer + method dispose + method move + method use interface Document : Node static method parseHTML static method parseHTMLUnsafe @@ -6665,6 +6685,7 @@ method fillRect method fillText method fillTextCluster + method getContextAttributes method getImageData method getLineDash method getTextureFormat @@ -9197,6 +9218,10 @@ method unwrapKey method verify method wrapKey +interface SuppressedError : Error + attribute message + attribute name + method constructor interface SyncManager attribute @@toStringTag method constructor
diff --git a/android_webview/tools/system_webview_shell/apk/src/org/chromium/webview_shell/WebViewBrowserActivity.java b/android_webview/tools/system_webview_shell/apk/src/org/chromium/webview_shell/WebViewBrowserActivity.java index 0adc047..c884e52d 100644 --- a/android_webview/tools/system_webview_shell/apk/src/org/chromium/webview_shell/WebViewBrowserActivity.java +++ b/android_webview/tools/system_webview_shell/apk/src/org/chromium/webview_shell/WebViewBrowserActivity.java
@@ -210,6 +210,8 @@ if (url != null) { String cookie = CookieManager.getInstance().getCookie(url); Log.w(TAG, "GetCookie: " + cookie); + Toast.makeText(this, "Printing cookie values to adb logcat", Toast.LENGTH_SHORT) + .show(); } else { Toast.makeText(this, "Error: Url is not set", Toast.LENGTH_SHORT).show(); }
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index e1246e38..3b2ce02 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -3418,6 +3418,7 @@ "//chromeos/ash/components/dbus/userdataauth:userdataauth", "//chromeos/ash/components/demo_mode", "//chromeos/ash/components/early_prefs", + "//chromeos/ash/components/editor_menu/public/cpp", "//chromeos/ash/components/emoji", "//chromeos/ash/components/feature_usage", "//chromeos/ash/components/fwupd", @@ -3458,7 +3459,6 @@ "//chromeos/ash/services/quick_pair/public/mojom", "//chromeos/ash/services/recording", "//chromeos/ash/services/recording/public/mojom", - "//chromeos/components/editor_menu/public/cpp", "//chromeos/components/kiosk", "//chromeos/components/magic_boost/public/cpp", "//chromeos/components/magic_boost/public/cpp/views", @@ -4661,6 +4661,7 @@ "//chromeos/ash/components/dbus/shill", "//chromeos/ash/components/dbus/userdataauth", "//chromeos/ash/components/dbus/userdataauth:userdataauth_proto", + "//chromeos/ash/components/editor_menu/public/cpp", "//chromeos/ash/components/emoji", "//chromeos/ash/components/emoji:resources_grit", "//chromeos/ash/components/feature_usage", @@ -4698,7 +4699,6 @@ "//chromeos/ash/services/nearby/public/cpp", "//chromeos/ash/services/network_config/public/cpp:test_support", "//chromeos/ash/services/recording:test_support", - "//chromeos/components/editor_menu/public/cpp", "//chromeos/components/magic_boost/public/cpp", "//chromeos/components/mahi/public/cpp", "//chromeos/components/sensors:sensors",
diff --git a/ash/DEPS b/ash/DEPS index 61d1be8a..4ebab32 100644 --- a/ash/DEPS +++ b/ash/DEPS
@@ -85,6 +85,7 @@ "+chromeos/ash/components/auth_panel", "+chromeos/ash/components/channel", "+chromeos/ash/components/cryptohome", + "+chromeos/ash/components/editor_menu", "+chromeos/ash/components/emoji", "+chromeos/ash/components/feature_usage", "+chromeos/ash/components/human_presence", @@ -98,7 +99,6 @@ "+chromeos/ash/components/proximity_auth", "+chromeos/ash/components/string_matching", "+chromeos/ash/components/system", - "+chromeos/components/editor_menu", "+chromeos/components/magic_boost", "+chromeos/components/mahi", "+chromeos/components/quick_answers",
diff --git a/ash/capture_mode/capture_mode_controller.cc b/ash/capture_mode/capture_mode_controller.cc index c22e71cc..55bad6c 100644 --- a/ash/capture_mode/capture_mode_controller.cc +++ b/ash/capture_mode/capture_mode_controller.cc
@@ -2118,7 +2118,11 @@ saved_video_file_path); } - auto reply = base::BindOnce(&RecordVideoFileSizeKB, is_gif, behavior); + // `behavior` could dangle here after the reply is received. Get the + // client metric component now, instead of after the reply is received, + // to prevent this. + auto reply = base::BindOnce(&RecordVideoFileSizeKB, is_gif, + behavior->GetClientMetricComponent()); if (on_file_saved_callback_for_test_) { reply = std::move(reply).Then( base::BindOnce(std::move(on_file_saved_callback_for_test_),
diff --git a/ash/capture_mode/capture_mode_metrics.cc b/ash/capture_mode/capture_mode_metrics.cc index 44cc5b00..c021eac8 100644 --- a/ash/capture_mode/capture_mode_metrics.cc +++ b/ash/capture_mode/capture_mode_metrics.cc
@@ -86,6 +86,21 @@ NudgeCatalogName::kCaptureModeEducationQuickSettingsNudge); } +std::string BuildHistogramNameInternal(const char* root_word, + const char* client_metric_component, + bool append_ui_mode_suffix) { + std::string histogram_name(kCaptureModeMetricCommonPrefix); + if (client_metric_component) { + histogram_name.append(client_metric_component); + } + histogram_name.append(root_word); + if (append_ui_mode_suffix) { + histogram_name.append(Shell::Get()->IsInTabletMode() ? ".TabletMode" + : ".ClamshellMode"); + } + return histogram_name; +} + } // namespace void RecordEndRecordingReason(EndRecordingReason reason) { @@ -152,7 +167,7 @@ } void RecordVideoFileSizeKB(bool is_gif, - const CaptureModeBehavior* behavior, + const char* client_metric_component, int size_in_kb) { if (!Shell::HasInstance()) { // This function can be called asynchronously after the `Shell` instance had @@ -166,9 +181,10 @@ } base::UmaHistogramMemoryKB( - BuildHistogramName(is_gif ? kGifRecordingFileSizeRootWord - : kScreenRecordingFileSizeRootWord, - behavior, /*append_ui_mode_suffix=*/true), + BuildHistogramNameInternal(is_gif ? kGifRecordingFileSizeRootWord + : kScreenRecordingFileSizeRootWord, + client_metric_component, + /*append_ui_mode_suffix=*/true), size_in_kb); } @@ -369,16 +385,9 @@ std::string BuildHistogramName(const char* const root_word, const CaptureModeBehavior* behavior, bool append_ui_mode_suffix) { - std::string histogram_name(kCaptureModeMetricCommonPrefix); - if (behavior) { - histogram_name.append(behavior->GetClientMetricComponent()); - } - histogram_name.append(root_word); - if (append_ui_mode_suffix) { - histogram_name.append(Shell::Get()->IsInTabletMode() ? ".TabletMode" - : ".ClamshellMode"); - } - return histogram_name; + return BuildHistogramNameInternal( + root_word, behavior ? behavior->GetClientMetricComponent() : nullptr, + append_ui_mode_suffix); } } // namespace ash
diff --git a/ash/capture_mode/capture_mode_metrics.h b/ash/capture_mode/capture_mode_metrics.h index bc1a60fc..7705940 100644 --- a/ash/capture_mode/capture_mode_metrics.h +++ b/ash/capture_mode/capture_mode_metrics.h
@@ -172,7 +172,7 @@ // Records the given video file `size_in_kb`. The used histogram will depend on // whether this video file was GIF or WebM. void RecordVideoFileSizeKB(bool is_gif, - const CaptureModeBehavior* behavior, + const char* client_metric_component, int size_in_kb); // Records if the user has switched modes during a capture session.
diff --git a/ash/capture_mode/capture_mode_unittests.cc b/ash/capture_mode/capture_mode_unittests.cc index 1ee168b..a932c35 100644 --- a/ash/capture_mode/capture_mode_unittests.cc +++ b/ash/capture_mode/capture_mode_unittests.cc
@@ -393,6 +393,25 @@ "Scanner", scanner_enabled ? "Enabled" : "Disabled"}); } +std::string SourceSunfishScannerTestName(CaptureModeSource source, + bool sunfish_enabled, + bool scanner_enabled) { + std::string test_name; + switch (source) { + case CaptureModeSource::kFullscreen: + test_name = "Fullscreen"; + break; + case CaptureModeSource::kRegion: + test_name = "Region"; + break; + case CaptureModeSource::kWindow: + test_name = "Window"; + break; + } + test_name += SunfishScannerTestName(sunfish_enabled, scanner_enabled); + return test_name; +} + class CaptureModeTest : public CaptureModeTestBase, public testing::WithParamInterface<std::tuple<bool, bool>> { @@ -2726,9 +2745,9 @@ EXPECT_EQ(capture_region_in_overview, gfx::ToRoundedRect(target_bounds)); } -class CaptureModeSaveFileTest - : public CaptureModeTestBase, - public testing::WithParamInterface<CaptureModeType> { +class CaptureModeSaveFileTest : public CaptureModeTestBase, + public testing::WithParamInterface< + std::tuple<CaptureModeType, bool, bool>> { public: CaptureModeSaveFileTest() = default; CaptureModeSaveFileTest( @@ -2736,15 +2755,23 @@ CaptureModeSaveFileTest& operator=(const CaptureModeSaveFileTest&) = delete; ~CaptureModeSaveFileTest() override = default; + // CaptureModeTestBase: + void SetUp() override { + auto [unused_type, sunfish_enabled, scanner_enabled] = GetParam(); + InitFeatures(sunfish_enabled, scanner_enabled); + CaptureModeTestBase::SetUp(); + } + void StartCaptureSessionWithParam() { - StartCaptureSession(CaptureModeSource::kFullscreen, GetParam()); + StartCaptureSession(CaptureModeSource::kFullscreen, + std::get<CaptureModeType>(GetParam())); } // Based on the `CaptureModeType`, it performs the capture and then returns // the path of the saved image or video files. base::FilePath PerformCapture() { auto* controller = CaptureModeController::Get(); - switch (GetParam()) { + switch (std::get<CaptureModeType>(GetParam())) { case CaptureModeType::kImage: controller->PerformCapture(); return WaitForCaptureFileToBeSaved(); @@ -2856,10 +2883,29 @@ } } -INSTANTIATE_TEST_SUITE_P(All, - CaptureModeSaveFileTest, - testing::Values(CaptureModeType::kImage, - CaptureModeType::kVideo)); +INSTANTIATE_TEST_SUITE_P( + All, + CaptureModeSaveFileTest, + testing::Combine(testing::Values(CaptureModeType::kImage, + CaptureModeType::kVideo), + testing::Bool(), + testing::Bool()), + [](const testing::TestParamInfo<CaptureModeSaveFileTest::ParamType>& info) { + auto type = std::get<CaptureModeType>(info.param); + bool sunfish_enabled = std::get<1>(info.param); + bool scanner_enabled = std::get<2>(info.param); + std::string test_name; + switch (type) { + case CaptureModeType::kImage: + test_name = "Image"; + break; + case CaptureModeType::kVideo: + test_name = "Video"; + break; + } + test_name += SunfishScannerTestName(sunfish_enabled, scanner_enabled); + return test_name; + }); // Test fixture for verifying that the videos are recorded at the pixel size of // the targets being captured in all recording modes. This avoids having the @@ -3094,15 +3140,17 @@ // Tests the behavior of screen recording with the presence of HDCP secure // content on the screen in all capture mode sources (fullscreen, region, and // window) depending on the test param. -class CaptureModeHdcpTest - : public CaptureModeTestBase, - public ::testing::WithParamInterface<CaptureModeSource> { +class CaptureModeHdcpTest : public CaptureModeTestBase, + public ::testing::WithParamInterface< + std::tuple<CaptureModeSource, bool, bool>> { public: CaptureModeHdcpTest() = default; ~CaptureModeHdcpTest() override = default; // CaptureModeTestBase: void SetUp() override { + auto [unused_source, sunfish_enabled, scanner_enabled] = GetParam(); + InitFeatures(sunfish_enabled, scanner_enabled); CaptureModeTestBase::SetUp(); window_ = CreateTestWindow(gfx::Rect(200, 200)); // Create a child window with protected content. This simulates the real @@ -3126,7 +3174,8 @@ // Enters the capture mode session. void StartSessionForVideo() { - StartCaptureSession(GetParam(), CaptureModeType::kVideo); + StartCaptureSession(std::get<CaptureModeSource>(GetParam()), + CaptureModeType::kVideo); } // Attempts video recording from the capture mode source set by the test @@ -3135,7 +3184,7 @@ auto* controller = CaptureModeController::Get(); ASSERT_TRUE(controller->IsActive()); - switch (GetParam()) { + switch (std::get<CaptureModeSource>(GetParam())) { case CaptureModeSource::kFullscreen: case CaptureModeSource::kRegion: controller->StartVideoRecordingImmediatelyForTesting(); @@ -3213,7 +3262,7 @@ // except when we're capturing a different |window_|. auto* controller = CaptureModeController::Get(); EXPECT_FALSE(controller->IsActive()); - if (GetParam() == CaptureModeSource::kWindow) { + if (std::get<CaptureModeSource>(GetParam()) == CaptureModeSource::kWindow) { WaitForRecordingToStart(); EXPECT_TRUE(controller->is_recording_in_progress()); controller->EndVideoRecording(EndRecordingReason::kStopRecordingButton); @@ -3267,7 +3316,7 @@ // Recording should be able to start (since the protected window is on the // first display) unless the protected window itself is the one being // recorded. - if (GetParam() == CaptureModeSource::kWindow) { + if (std::get<CaptureModeSource>(GetParam()) == CaptureModeSource::kWindow) { EXPECT_FALSE(controller->is_recording_in_progress()); } else { WaitForRecordingToStart(); @@ -3287,11 +3336,21 @@ } } -INSTANTIATE_TEST_SUITE_P(All, - CaptureModeHdcpTest, - testing::Values(CaptureModeSource::kFullscreen, - CaptureModeSource::kRegion, - CaptureModeSource::kWindow)); +INSTANTIATE_TEST_SUITE_P( + All, + CaptureModeHdcpTest, + testing::Combine(testing::Values(CaptureModeSource::kFullscreen, + CaptureModeSource::kRegion, + CaptureModeSource::kWindow), + testing::Bool(), + testing::Bool()), + [](const testing::TestParamInfo<CaptureModeHdcpTest::ParamType>& info) { + auto source = std::get<CaptureModeSource>(info.param); + bool sunfish_enabled = std::get<1>(info.param); + bool scanner_enabled = std::get<2>(info.param); + return SourceSunfishScannerTestName(source, sunfish_enabled, + scanner_enabled); + }); TEST_P(CaptureModeTest, ClosingWindowBeingRecorded) { auto window = CreateTestWindow(gfx::Rect(200, 200)); @@ -5550,10 +5609,10 @@ } // namespace -class ProjectorCaptureModeIntegrationTests : public CaptureModeTestBase { +class ProjectorCaptureModeIntegrationTestsBase : public CaptureModeTestBase { public: - ProjectorCaptureModeIntegrationTests() = default; - ~ProjectorCaptureModeIntegrationTests() override = default; + ProjectorCaptureModeIntegrationTestsBase() = default; + ~ProjectorCaptureModeIntegrationTestsBase() override = default; static constexpr gfx::Rect kUserRegion{20, 50, 60, 70}; @@ -5605,14 +5664,46 @@ base::HistogramTester histogram_tester_; }; +class ProjectorCaptureModeIntegrationTests + : public ProjectorCaptureModeIntegrationTestsBase, + public ::testing::WithParamInterface<std::tuple<bool, bool>> { + public: + // ProjectorCaptureModeIntegrationTestsBase: + void SetUp() override { + auto [sunfish_enabled, scanner_enabled] = GetParam(); + InitFeatures(sunfish_enabled, scanner_enabled); + ProjectorCaptureModeIntegrationTestsBase::SetUp(); + } +}; + +INSTANTIATE_TEST_SUITE_P( + , + ProjectorCaptureModeIntegrationTests, + testing::Combine(testing::Bool(), testing::Bool()), + [](const testing::TestParamInfo< + ProjectorCaptureModeIntegrationTests::ParamType>& info) { + bool sunfish_enabled = std::get<0>(info.param); + bool scanner_enabled = std::get<1>(info.param); + return SunfishScannerTestName(sunfish_enabled, scanner_enabled); + }); + class ProjectorCaptureModeIntegrationTestsWithSource - : public ProjectorCaptureModeIntegrationTests, - public ::testing::WithParamInterface<CaptureModeSource> {}; + : public ProjectorCaptureModeIntegrationTestsBase, + public ::testing::WithParamInterface< + std::tuple<CaptureModeSource, bool, bool>> { + public: + // ProjectorCaptureModeIntegrationTestsBase: + void SetUp() override { + auto [unused_source, sunfish_enabled, scanner_enabled] = GetParam(); + InitFeatures(sunfish_enabled, scanner_enabled); + ProjectorCaptureModeIntegrationTestsBase::SetUp(); + } +}; // static -constexpr gfx::Rect ProjectorCaptureModeIntegrationTests::kUserRegion; +constexpr gfx::Rect ProjectorCaptureModeIntegrationTestsBase::kUserRegion; -TEST_F(ProjectorCaptureModeIntegrationTests, EntryPoint) { +TEST_P(ProjectorCaptureModeIntegrationTests, EntryPoint) { // With the most recent source type set to kImage, starting capture mode for // the projector workflow will still force it to kVideo. auto* controller = CaptureModeController::Get(); @@ -5641,7 +5732,7 @@ // Tests that a fullscreen screenshot can be taken via the keyboard shortcut // while a Projector-initiated session is active without ending the session. -TEST_F(ProjectorCaptureModeIntegrationTests, FullscreenScreenshotKeyCombo) { +TEST_P(ProjectorCaptureModeIntegrationTests, FullscreenScreenshotKeyCombo) { StartProjectorModeSession(); PressAndReleaseKey(ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_CONTROL_DOWN); WaitForCaptureFileToBeSaved(); @@ -5654,7 +5745,7 @@ } // Tests that the settings view is simplified in projector mode. -TEST_F(ProjectorCaptureModeIntegrationTests, CaptureModeSettings) { +TEST_P(ProjectorCaptureModeIntegrationTests, CaptureModeSettings) { auto* controller = CaptureModeController::Get(); StartProjectorModeSession(); auto* event_generator = GetEventGenerator(); @@ -5677,7 +5768,7 @@ controller->GetEffectiveAudioRecordingMode()); } -TEST_F(ProjectorCaptureModeIntegrationTests, AudioCaptureDisabledByPolicy) { +TEST_P(ProjectorCaptureModeIntegrationTests, AudioCaptureDisabledByPolicy) { auto* controller = CaptureModeController::Get(); auto* delegate = static_cast<TestCaptureModeDelegate*>(controller->delegate_for_testing()); @@ -5690,7 +5781,7 @@ EXPECT_FALSE(projector_helper_.CanStartProjectorSession()); } -TEST_F(ProjectorCaptureModeIntegrationTests, +TEST_P(ProjectorCaptureModeIntegrationTests, AudioCaptureDisabledByPolicyAfterSessionStarts) { auto* controller = CaptureModeController::Get(); auto* delegate = @@ -5717,7 +5808,7 @@ // Tests the keyboard navigation for projector mode. The `image_toggle_button_` // in `CaptureModeTypeView` and the `Off` audio input option in // `CaptureModeSettingsView` are not available in projector mode. -TEST_F(ProjectorCaptureModeIntegrationTests, KeyboardNavigationBasic) { +TEST_P(ProjectorCaptureModeIntegrationTests, KeyboardNavigationBasic) { auto* controller = CaptureModeController::Get(); // Use `kFullscreen` here to minimize the number of tabs to reach the setting // button. @@ -5752,7 +5843,7 @@ settings_test_api.GetMicrophoneOption()); } -TEST_F(ProjectorCaptureModeIntegrationTests, BarButtonsState) { +TEST_P(ProjectorCaptureModeIntegrationTests, BarButtonsState) { auto* controller = CaptureModeController::Get(); StartProjectorModeSession(); EXPECT_TRUE(controller->IsActive()); @@ -5764,7 +5855,7 @@ EXPECT_TRUE(GetVideoToggleButton()->selected()); } -TEST_F(ProjectorCaptureModeIntegrationTests, StartEndRecording) { +TEST_P(ProjectorCaptureModeIntegrationTests, StartEndRecording) { auto* controller = CaptureModeController::Get(); controller->SetSource(CaptureModeSource::kFullscreen); StartProjectorModeSession(); @@ -5803,7 +5894,7 @@ /*expected_count=*/4); } -TEST_F(ProjectorCaptureModeIntegrationTests, +TEST_P(ProjectorCaptureModeIntegrationTests, ProjectorSessionNeverStartsWhenCaptureModeIsBlocked) { auto* controller = CaptureModeController::Get(); controller->SetSource(CaptureModeSource::kFullscreen); @@ -5820,7 +5911,7 @@ EXPECT_FALSE(controller->is_recording_in_progress()); } -TEST_F(ProjectorCaptureModeIntegrationTests, +TEST_P(ProjectorCaptureModeIntegrationTests, ProjectorSessionNeverStartsWhenVideoRecordingIsOnGoing) { auto* controller = StartCaptureSession(CaptureModeSource::kFullscreen, CaptureModeType::kVideo); @@ -5847,7 +5938,7 @@ // that include the capture mode type, capture mode source and capture mode // audio settings will not be overridden by the projector-initiated capture mode // session. -TEST_F(ProjectorCaptureModeIntegrationTests, +TEST_P(ProjectorCaptureModeIntegrationTests, RestoreCaptureSessionConfigurationsInNormalCaptureSession) { // Start an image capture mode session in window mode. auto* controller = @@ -5915,7 +6006,7 @@ } // namespace -TEST_F(ProjectorCaptureModeIntegrationTests, +TEST_P(ProjectorCaptureModeIntegrationTests, ProjectorSessionAbortedBeforeCountDownStarts) { auto* controller = CaptureModeController::Get(); controller->SetSource(CaptureModeSource::kFullscreen); @@ -5961,7 +6052,7 @@ /*expected_count=*/9); } -TEST_F(ProjectorCaptureModeIntegrationTests, +TEST_P(ProjectorCaptureModeIntegrationTests, ProjectorSessionAbortedAfterCountDownStarts) { ui::ScopedAnimationDurationScaleMode animation_scale( ui::ScopedAnimationDurationScaleMode::FAST_DURATION); @@ -6008,7 +6099,7 @@ /*expected_count=*/9); } -TEST_F(ProjectorCaptureModeIntegrationTests, AnnotationsOverlayWidget) { +TEST_P(ProjectorCaptureModeIntegrationTests, AnnotationsOverlayWidget) { auto* controller = CaptureModeController::Get(); controller->SetSource(CaptureModeSource::kFullscreen); StartProjectorModeSession(); @@ -6033,7 +6124,7 @@ VerifyOverlayEnabledState(overlay_window, /*overlay_enabled_state=*/false); } -TEST_F(ProjectorCaptureModeIntegrationTests, +TEST_P(ProjectorCaptureModeIntegrationTests, AnnotationsOverlayDockedMagnifier) { auto* controller = CaptureModeController::Get(); controller->SetSource(CaptureModeSource::kFullscreen); @@ -6073,7 +6164,7 @@ TEST_P(ProjectorCaptureModeIntegrationTestsWithSource, AnnotationsOverlayWidgetBounds) { - const auto capture_source = GetParam(); + const auto capture_source = std::get<CaptureModeSource>(GetParam()); StartRecordingForProjectorFromSource(capture_source); CaptureModeTestApi test_api; AnnotationsOverlayController* overlay_controller = @@ -6095,7 +6186,7 @@ display::Screen::GetScreen()->GetDisplayNearestWindow( Shell::GetAllRootWindows()[1])); - const auto capture_source = GetParam(); + const auto capture_source = std::get<CaptureModeSource>(GetParam()); StartRecordingForProjectorFromSource(capture_source); const auto roots = Shell::GetAllRootWindows(); EXPECT_EQ(roots[1], GetWindowBeingRecorded()->GetRootWindow()); @@ -6177,7 +6268,7 @@ // projector mode. TEST_P(ProjectorCaptureModeIntegrationTestsWithSource, NotShowRecordingInToteOrNotificationForProjectorMode) { - const auto capture_source = GetParam(); + const auto capture_source = std::get<CaptureModeSource>(GetParam()); StartRecordingForProjectorFromSource(capture_source); CaptureModeTestApi().StopVideoRecording(); WaitForCaptureFileToBeSaved(); @@ -6190,7 +6281,7 @@ // from projector in both clamshell and tablet mode. TEST_P(ProjectorCaptureModeIntegrationTestsWithSource, ProjectorCaptureConfigurationMetrics) { - const auto capture_source = GetParam(); + const auto capture_source = std::get<CaptureModeSource>(GetParam()); constexpr char kProjectorCaptureConfigurationHistogramBase[] = "CaptureConfiguration"; ash::CaptureModeTestApi test_api; @@ -6234,7 +6325,7 @@ // entering from projector in both clamshell and tablet mode. TEST_P(ProjectorCaptureModeIntegrationTestsWithSource, ProjectorScreenRecordingLengthMetrics) { - const auto capture_source = GetParam(); + const auto capture_source = std::get<CaptureModeSource>(GetParam()); constexpr char kProjectorRecordTimeHistogramBase[] = "ScreenRecordingLength"; ash::CaptureModeTestApi test_api; @@ -6265,7 +6356,7 @@ // Tests that metrics are recorded correctly for capture region adjustment // entering from projector in both clamshell and tablet mode. -TEST_F(ProjectorCaptureModeIntegrationTests, +TEST_P(ProjectorCaptureModeIntegrationTests, ProjectorCaptureRegionAdjustmentTest) { constexpr char kProjectorCaptureRegionAdjustmentHistogramBase[] = "CaptureRegionAdjusted"; @@ -6331,7 +6422,7 @@ // Tests that if the user is in projector mode, then presses the shortcut to // start default capture mode, it is ignored. -TEST_F(ProjectorCaptureModeIntegrationTests, SwitchToDefaultCaptureMode) { +TEST_P(ProjectorCaptureModeIntegrationTests, SwitchToDefaultCaptureMode) { StartProjectorModeSession(); VerifyActiveBehavior(BehaviorType::kProjector); PressAndReleaseKey(ui::VKEY_MEDIA_LAUNCH_APP1, @@ -6339,16 +6430,28 @@ VerifyActiveBehavior(BehaviorType::kProjector); } -INSTANTIATE_TEST_SUITE_P(All, - ProjectorCaptureModeIntegrationTestsWithSource, - testing::Values(CaptureModeSource::kFullscreen, - CaptureModeSource::kRegion, - CaptureModeSource::kWindow)); +INSTANTIATE_TEST_SUITE_P( + All, + ProjectorCaptureModeIntegrationTestsWithSource, + testing::Combine(testing::Values(CaptureModeSource::kFullscreen, + CaptureModeSource::kRegion, + CaptureModeSource::kWindow), + testing::Bool(), + testing::Bool()), -class AnnotatorCaptureModeIntegrationTests : public CaptureModeTestBase { + [](const testing::TestParamInfo< + ProjectorCaptureModeIntegrationTestsWithSource::ParamType>& info) { + auto source = std::get<CaptureModeSource>(info.param); + bool sunfish_enabled = std::get<1>(info.param); + bool scanner_enabled = std::get<2>(info.param); + return SourceSunfishScannerTestName(source, sunfish_enabled, + scanner_enabled); + }); + +class AnnotatorCaptureModeIntegrationTestsBase : public CaptureModeTestBase { public: - AnnotatorCaptureModeIntegrationTests() = default; - ~AnnotatorCaptureModeIntegrationTests() override = default; + AnnotatorCaptureModeIntegrationTestsBase() = default; + ~AnnotatorCaptureModeIntegrationTestsBase() override = default; static constexpr gfx::Rect kUserRegion{20, 50, 60, 70}; @@ -6395,11 +6498,43 @@ base::HistogramTester histogram_tester_; }; -class AnnotatorCaptureModeIntegrationTestsWithSource - : public AnnotatorCaptureModeIntegrationTests, - public ::testing::WithParamInterface<CaptureModeSource> {}; +class AnnotatorCaptureModeIntegrationTests + : public AnnotatorCaptureModeIntegrationTestsBase, + public ::testing::WithParamInterface<std::tuple<bool, bool>> { + public: + // AnnotatorCaptureModeIntegrationTestsBase: + void SetUp() override { + auto [sunfish_enabled, scanner_enabled] = GetParam(); + InitFeatures(sunfish_enabled, scanner_enabled); + AnnotatorCaptureModeIntegrationTestsBase::SetUp(); + } +}; -TEST_F(AnnotatorCaptureModeIntegrationTests, AnnotationsOverlayWidget) { +INSTANTIATE_TEST_SUITE_P( + , + AnnotatorCaptureModeIntegrationTests, + testing::Combine(testing::Bool(), testing::Bool()), + [](const testing::TestParamInfo< + AnnotatorCaptureModeIntegrationTests::ParamType>& info) { + bool sunfish_enabled = std::get<0>(info.param); + bool scanner_enabled = std::get<1>(info.param); + return SunfishScannerTestName(sunfish_enabled, scanner_enabled); + }); + +class AnnotatorCaptureModeIntegrationTestsWithSource + : public AnnotatorCaptureModeIntegrationTestsBase, + public ::testing::WithParamInterface< + std::tuple<CaptureModeSource, bool, bool>> { + public: + // AnnotatorCaptureModeIntegrationTestsBase: + void SetUp() override { + auto [unused_source, sunfish_enabled, scanner_enabled] = GetParam(); + InitFeatures(sunfish_enabled, scanner_enabled); + AnnotatorCaptureModeIntegrationTestsBase::SetUp(); + } +}; + +TEST_P(AnnotatorCaptureModeIntegrationTests, AnnotationsOverlayWidget) { StartRecordingFromSource(CaptureModeSource::kFullscreen); PressAndReleaseKey(ui::VKEY_RETURN); @@ -6421,7 +6556,7 @@ VerifyOverlayEnabledState(overlay_window, /*overlay_enabled_state=*/false); } -TEST_F(AnnotatorCaptureModeIntegrationTests, +TEST_P(AnnotatorCaptureModeIntegrationTests, AnnotationsOverlayDockedMagnifier) { StartRecordingFromSource(CaptureModeSource::kFullscreen); @@ -6485,7 +6620,7 @@ } // namespace -TEST_F(AnnotatorCaptureModeIntegrationTests, +TEST_P(AnnotatorCaptureModeIntegrationTests, AnnotationsOverlayWidgetTargeting) { StartRecordingFromSource(CaptureModeSource::kFullscreen); @@ -6542,7 +6677,7 @@ // Tests that auto hidden shelf can be brought back if user moves mouse to the // shelf activation area even while annotation is active. -TEST_F(AnnotatorCaptureModeIntegrationTests, +TEST_P(AnnotatorCaptureModeIntegrationTests, BringBackAutoHiddenShelfWhileAnnotationIsOn) { auto* root_window = Shell::GetPrimaryRootWindow(); // Set `shelf` to always auto-hidden. @@ -6609,7 +6744,7 @@ TEST_P(AnnotatorCaptureModeIntegrationTestsWithSource, AnnotationsOverlayWidgetBounds) { - const auto capture_source = GetParam(); + const auto capture_source = std::get<CaptureModeSource>(GetParam()); StartRecordingFromSource(capture_source); CaptureModeTestApi test_api; AnnotationsOverlayController* overlay_controller = @@ -6630,7 +6765,7 @@ display::Screen::GetScreen()->GetDisplayNearestWindow( Shell::GetAllRootWindows()[1])); - const auto capture_source = GetParam(); + const auto capture_source = std::get<CaptureModeSource>(GetParam()); StartRecordingFromSource(capture_source); const auto roots = Shell::GetAllRootWindows(); EXPECT_EQ(roots[1], GetWindowBeingRecorded()->GetRootWindow()); @@ -6643,20 +6778,32 @@ VerifyOverlayWindow(overlay_window, capture_source, kUserRegion); } -INSTANTIATE_TEST_SUITE_P(All, - AnnotatorCaptureModeIntegrationTestsWithSource, - testing::Values(CaptureModeSource::kFullscreen, - CaptureModeSource::kRegion, - CaptureModeSource::kWindow)); +INSTANTIATE_TEST_SUITE_P( + All, + AnnotatorCaptureModeIntegrationTestsWithSource, + testing::Combine(testing::Values(CaptureModeSource::kFullscreen, + CaptureModeSource::kRegion, + CaptureModeSource::kWindow), + testing::Bool(), + testing::Bool()), + + [](const testing::TestParamInfo< + AnnotatorCaptureModeIntegrationTestsWithSource::ParamType>& info) { + auto source = std::get<CaptureModeSource>(info.param); + bool sunfish_enabled = std::get<1>(info.param); + bool scanner_enabled = std::get<2>(info.param); + return SourceSunfishScannerTestName(source, sunfish_enabled, + scanner_enabled); + }); // ----------------------------------------------------------------------------- // CaptureModeSettingsTest: // Test fixture for CaptureMode settings view. -class CaptureModeSettingsTest : public CaptureModeTestBase { +class CaptureModeSettingsTestBase : public CaptureModeTestBase { public: - CaptureModeSettingsTest() = default; - ~CaptureModeSettingsTest() override = default; + CaptureModeSettingsTestBase() = default; + ~CaptureModeSettingsTestBase() override = default; // CaptureModeTestBase: void SetUp() override { @@ -6683,7 +6830,32 @@ } }; -TEST_F(CaptureModeSettingsTest, NudgeChangesRootWithBar) { +class CaptureModeSettingsTest + : public CaptureModeSettingsTestBase, + public testing::WithParamInterface<std::tuple<bool, bool>> { + public: + CaptureModeSettingsTest() = default; + ~CaptureModeSettingsTest() override = default; + + // CaptureModeSettingsTestBase: + void SetUp() override { + auto [sunfish_enabled, scanner_enabled] = GetParam(); + InitFeatures(sunfish_enabled, scanner_enabled); + CaptureModeSettingsTestBase::SetUp(); + } +}; + +INSTANTIATE_TEST_SUITE_P( + , + CaptureModeSettingsTest, + testing::Combine(testing::Bool(), testing::Bool()), + [](const testing::TestParamInfo<CaptureModeSettingsTest::ParamType>& info) { + bool sunfish_enabled = std::get<0>(info.param); + bool scanner_enabled = std::get<1>(info.param); + return SunfishScannerTestName(sunfish_enabled, scanner_enabled); + }); + +TEST_P(CaptureModeSettingsTest, NudgeChangesRootWithBar) { UpdateDisplay("800x700,801+0-800x700"); auto* event_generator = GetEventGenerator(); @@ -6710,7 +6882,7 @@ session->current_root()); } -TEST_F(CaptureModeSettingsTest, NudgeBehaviorWhenSelectingRegion) { +TEST_P(CaptureModeSettingsTest, NudgeBehaviorWhenSelectingRegion) { UpdateDisplay("800x700,801+0-800x700"); auto* event_generator = GetEventGenerator(); @@ -6743,7 +6915,7 @@ session->current_root()); } -TEST_F(CaptureModeSettingsTest, NudgeDoesNotShowForAllUserTypes) { +TEST_P(CaptureModeSettingsTest, NudgeDoesNotShowForAllUserTypes) { struct { std::string trace; user_manager::UserType user_type; @@ -6774,7 +6946,7 @@ // Tests that the capture mode settings menu is centered with respect to the // capture bar. -TEST_F(CaptureModeSettingsTest, SettingsMenuCenteredWithCaptureBar) { +TEST_P(CaptureModeSettingsTest, SettingsMenuCenteredWithCaptureBar) { StartCaptureSession(CaptureModeSource::kFullscreen, CaptureModeType::kImage); auto* bar_widget = GetCaptureModeBarWidget(); ASSERT_TRUE(bar_widget); @@ -6788,7 +6960,7 @@ // Tests that it's possbile to take a screenshot using the keyboard shortcut at // the login screen without any crashes. https://crbug.com/1266728. -TEST_F(CaptureModeSettingsTest, TakeScreenshotAtLoginScreen) { +TEST_P(CaptureModeSettingsTest, TakeScreenshotAtLoginScreen) { ClearLogin(); PressAndReleaseKey(ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_CONTROL_DOWN); WaitForCaptureFileToBeSaved(); @@ -6796,7 +6968,7 @@ // Tests that clicking on audio input buttons updates the state in the // controller, and persists between sessions. -TEST_F(CaptureModeSettingsTest, AudioInputSettingsMenu) { +TEST_P(CaptureModeSettingsTest, AudioInputSettingsMenu) { auto* controller = StartImageRegionCapture(); auto* event_generator = GetEventGenerator(); @@ -6828,7 +7000,7 @@ controller->GetEffectiveAudioRecordingMode()); } -TEST_F(CaptureModeSettingsTest, AccessibleName) { +TEST_P(CaptureModeSettingsTest, AccessibleName) { StartImageRegionCapture(); ClickOnView(GetSettingsButton(), GetEventGenerator()); CaptureModeSettingsTestApi test_api; @@ -6842,7 +7014,7 @@ data.GetString16Attribute(ax::mojom::StringAttribute::kName)); } -TEST_F(CaptureModeSettingsTest, AudioCaptureDisabledByPolicy) { +TEST_P(CaptureModeSettingsTest, AudioCaptureDisabledByPolicy) { auto* controller = CaptureModeController::Get(); // Even if audio recording is set to enabled, the policy setting will @@ -6869,7 +7041,7 @@ EXPECT_FALSE(test_api.GetMicrophoneOption()); } -TEST_F(CaptureModeSettingsTest, SelectFolderFromDialog) { +TEST_P(CaptureModeSettingsTest, SelectFolderFromDialog) { auto* controller = StartImageRegionCapture(); auto* event_generator = GetEventGenerator(); ClickOnView(GetSettingsButton(), event_generator); @@ -6914,7 +7086,7 @@ // Tests that folder selection dialog can be opened without crash while in // window capture mode. -TEST_F(CaptureModeSettingsTest, SelectFolderInWindowCaptureMode) { +TEST_P(CaptureModeSettingsTest, SelectFolderInWindowCaptureMode) { std::unique_ptr<aura::Window> window1( CreateTestWindow(gfx::Rect(0, 0, 200, 300))); StartCaptureSession(CaptureModeSource::kWindow, CaptureModeType::kImage); @@ -6926,7 +7098,7 @@ EXPECT_TRUE(IsFolderSelectionDialogShown()); } -TEST_F(CaptureModeSettingsTest, DismissDialogWithoutSelection) { +TEST_P(CaptureModeSettingsTest, DismissDialogWithoutSelection) { auto* controller = StartImageRegionCapture(); const auto old_capture_folder = controller->GetCurrentCaptureFolder(); @@ -6952,7 +7124,7 @@ new_capture_folder.is_default_downloads_folder); } -TEST_F(CaptureModeSettingsTest, AcceptUpdatedCustomFolderFromDialog) { +TEST_P(CaptureModeSettingsTest, AcceptUpdatedCustomFolderFromDialog) { // Start a new session with a pre-configured custom folder. auto* controller = CaptureModeController::Get(); const base::FilePath custom_folder( @@ -6996,7 +7168,7 @@ EXPECT_FALSE(capture_folder.is_default_downloads_folder); } -TEST_F(CaptureModeSettingsTest, +TEST_P(CaptureModeSettingsTest, InitializeSettingsViewWithUnavailableCustomFolder) { // Start a new session with a pre-configured unavailable custom folder. auto* controller = CaptureModeController::Get(); @@ -7043,7 +7215,7 @@ save_to_menu_group->GetOptionLabelForTesting(kCustomFolder)); } -TEST_F(CaptureModeSettingsTest, DeleteCustomFolderFromDialog) { +TEST_P(CaptureModeSettingsTest, DeleteCustomFolderFromDialog) { // Start a new session with a pre-configured custom folder. auto* controller = CaptureModeController::Get(); const base::FilePath custom_folder( @@ -7084,7 +7256,7 @@ EXPECT_TRUE(save_to_menu_group->IsOptionChecked(kDownloadsFolder)); } -TEST_F(CaptureModeSettingsTest, AccessibleCheckedStateChange) { +TEST_P(CaptureModeSettingsTest, AccessibleCheckedStateChange) { // Start a new session with a pre-configured custom folder. ui::AXNodeData data; auto* controller = CaptureModeController::Get(); @@ -7113,7 +7285,7 @@ EXPECT_EQ(data.GetCheckedState(), ax::mojom::CheckedState::kFalse); } -TEST_F(CaptureModeSettingsTest, AcceptDefaultDownloadsFolderFromDialog) { +TEST_P(CaptureModeSettingsTest, AcceptDefaultDownloadsFolderFromDialog) { // Start a new session with a pre-configured custom folder. auto* controller = CaptureModeController::Get(); controller->SetCustomCaptureFolder( @@ -7140,7 +7312,7 @@ EXPECT_TRUE(save_to_menu_group->IsOptionChecked(kDownloadsFolder)); } -TEST_F(CaptureModeSettingsTest, SwitchWhichFolderToUserFromOptions) { +TEST_P(CaptureModeSettingsTest, SwitchWhichFolderToUserFromOptions) { // Start a new session with a pre-configured custom folder. auto* controller = CaptureModeController::Get(); const base::FilePath custom_path( @@ -7177,7 +7349,13 @@ // Tests that when there's no overlap betwwen capture label widget and settings // widget, capture label widget is shown/hidden correctly after open/close the // folder selection window. -TEST_F(CaptureModeSettingsTest, CaptureLabelViewNotOverlapsWithSettingsView) { +TEST_P(CaptureModeSettingsTest, CaptureLabelViewNotOverlapsWithSettingsView) { + auto [sunfish_enabled, scanner_enabled] = GetParam(); + if (sunfish_enabled || scanner_enabled) { + // This test crashes when either Sunfish or Scanner is enabled. + // TODO: b/381965299 - Fix these test failures. + GTEST_SKIP(); + } // Update the display size to make sure capture label widget will not // overlap with settings widget UpdateDisplay("800x600"); @@ -7226,7 +7404,7 @@ // label widget is shown/hidden correctly after open/close the folder selection // window, open/close settings menu. Regression test for // https://crbug.com/1279606. -TEST_F(CaptureModeSettingsTest, CaptureLabelViewOverlapsWithSettingsView) { +TEST_P(CaptureModeSettingsTest, CaptureLabelViewOverlapsWithSettingsView) { // Update display size to make capture label widget overlap with settings // widget. UpdateDisplay("1100x700"); @@ -7263,7 +7441,7 @@ controller->Stop(); } -TEST_F(CaptureModeSettingsTest, PressingEnterSelectsFocusedItem) { +TEST_P(CaptureModeSettingsTest, PressingEnterSelectsFocusedItem) { auto* controller = StartCaptureSession(CaptureModeSource::kRegion, CaptureModeType::kImage); @@ -7308,7 +7486,7 @@ } // Tests the basic keyboard navigation functions for the settings menu. -TEST_F(CaptureModeSettingsTest, KeyboardNavigationForSettingsMenu) { +TEST_P(CaptureModeSettingsTest, KeyboardNavigationForSettingsMenu) { auto* controller = StartCaptureSession(CaptureModeSource::kRegion, CaptureModeType::kImage); @@ -7402,7 +7580,7 @@ // Tests that the disabled option in the settings menu will be skipped while // tabbing through. -TEST_F(CaptureModeSettingsTest, +TEST_P(CaptureModeSettingsTest, KeyboardNavigationForSettingsMenuWithDisabledOption) { // Start a new session with a pre-configured unavailable custom folder. auto* controller = CaptureModeController::Get(); @@ -7460,7 +7638,7 @@ // Tests that selecting the default `Downloads` folder as the custom folder via // keyboard navigation doesn't lead to a crash. Regression test for // https://crbug.com/1269373. -TEST_F(CaptureModeSettingsTest, +TEST_P(CaptureModeSettingsTest, KeyboardNavigationForRemovingCustomFolderOption) { // Start a new session with a pre-configured custom folder. auto* controller = CaptureModeController::Get(); @@ -7521,7 +7699,7 @@ // Tests that first time selecting a custom folder via keyboard navigation. // After the custom folder is selected, tabbing one more time will move focus // from the settings menu to the settings button. -TEST_F(CaptureModeSettingsTest, KeyboardNavigationForAddingCustomFolderOption) { +TEST_P(CaptureModeSettingsTest, KeyboardNavigationForAddingCustomFolderOption) { auto* controller = CaptureModeController::Get(); StartImageRegionCapture(); @@ -7579,7 +7757,7 @@ } // Tests the folder selection settings when it's recommended by policy. -TEST_F(CaptureModeSettingsTest, FolderRecommendedByPolicy) { +TEST_P(CaptureModeSettingsTest, FolderRecommendedByPolicy) { auto* controller = StartImageRegionCapture(); // Set the pref to recommended values. @@ -7613,7 +7791,7 @@ } // Tests the folder selection settings when it's enforced by policy. -TEST_F(CaptureModeSettingsTest, FolderSetByPolicy) { +TEST_P(CaptureModeSettingsTest, FolderSetByPolicy) { auto* controller = StartImageRegionCapture(); // Set the pref to managed values. @@ -7651,17 +7829,21 @@ // Test fixture to verify screen capture histograms depending on the test // param (true for tablet mode, false for clamshell mode). -class CaptureModeHistogramTest : public CaptureModeSettingsTest, - public ::testing::WithParamInterface<bool> { +class CaptureModeHistogramTest + : public CaptureModeSettingsTestBase, + public ::testing::WithParamInterface<std::tuple<bool, bool, bool>> { public: CaptureModeHistogramTest() = default; ~CaptureModeHistogramTest() override = default; - // CaptureModeSettingsTest: + // CaptureModeSettingsTestBase: void SetUp() override { - CaptureModeSettingsTest::SetUp(); - if (GetParam()) + auto [unused_is_tablet, sunfish_enabled, scanner_enabled] = GetParam(); + InitFeatures(sunfish_enabled, scanner_enabled); + CaptureModeSettingsTestBase::SetUp(); + if (std::get<0>(GetParam())) { SwitchToTabletMode(); + } } void StartSessionForVideo() { @@ -7675,10 +7857,11 @@ void OpenView(const views::View* view, ui::test::EventGenerator* event_generator) { - if (GetParam()) + if (std::get<0>(GetParam())) { TouchOnView(view, event_generator); - else + } else { ClickOnView(view, event_generator); + } } }; @@ -7886,6 +8069,18 @@ CaptureModeSwitchToDefaultReason::kUserSelectedFromSettingsMenu, 1); } -INSTANTIATE_TEST_SUITE_P(All, CaptureModeHistogramTest, ::testing::Bool()); +INSTANTIATE_TEST_SUITE_P( + All, + CaptureModeHistogramTest, + testing::Combine(testing::Bool(), testing::Bool(), testing::Bool()), + [](const testing::TestParamInfo<CaptureModeHistogramTest::ParamType>& + info) { + bool is_tablet_mode = std::get<0>(info.param); + bool sunfish_enabled = std::get<1>(info.param); + bool scanner_enabled = std::get<2>(info.param); + std::string test_name = is_tablet_mode ? "Tablet" : "Clamshell"; + test_name += SunfishScannerTestName(sunfish_enabled, scanner_enabled); + return test_name; + }); } // namespace ash
diff --git a/ash/quick_insert/model/quick_insert_model.cc b/ash/quick_insert/model/quick_insert_model.cc index df0ec33..e64a30a9 100644 --- a/ash/quick_insert/model/quick_insert_model.cc +++ b/ash/quick_insert/model/quick_insert_model.cc
@@ -8,7 +8,7 @@ #include "ash/quick_insert/model/quick_insert_mode_type.h" #include "ash/quick_insert/quick_insert_category.h" #include "base/check_deref.h" -#include "chromeos/components/editor_menu/public/cpp/editor_helpers.h" +#include "chromeos/ash/components/editor_menu/public/cpp/editor_helpers.h" #include "components/prefs/pref_service.h" #include "ui/base/ime/ash/ime_keyboard.h" #include "ui/base/ime/text_input_client.h"
diff --git a/ash/quick_insert/views/quick_insert_emoji_bar_view.cc b/ash/quick_insert/views/quick_insert_emoji_bar_view.cc index cc4a725..e143b17 100644 --- a/ash/quick_insert/views/quick_insert_emoji_bar_view.cc +++ b/ash/quick_insert/views/quick_insert_emoji_bar_view.cc
@@ -34,9 +34,11 @@ #include "ui/base/metadata/metadata_header_macros.h" #include "ui/base/metadata/metadata_impl_macros.h" #include "ui/chromeos/styles/cros_tokens_color_mappings.h" +#include "ui/gfx/canvas.h" #include "ui/gfx/geometry/insets.h" #include "ui/gfx/geometry/rounded_corners_f.h" #include "ui/gfx/geometry/size.h" +#include "ui/gfx/geometry/skia_conversions.h" #include "ui/gfx/text_constants.h" #include "ui/views/accessibility/view_accessibility.h" #include "ui/views/background.h" @@ -204,13 +206,26 @@ : kGifsButtonIconSize + kGifsButtonIconLabelSpacing), max_height); } + void PaintButtonContents(gfx::Canvas* canvas) override { + views::LabelButton::PaintButtonContents(canvas); + + if (is_checked_ && + GetState() == views::Button::ButtonState::STATE_HOVERED) { + SkPath mask; + mask.addRoundRect(gfx::RectToSkRect(GetLocalBounds()), + kGifsButtonCornerRadius, kGifsButtonCornerRadius); + canvas->ClipPath(mask, true); + canvas->DrawColor( + GetColorProvider()->GetColor(cros_tokens::kCrosSysHoverOnSubtle)); + } + } void UpdateBackground() { SetBackground(views::CreateThemedRoundedRectBackground( - GetState() == views::Button::ButtonState::STATE_HOVERED - ? cros_tokens::kCrosSysHoverOnSubtle - : (is_checked_ ? cros_tokens::kCrosSysSystemPrimaryContainer - : cros_tokens::kCrosSysSystemOnBase), + (is_checked_ ? cros_tokens::kCrosSysSystemPrimaryContainer + : (GetState() == views::Button::ButtonState::STATE_HOVERED + ? cros_tokens::kCrosSysHoverOnSubtle + : cros_tokens::kCrosSysSystemOnBase)), kGifsButtonCornerRadius)); }
diff --git a/ash/quick_insert/views/quick_insert_section_view.cc b/ash/quick_insert/views/quick_insert_section_view.cc index 06a4cd6..0a27035 100644 --- a/ash/quick_insert/views/quick_insert_section_view.cc +++ b/ash/quick_insert/views/quick_insert_section_view.cc
@@ -33,7 +33,7 @@ #include "base/ranges/algorithm.h" #include "base/strings/utf_string_conversions.h" #include "build/branding_buildflags.h" -#include "chromeos/components/editor_menu/public/cpp/icon.h" +#include "chromeos/ash/components/editor_menu/public/cpp/icon.h" #include "chromeos/ui/base/file_icon_util.h" #include "chromeos/ui/vector_icons/vector_icons.h" #include "components/url_formatter/url_formatter.h"
diff --git a/ash/quick_insert/views/quick_insert_zero_state_view.cc b/ash/quick_insert/views/quick_insert_zero_state_view.cc index 47a0d67..790572e 100644 --- a/ash/quick_insert/views/quick_insert_zero_state_view.cc +++ b/ash/quick_insert/views/quick_insert_zero_state_view.cc
@@ -37,7 +37,7 @@ #include "base/functional/callback.h" #include "base/memory/weak_ptr.h" #include "base/time/time.h" -#include "chromeos/components/editor_menu/public/cpp/preset_text_query.h" +#include "chromeos/ash/components/editor_menu/public/cpp/preset_text_query.h" #include "chromeos/ui/vector_icons/vector_icons.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h"
diff --git a/ash/quick_insert/views/quick_insert_zero_state_view_unittest.cc b/ash/quick_insert/views/quick_insert_zero_state_view_unittest.cc index 4b13231..ddaea0f 100644 --- a/ash/quick_insert/views/quick_insert_zero_state_view_unittest.cc +++ b/ash/quick_insert/views/quick_insert_zero_state_view_unittest.cc
@@ -37,7 +37,7 @@ #include "base/test/task_environment.h" #include "base/test/test_future.h" #include "build/branding_buildflags.h" -#include "chromeos/components/editor_menu/public/cpp/preset_text_query.h" +#include "chromeos/ash/components/editor_menu/public/cpp/preset_text_query.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/testing_pref_service.h" #include "testing/gmock/include/gmock/gmock-matchers.h"
diff --git a/ash/wm/overview/overview_session_unittest.cc b/ash/wm/overview/overview_session_unittest.cc index 29918d1..c19289ef 100644 --- a/ash/wm/overview/overview_session_unittest.cc +++ b/ash/wm/overview/overview_session_unittest.cc
@@ -1233,6 +1233,26 @@ EXPECT_TRUE(window2->IsVisible()); } +// Tests that showing the non-forcefully hidden windows will not crash. The +// regression test of crbug.com/372335240. +TEST_P(OverviewSessionTest, NoCrashOnShowingNonForceHiddenWindows) { + std::unique_ptr<aura::Window> window(CreateTestWindow()); + window->SetProperty(kHideInOverviewKey, true); + + // Enter overview. + ToggleOverview(); + + // The second window should be hidden. + EXPECT_FALSE(window->IsVisible()); + + // Showing and focusing on the second window should exit Overview without + // crash. Here we simulate the process of `SystemWebDialogDelegate::Focus`. + window->Show(); + window->Focus(); + EXPECT_FALSE(InOverviewSession()); + EXPECT_TRUE(window->IsVisible()); +} + // Tests that a minimized window's visibility and layer visibility // stay invisible (A minimized window is cloned during overview). TEST_P(OverviewSessionTest, MinimizedWindowState) {
diff --git a/ash/wm/overview/scoped_overview_hide_windows.cc b/ash/wm/overview/scoped_overview_hide_windows.cc index d0d49f1..934a910 100644 --- a/ash/wm/overview/scoped_overview_hide_windows.cc +++ b/ash/wm/overview/scoped_overview_hide_windows.cc
@@ -74,17 +74,22 @@ void ScopedOverviewHideWindows::OnWindowVisibilityChanged(aura::Window* window, bool visible) { - if (!visible) + if (!visible) { return; + } // If it's not one of the registered windows, then it must be a child of the // registered windows. Early return in this case. - if (!HasWindow(window)) + if (!HasWindow(window)) { return; + } - // It's expected that windows hidden in overview, unless they are forcefully - // hidden should not be shown while in overview. - CHECK(force_hidden_); + // If the window is not forcefully hidden, we remove it from observations. + // Otherwise, keep it hidden and update the visibility. + if (!force_hidden_) { + RemoveWindow(window, visible); + return; + } // Do not let |window| change to visible during the lifetime of |this|. Also // update |window_visibility_| so that we can restore the window visibility
diff --git a/build/android/BUILD.gn b/build/android/BUILD.gn index db7fe9e4..d10371e 100644 --- a/build/android/BUILD.gn +++ b/build/android/BUILD.gn
@@ -46,7 +46,6 @@ sources = [ "java/src/org/chromium/build/NullUtil.java", "java/src/org/chromium/build/annotations/AlwaysInline.java", - "java/src/org/chromium/build/annotations/AssumeNonNull.java", "java/src/org/chromium/build/annotations/CheckDiscard.java", "java/src/org/chromium/build/annotations/Contract.java", "java/src/org/chromium/build/annotations/DoNotClassMerge.java", @@ -60,6 +59,7 @@ "java/src/org/chromium/build/annotations/NullMarked.java", "java/src/org/chromium/build/annotations/NullUnmarked.java", "java/src/org/chromium/build/annotations/Nullable.java", + "java/src/org/chromium/build/annotations/OptimizeAsNonNull.java", "java/src/org/chromium/build/annotations/RequiresNonNull.java", "java/src/org/chromium/build/annotations/ServiceImpl.java", "java/src/org/chromium/build/annotations/UsedByReflection.java",
diff --git a/build/android/chromium_annotations.flags b/build/android/chromium_annotations.flags index 99a670b1..a7e160f 100644 --- a/build/android/chromium_annotations.flags +++ b/build/android/chromium_annotations.flags
@@ -63,14 +63,14 @@ # Use assumevalues in addition to assumenosideeffects block because Google3 proguard cannot parse # assumenosideeffects blocks which overwrite return value. -assumevalues class ** { - @org.chromium.build.annotations.AssumeNonNull *** *(...) return _NONNULL_; + @org.chromium.build.annotations.OptimizeAsNonNull *** *(...) return _NONNULL_; } -assumenosideeffects class ** { - @org.chromium.build.annotations.AssumeNonNull *** *(...); + @org.chromium.build.annotations.OptimizeAsNonNull *** *(...); } -assumevalues class ** { - @org.chromium.build.annotations.AssumeNonNull *** * return _NONNULL_; + @org.chromium.build.annotations.OptimizeAsNonNull *** * return _NONNULL_; } -assumenosideeffects class ** { - @org.chromium.build.annotations.AssumeNonNull *** *; + @org.chromium.build.annotations.OptimizeAsNonNull *** *; }
diff --git a/build/android/docs/static_analysis.md b/build/android/docs/static_analysis.md index f67cb46..9703e05 100644 --- a/build/android/docs/static_analysis.md +++ b/build/android/docs/static_analysis.md
@@ -19,20 +19,25 @@ [within `lint.py`]: https://source.chromium.org/chromium/chromium/src/+/main:build/android/gyp/lint.py;l=25 [`lint-baseline.xml`]: https://source.chromium.org/search?q=f:lint-baseline.xml%20-f:third_party -## [ErrorProne](https://errorprone.info/) +## [ErrorProne] * Runs as part of normal compilation. * Controlled by GN arg: `use_errorprone_java_compiler` (or `android_static_analysis`). -* [Useful checks include](https://errorprone.info/bugpatterns): +* [Useful checks include]: + * Checking correctness of [nullable annotations] (via NullAway plugin). * Enforcement of `@GuardedBy`, `@CheckReturnValue`, and `@DoNotMock`. * Enforcement of `/* paramName= */` comments. -* A list of enabled / disabled checks is found [within `compile_java.py`](https://cs.chromium.org/chromium/src/build/android/gyp/compile_java.py?l=30) +* A list of enabled / disabled checks is found [within `compile_java.py`] * Many checks are currently disabled because there is work involved in fixing violations they introduce. Please help! -* Chrome has [a few custom checks]: +* Chrome has [a few custom checks]. * Checks run on the entire codebase, not only on changed lines. * Does not run when `chromium_code = false` (e.g. for `//third_party`). +[ErrorProne]: https://errorprone.info/ +[Useful checks include]: https://errorprone.info/bugpatterns +[nullable annotations]: /styleguide/java/nullaway.md +[within `compile_java.py`]: https://source.chromium.org/chromium/chromium/src/+/main:build/android/gyp/compile_java.py;l=46;drc=5dc479e73c3c9c03b59f324b2e349b8bd008401f [a few custom checks]: /tools/android/errorprone_plugin/src/org/chromium/tools/errorprone/plugin/ ## [Checkstyle](https://checkstyle.sourceforge.io/)
diff --git a/build/android/java/src/org/chromium/build/annotations/AssumeNonNull.java b/build/android/java/src/org/chromium/build/annotations/OptimizeAsNonNull.java similarity index 75% rename from build/android/java/src/org/chromium/build/annotations/AssumeNonNull.java rename to build/android/java/src/org/chromium/build/annotations/OptimizeAsNonNull.java index 37eb1117..6fe0479 100644 --- a/build/android/java/src/org/chromium/build/annotations/AssumeNonNull.java +++ b/build/android/java/src/org/chromium/build/annotations/OptimizeAsNonNull.java
@@ -9,7 +9,7 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -/** The annotated field is never null. Helps R8 optimize until b/302213229 is implemented. */ +/** The annotated method or field is never null. Helps R8 optimize until b/302213229 is implemented. */ @Target({ElementType.FIELD, ElementType.METHOD}) @Retention(RetentionPolicy.CLASS) -public @interface AssumeNonNull {} +public @interface OptimizeAsNonNull {}
diff --git a/build/android/pylib/local/device/local_device_gtest_run_test.py b/build/android/pylib/local/device/local_device_gtest_run_test.py index dc947e73..bc78184 100755 --- a/build/android/pylib/local/device/local_device_gtest_run_test.py +++ b/build/android/pylib/local/device/local_device_gtest_run_test.py
@@ -17,8 +17,10 @@ from pylib.gtest import gtest_test_instance from pylib.local.device import local_device_environment from pylib.local.device import local_device_gtest_run +from pylib.local.device import local_device_test_run import mock # pylint: disable=import-error +from unittest.mock import MagicMock def isSliceInList(s, l): @@ -132,26 +134,41 @@ class LocalDeviceGtestTestRunShardingTest(unittest.TestCase): def setUp(self): + self._env = mock.MagicMock( + spec=local_device_environment.LocalDeviceEnvironment) + self._test_instance = mock.MagicMock( + spec=gtest_test_instance.GtestTestInstance) self._obj = local_device_gtest_run.LocalDeviceGtestRun( - mock.MagicMock(spec=local_device_environment.LocalDeviceEnvironment), - mock.MagicMock(spec=gtest_test_instance.GtestTestInstance)) + self._env, self._test_instance) - def test_CreateShardsForDevices(self): - self._obj._env.devices = [1] - self._obj._test_instance.test_launcher_batch_limit = 2 - tests = [ + self.test_list = [ 'TestClass1.testcase1', 'TestClass2.testcase1', 'TestClass1.def_testcase3', 'TestClass1.abc_testcase2', 'TestClass3.testcase1' ] + + # Mock these methods called in RunTests + self._env.ResetCurrentTry = MagicMock(side_effect = self.reset_try) + self._env.IncrementCurrentTry = MagicMock(side_effect = self.increment_try) + self._obj._GetTests = MagicMock(return_value=self.test_list) + + def reset_try(self): + self._env.current_try = 0 + + def increment_try(self): + self._env.current_try += 1 + + def test_CreateShardsForDevices(self): + self._obj._env.devices = [1] + self._obj._test_instance.test_launcher_batch_limit = 2 expected_shards = [ ['TestClass1.testcase1', 'TestClass2.testcase1'], ['TestClass1.def_testcase3', 'TestClass1.abc_testcase2'], ['TestClass3.testcase1'] ] - actual_shards = self._obj._CreateShardsForDevices(tests) + actual_shards = self._obj._CreateShardsForDevices(self.test_list) self.assertEqual(expected_shards, actual_shards) def test_ApplyExternalSharding_1_shard(self): @@ -182,6 +199,57 @@ self.assertEqual(expected_shard1, expected_shard1) self.assertSetEqual(set(actual_shard0 + actual_shard1), set(tests)) + def test_deterministic_sharding_grouped_tests(self): + self._test_instance.external_shard_index = 0 + self._test_instance.total_external_shards = 1 + self._test_instance.test_launcher_batch_limit = 2 + self._env.devices = [1] + self._env.recover_devices = False + # 1 try and just the last try of mock_RunTestsOnDevice call is asserted + self._env.max_tries = 1 + + expected_shards = [ + ['TestClass1.def_testcase3', 'TestClass1.abc_testcase2'], + ['TestClass1.testcase1', 'TestClass3.testcase1'], + ['TestClass2.testcase1'] + ] + + # Mock pMap to call the provided function + def mock_pMap(func, *args): + for _ in self._env.devices: + func(*args) + return MagicMock() + + # Process test collection arg of last mock_RunTestsOnDevice call + def get_actual_shards(): + actual_shards = [] + # mock_RunTestsOnDevice must be called for call_args to not be None + mock_RunTestsOnDevice.assert_called() + tc = mock_RunTestsOnDevice.call_args.args[0] + for group in tc: + actual_shards.append(group) + tc.test_completed() + return actual_shards + + mock_RunTestsOnDevice = MagicMock( + autospec='local_device_test_run.LocalDeviceTestRun._RunTestsOnDevice') + # Monkey patch needed to call mock. Decorator patch calls original method + # instead of mock possibly due to decorator or pMap on original method. + (local_device_test_run.LocalDeviceTestRun + ._RunTestsOnDevice) = mock_RunTestsOnDevice + + with mock.patch.object( + self._env.parallel_devices, "pMap", side_effect=mock_pMap + ): + self._obj.RunTests(results=[]) + actual_shards = get_actual_shards() + self.assertEqual(actual_shards, expected_shards) + + # Check "Retry shards with patch" has deterministic test ordering + self._obj.RunTests(results=[]) + actual_shards = get_actual_shards() + self.assertEqual(actual_shards, expected_shards) + if __name__ == '__main__': unittest.main(verbosity=2)
diff --git a/build/android/pylib/local/device/local_device_instrumentation_test_run_test.py b/build/android/pylib/local/device/local_device_instrumentation_test_run_test.py index 9111b12..5f5e746 100755 --- a/build/android/pylib/local/device/local_device_instrumentation_test_run_test.py +++ b/build/android/pylib/local/device/local_device_instrumentation_test_run_test.py
@@ -19,8 +19,10 @@ from pylib.base import mock_environment from pylib.base import mock_test_instance from pylib.local.device import local_device_instrumentation_test_run +from pylib.local.device import local_device_test_run import mock # pylint: disable=import-error +from unittest.mock import MagicMock class LocalDeviceInstrumentationTestRunTest(unittest.TestCase): @@ -195,6 +197,17 @@ self.test8 ] + # Mock these methods called in RunTests + self._env.ResetCurrentTry = MagicMock(side_effect = self.reset_try) + self._env.IncrementCurrentTry = MagicMock(side_effect = self.increment_try) + self._obj._GetTests = MagicMock(return_value=self.test_list) + + def reset_try(self): + self._env.current_try = 0 + + def increment_try(self): + self._env.current_try += 1 + def test_GroupTestsIntoBatchesAndOthers(self): expected_batched_tests = { 'batch1': [self.test1_batch1, self.test4_batch1, self.test5_batch1] @@ -213,8 +226,8 @@ def test_GroupTests(self): expected_tests = [ [self.test1_batch1, self.test4_batch1], - self.test3_multiprocess, self.test8, self.test2, self.test7, - self.test6, + self.test3_multiprocess, self.test8, self.test2, + self.test7, self.test6, [self.test5_batch1], self.test3 ] @@ -224,8 +237,8 @@ def test_GroupTestsAfterSharding(self): expected_tests = [ [self.test1_batch1, self.test4_batch1, self.test5_batch1], - self.test3_multiprocess, self.test8, self.test2, self.test7, - self.test6, self.test3 + self.test3_multiprocess, self.test8, self.test2, + self.test7, self.test6, self.test3 ] actual_tests = self._obj._GroupTestsAfterSharding(self.test_list) self.assertEqual(actual_tests, expected_tests) @@ -265,6 +278,54 @@ actual_tests = self._obj._CreateShardsForDevices(self.test_list) self.assertEqual(actual_tests, self.test_list) + def test_deterministic_sharding_grouped_tests(self): + self._env.devices = [1] + # 1 try and just the last try of mock_RunTestsOnDevice call is asserted + self._env.max_tries = 1 + + expected_shards = [ + [self.test1_batch1, self.test4_batch1, self.test5_batch1], + self.test3_multiprocess, self.test8, self.test2, + self.test7, self.test6, self.test3 + ] + + # Mock pMap to call the provided function + def mock_pMap(func, *args): + for _ in self._env.devices: + func(*args) + return MagicMock() + + # Store test collection arg as actual_shards + def get_actual_shards(): + actual_shards = [] + # mock_RunTestsOnDevice must be called for call_args to not be None + mock_RunTestsOnDevice.assert_called() + tc = mock_RunTestsOnDevice.call_args.args[0] + for group in tc: + actual_shards.append(group) + tc.test_completed() + return actual_shards + + mock_RunTestsOnDevice = MagicMock( + autospec='local_device_test_run.LocalDeviceTestRun._RunTestsOnDevice') + # Monkey patch needed to call mock. Decorator patch calls original method + # instead of mock possibly due to decorator or pMap on original method. + (local_device_test_run.LocalDeviceTestRun + ._RunTestsOnDevice) = mock_RunTestsOnDevice + + with mock.patch.object( + self._env.parallel_devices, "pMap", side_effect=mock_pMap + ): + self._obj.RunTests(results=[]) + actual_shards = get_actual_shards() + self.assertEqual(actual_shards, expected_shards) + + # Check "Retry shards with patch" has deterministic test ordering + self._obj.RunTests(results=[]) + actual_shards = get_actual_shards() + self.assertEqual(actual_shards, expected_shards) + + def create_test(annotation_dict, class_name, method_name): # Helper function to generate test dict test = {
diff --git a/build/android/pylib/local/device/local_device_test_run.py b/build/android/pylib/local/device/local_device_test_run.py index add1ea61..af14761 100644 --- a/build/android/pylib/local/device/local_device_test_run.py +++ b/build/android/pylib/local/device/local_device_test_run.py
@@ -46,102 +46,102 @@ self._installed_packages = [] env.SetPreferredAbis(test_instance.GetPreferredAbis()) + @local_device_environment.handle_shard_failures + def _RunTestsOnDevice(self, dev, tests, results, exit_now): + # This is performed here instead of during setup because restarting the + # device clears app compatibility flags, which will happen if a device + # needs to be recovered. + SetAppCompatibilityFlagsIfNecessary(self._installed_packages, dev) + consecutive_device_errors = 0 + for test in tests: + if not test: + logging.warning('No tests in shard. Continuing.') + tests.test_completed() + continue + if exit_now.isSet(): + thread.exit() + + result = None + rerun = None + try: + result, rerun = crash_handler.RetryOnSystemCrash( + lambda d, t=test: self._RunTest(d, t), + device=dev) + consecutive_device_errors = 0 + if isinstance(result, base_test_result.BaseTestResult): + results.AddResult(result) + elif isinstance(result, list): + results.AddResults(result) + else: + raise Exception( + 'Unexpected result type: %s' % type(result).__name__) + except device_errors.CommandTimeoutError as e: + exception_recorder.register(e) + # Test timeouts don't count as device errors for the purpose + # of bad device detection. + consecutive_device_errors = 0 + + if isinstance(test, list): + result_log = '' + if len(test) > 1: + result_log = ('The test command timed out when running multiple ' + 'tests including this test. It does not ' + 'necessarily mean this specific test timed out.') + # Ensure instrumentation tests not batched at env level retries. + for t in test: + # |dict| type infers it's an instrumentation test. + if isinstance(t, dict) and t['annotations']: + t['annotations'].pop('Batch', None) + + results.AddResults( + base_test_result.BaseTestResult( + self._GetUniqueTestName(t), + base_test_result.ResultType.TIMEOUT, + log=result_log) for t in test) + else: + results.AddResult( + base_test_result.BaseTestResult( + self._GetUniqueTestName(test), + base_test_result.ResultType.TIMEOUT)) + except device_errors.DeviceUnreachableError as e: + exception_recorder.register(e) + # If the device is no longer reachable then terminate this + # _RunTestsOnDevice call. + raise + except base_error.BaseError as e: + exception_recorder.register(e) + # If we get a device error but believe the device is still + # reachable, attempt to continue using it. + if isinstance(tests, test_collection.TestCollection): + rerun = test + + consecutive_device_errors += 1 + if consecutive_device_errors >= 3: + # We believe the device is still reachable and may still be usable, + # but if it fails repeatedly, we shouldn't attempt to keep using + # it. + logging.error('Repeated failures on device %s. Abandoning.', + str(dev)) + raise + + logging.exception( + 'Attempting to continue using device %s despite failure (%d/3).', + str(dev), consecutive_device_errors) + + finally: + if isinstance(tests, test_collection.TestCollection): + if rerun: + tests.add(rerun) + tests.test_completed() + + logging.info('Finished running tests on this device.') + #override def RunTests(self, results, raw_logs_fh=None): tests = self._GetTests() exit_now = threading.Event() - @local_device_environment.handle_shard_failures - def run_tests_on_device(dev, tests, results): - # This is performed here instead of during setup because restarting the - # device clears app compatibility flags, which will happen if a device - # needs to be recovered. - SetAppCompatibilityFlagsIfNecessary(self._installed_packages, dev) - consecutive_device_errors = 0 - for test in tests: - if not test: - logging.warning('No tests in shard. Continuing.') - tests.test_completed() - continue - if exit_now.isSet(): - thread.exit() - - result = None - rerun = None - try: - result, rerun = crash_handler.RetryOnSystemCrash( - lambda d, t=test: self._RunTest(d, t), - device=dev) - consecutive_device_errors = 0 - if isinstance(result, base_test_result.BaseTestResult): - results.AddResult(result) - elif isinstance(result, list): - results.AddResults(result) - else: - raise Exception( - 'Unexpected result type: %s' % type(result).__name__) - except device_errors.CommandTimeoutError as e: - exception_recorder.register(e) - # Test timeouts don't count as device errors for the purpose - # of bad device detection. - consecutive_device_errors = 0 - - if isinstance(test, list): - result_log = '' - if len(test) > 1: - result_log = ('The test command timed out when running multiple ' - 'tests including this test. It does not ' - 'necessarily mean this specific test timed out.') - # Ensure instrumentation tests not batched at env level retries. - for t in test: - # |dict| type infers it's an instrumentation test. - if isinstance(t, dict) and t['annotations']: - t['annotations'].pop('Batch', None) - - results.AddResults( - base_test_result.BaseTestResult( - self._GetUniqueTestName(t), - base_test_result.ResultType.TIMEOUT, - log=result_log) for t in test) - else: - results.AddResult( - base_test_result.BaseTestResult( - self._GetUniqueTestName(test), - base_test_result.ResultType.TIMEOUT)) - except device_errors.DeviceUnreachableError as e: - exception_recorder.register(e) - # If the device is no longer reachable then terminate this - # run_tests_on_device call. - raise - except base_error.BaseError as e: - exception_recorder.register(e) - # If we get a device error but believe the device is still - # reachable, attempt to continue using it. - if isinstance(tests, test_collection.TestCollection): - rerun = test - - consecutive_device_errors += 1 - if consecutive_device_errors >= 3: - # We believe the device is still reachable and may still be usable, - # but if it fails repeatedly, we shouldn't attempt to keep using - # it. - logging.error('Repeated failures on device %s. Abandoning.', - str(dev)) - raise - - logging.exception( - 'Attempting to continue using device %s despite failure (%d/3).', - str(dev), consecutive_device_errors) - - finally: - if isinstance(tests, test_collection.TestCollection): - if rerun: - tests.add(rerun) - tests.test_completed() - - logging.info('Finished running tests on this device.') - def stop_tests(_signum, _frame): logging.critical('Received SIGTERM. Stopping test execution.') exit_now.set() @@ -192,11 +192,13 @@ tc = test_collection.TestCollection( self._CreateShardsForDevices(grouped_tests)) self._env.parallel_devices.pMap( - run_tests_on_device, tc, try_results).pGet(None) + self._RunTestsOnDevice, + tc, try_results, exit_now).pGet(None) else: - self._env.parallel_devices.pMap(run_tests_on_device, + self._env.parallel_devices.pMap(self._RunTestsOnDevice, grouped_tests, - try_results).pGet(None) + try_results, + exit_now).pGet(None) except TestsTerminated: for unknown_result in try_results.GetUnknown(): try_results.AddResult(
diff --git a/cc/layers/layer.cc b/cc/layers/layer.cc index cd6c1bb..9dbe59a 100644 --- a/cc/layers/layer.cc +++ b/cc/layers/layer.cc
@@ -1472,7 +1472,7 @@ if (subtree_property_changed_.Read(*this)) { layer->NoteLayerPropertyChanged(); } - layer->set_may_contain_video(may_contain_video()); + layer->SetMayContainVideo(may_contain_video()); layer->SetTouchActionRegion(inputs.touch_action_region); layer->SetContentsOpaque(inputs.contents_opaque); layer->SetContentsOpaqueForText(inputs.contents_opaque_for_text); @@ -1515,8 +1515,6 @@ subtree_property_changed_.Write(*this) = false; update_rect_.Write(*this) = gfx::Rect(); } - - layer->SetNeedsPushProperties(); } void Layer::PushPropertiesTo(LayerImpl* layer_impl,
diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc index 2dac2c0..4021fcc 100644 --- a/cc/layers/layer_impl.cc +++ b/cc/layers/layer_impl.cc
@@ -111,7 +111,7 @@ DCHECK(layer_tree_impl_); layer_tree_impl_->RegisterLayer(this); - SetNeedsPushProperties(); + SetNeedsPushProperties(LayerImpl::kChangedAllProperties); } LayerImpl::~LayerImpl() { @@ -129,6 +129,8 @@ } void LayerImpl::UpdateDebugInfo(LayerDebugInfo* debug_info) { + SetNeedsPushProperties(); + // nullptr means we have stopped collecting debug info. if (!debug_info) { debug_info_.reset(); @@ -148,16 +150,49 @@ existing_invalidations.end()); } +void LayerImpl::SetMayContainVideo(bool may_contain_video) { + if (may_contain_video_ == may_contain_video) { + return; + } + + may_contain_video_ = may_contain_video; + SetNeedsPushProperties(); +} + +void LayerImpl::SetHasTransformNode(bool val) { + if (has_transform_node_ == val) { + return; + } + + has_transform_node_ = val; + SetNeedsPushProperties(LayerImpl::kChangedPropertyTreeIndex); +} + void LayerImpl::SetTransformTreeIndex(int index) { + if (transform_tree_index_ == index) { + return; + } + transform_tree_index_ = index; + SetNeedsPushProperties(LayerImpl::kChangedPropertyTreeIndex); } void LayerImpl::SetClipTreeIndex(int index) { + if (clip_tree_index_ == index) { + return; + } + clip_tree_index_ = index; + SetNeedsPushProperties(LayerImpl::kChangedPropertyTreeIndex); } void LayerImpl::SetEffectTreeIndex(int index) { + if (effect_tree_index_ == index) { + return; + } + effect_tree_index_ = index; + SetNeedsPushProperties(LayerImpl::kChangedPropertyTreeIndex); } int LayerImpl::render_target_effect_tree_index() const { @@ -169,7 +204,21 @@ } void LayerImpl::SetScrollTreeIndex(int index) { + if (scroll_tree_index_ == index) { + return; + } + scroll_tree_index_ = index; + SetNeedsPushProperties(LayerImpl::kChangedPropertyTreeIndex); +} + +void LayerImpl::SetOffsetToTransformParent(const gfx::Vector2dF& offset) { + if (offset_to_transform_parent_ == offset) { + return; + } + + offset_to_transform_parent_ = offset; + SetNeedsPushProperties(); } void LayerImpl::PopulateSharedQuadState(viz::SharedQuadState* state, @@ -342,6 +391,7 @@ return; touch_action_region_ = std::move(region); all_touch_action_regions_ = nullptr; + SetNeedsPushProperties(); } const Region& LayerImpl::GetAllTouchActionRegions() const { @@ -356,8 +406,10 @@ } void LayerImpl::SetCaptureBounds(viz::RegionCaptureBounds bounds) { - if (rare_properties_ || !bounds.IsEmpty()) + if (rare_properties_ || !bounds.IsEmpty()) { EnsureRareProperties().capture_bounds = std::move(bounds); + SetNeedsPushProperties(); + } } std::unique_ptr<LayerImpl> LayerImpl::CreateLayerImpl( @@ -372,56 +424,65 @@ void LayerImpl::PushPropertiesTo(LayerImpl* layer) { DCHECK(layer->IsActive()); - // The element id should be set first because other setters may - // depend on it. Referencing element id on a layer is - // deprecated. http://crbug.com/709137 - layer->SetElementId(element_id_); + if (GetChangeFlag(kChangedPropertyTreeIndex)) { + layer->transform_tree_index_ = transform_tree_index_; + layer->has_transform_node_ = has_transform_node_; + layer->effect_tree_index_ = effect_tree_index_; + layer->clip_tree_index_ = clip_tree_index_; + layer->scroll_tree_index_ = scroll_tree_index_; + } - layer->has_transform_node_ = has_transform_node_; - layer->offset_to_transform_parent_ = offset_to_transform_parent_; - layer->contents_opaque_ = contents_opaque_; - layer->contents_opaque_for_text_ = contents_opaque_for_text_; - layer->may_contain_video_ = may_contain_video_; - layer->should_check_backface_visibility_ = should_check_backface_visibility_; - layer->draws_content_ = draws_content_; - layer->hit_test_opaqueness_ = hit_test_opaqueness_; - layer->touch_action_region_ = touch_action_region_; - layer->all_touch_action_regions_ = ClonePtr(all_touch_action_regions_); - layer->background_color_ = background_color_; - layer->safe_opaque_background_color_ = safe_opaque_background_color_; - layer->transform_tree_index_ = transform_tree_index_; - layer->effect_tree_index_ = effect_tree_index_; - layer->clip_tree_index_ = clip_tree_index_; - layer->scroll_tree_index_ = scroll_tree_index_; + if (GetChangeFlag(kChangedGeneralProperty)) { + // The element id should be set first because other setters may + // depend on it. Referencing element id on a layer is + // deprecated. http://crbug.com/709137 + layer->SetElementId(element_id_); - if (layer_property_changed_not_from_property_trees_ || - layer_property_changed_from_property_trees_) - layer->layer_tree_impl()->set_needs_update_draw_properties(); - if (layer_property_changed_not_from_property_trees_) - layer->layer_property_changed_not_from_property_trees_ = true; - if (layer_property_changed_from_property_trees_) - layer->layer_property_changed_from_property_trees_ = true; + layer->offset_to_transform_parent_ = offset_to_transform_parent_; + layer->contents_opaque_ = contents_opaque_; + layer->contents_opaque_for_text_ = contents_opaque_for_text_; + layer->may_contain_video_ = may_contain_video_; + layer->should_check_backface_visibility_ = + should_check_backface_visibility_; + layer->draws_content_ = draws_content_; + layer->hit_test_opaqueness_ = hit_test_opaqueness_; + layer->touch_action_region_ = touch_action_region_; + layer->all_touch_action_regions_ = ClonePtr(all_touch_action_regions_); + layer->background_color_ = background_color_; + layer->safe_opaque_background_color_ = safe_opaque_background_color_; - layer->SetBounds(bounds_); + if (layer_property_changed_not_from_property_trees_ || + layer_property_changed_from_property_trees_) { + layer->layer_tree_impl()->set_needs_update_draw_properties(); + } + if (layer_property_changed_not_from_property_trees_) { + layer->layer_property_changed_not_from_property_trees_ = true; + } + if (layer_property_changed_from_property_trees_) { + layer->layer_property_changed_from_property_trees_ = true; + } - layer->UnionUpdateRect(update_rect_); + layer->SetBounds(bounds_); - layer->UpdateDebugInfo(debug_info_.get()); + layer->UnionUpdateRect(update_rect_); - if (rare_properties_) { - layer->rare_properties_ = - std::make_unique<RareProperties>(*rare_properties_); - } else { - layer->rare_properties_.reset(); + layer->UpdateDebugInfo(debug_info_.get()); + + if (rare_properties_) { + layer->rare_properties_ = + std::make_unique<RareProperties>(*rare_properties_); + } else { + layer->rare_properties_.reset(); + } + } + + if (layer_tree_impl()->settings().UseLayerContextForDisplay()) { + // Ensure updates also propagate to the display tree on its next update. + layer->SetNeedsPushProperties(changed_properties_); } // Reset any state that should be cleared for the next update. ResetChangeTracking(); - - if (layer_tree_impl()->settings().UseLayerContextForDisplay()) { - // Ensure updates also propagate to the display tree on its next update. - layer->SetNeedsPushProperties(); - } } bool LayerImpl::IsAffectedByPageScale() const { @@ -490,6 +551,7 @@ layer_property_changed_not_from_property_trees_ = false; layer_property_changed_from_property_trees_ = false; needs_push_properties_ = false; + changed_properties_ = 0; update_rect_.SetRect(0, 0, 0, 0); if (debug_info_) @@ -516,6 +578,7 @@ bounds_ = bounds; NoteLayerPropertyChanged(); + SetNeedsPushProperties(); } bool LayerImpl::IsScrollbarLayer() const { @@ -534,6 +597,7 @@ draws_content_ = draws_content; NoteLayerPropertyChanged(); + SetNeedsPushProperties(); } void LayerImpl::SetHitTestOpaqueness(HitTestOpaqueness opaqueness) { @@ -543,6 +607,7 @@ hit_test_opaqueness_ = opaqueness; NoteLayerPropertyChanged(); + SetNeedsPushProperties(); } bool LayerImpl::HitTestable() const { @@ -573,20 +638,37 @@ background_color_ = background_color; NoteLayerPropertyChanged(); + SetNeedsPushProperties(); } void LayerImpl::SetSafeOpaqueBackgroundColor(SkColor4f background_color) { + if (safe_opaque_background_color_ == background_color) { + return; + } + safe_opaque_background_color_ = background_color; + SetNeedsPushProperties(); } void LayerImpl::SetContentsOpaque(bool opaque) { + if (contents_opaque_ == opaque && contents_opaque_for_text_ == opaque) { + return; + } + contents_opaque_ = opaque; contents_opaque_for_text_ = opaque; + SetNeedsPushProperties(); } void LayerImpl::SetContentsOpaqueForText(bool opaque) { DCHECK(!contents_opaque_ || opaque); + + if (contents_opaque_for_text_ == opaque) { + return; + } + contents_opaque_for_text_ = opaque; + SetNeedsPushProperties(); } float LayerImpl::Opacity() const { @@ -603,10 +685,26 @@ TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), "LayerImpl::SetElementId", "element", element_id.ToString()); element_id_ = element_id; + SetNeedsPushProperties(); +} + +void LayerImpl::SetShouldCheckBackfaceVisibility( + bool should_check_backface_visibility) { + if (should_check_backface_visibility_ == should_check_backface_visibility) { + return; + } + + should_check_backface_visibility_ = should_check_backface_visibility; + SetNeedsPushProperties(); } void LayerImpl::UnionUpdateRect(const gfx::Rect& update_rect) { + if (update_rect_ == update_rect) { + return; + } + update_rect_.Union(update_rect); + SetNeedsPushProperties(); } gfx::Rect LayerImpl::GetDamageRect() const { @@ -648,7 +746,7 @@ void LayerImpl::RecreateTileResources() {} -void LayerImpl::SetNeedsPushProperties() { +void LayerImpl::SetNeedsPushProperties(uint8_t changed_props) { // For the pending tree, there's no need to mark this layer to push properties // when |will_always_push_properties_| is true. if (will_always_push_properties_ && layer_tree_impl()->IsPendingTree()) { @@ -661,6 +759,11 @@ return; } + if (::features::IsCCSlimmingEnabled()) { + changed_properties_ |= changed_props; + } else { + changed_properties_ = LayerImpl::kChangedAllProperties; + } if (!needs_push_properties_) { needs_push_properties_ = true; layer_tree_impl()->AddLayerShouldPushProperties(this); @@ -914,6 +1017,7 @@ return; } EnsureRareProperties().filter_quality = filter_quality; + SetNeedsPushProperties(); } void LayerImpl::SetDynamicRangeLimit( @@ -923,6 +1027,7 @@ } EnsureRareProperties().dynamic_range_limit = dynamic_range_limit; NoteLayerPropertyChanged(); + SetNeedsPushProperties(); } PropertyTrees* LayerImpl::GetPropertyTrees() const {
diff --git a/cc/layers/layer_impl.h b/cc/layers/layer_impl.h index e94f86f8..43580cd 100644 --- a/cc/layers/layer_impl.h +++ b/cc/layers/layer_impl.h
@@ -89,7 +89,7 @@ // pending tree. bool IsActive() const; - void SetHasTransformNode(bool val) { has_transform_node_ = val; } + void SetHasTransformNode(bool val); bool has_transform_node() const { return has_transform_node_; } void set_property_tree_sequence_number(int sequence_number) {} @@ -107,9 +107,7 @@ void SetScrollTreeIndex(int index); int scroll_tree_index() const { return scroll_tree_index_; } - void SetOffsetToTransformParent(const gfx::Vector2dF& offset) { - offset_to_transform_parent_ = offset; - } + void SetOffsetToTransformParent(const gfx::Vector2dF& offset); gfx::Vector2dF offset_to_transform_parent() const { return offset_to_transform_parent_; } @@ -195,9 +193,7 @@ bool Is3dSorted() const { return GetSortingContextId() != 0; } - void SetShouldCheckBackfaceVisibility(bool should_check_backface_visibility) { - should_check_backface_visibility_ = should_check_backface_visibility; - } + void SetShouldCheckBackfaceVisibility(bool should_check_backface_visibility); bool should_check_backface_visibility() const { return should_check_backface_visibility_; } @@ -279,11 +275,18 @@ return *rare_properties_; } - void ResetRareProperties() { rare_properties_.reset(); } + void ResetRareProperties() { + if (rare_properties_) { + rare_properties_.reset(); + SetNeedsPushProperties(); + } + } void SetMainThreadScrollHitTestRegion(const Region& region) { - if (rare_properties_ || !region.IsEmpty()) + if (rare_properties_ || !region.IsEmpty()) { EnsureRareProperties().main_thread_scroll_hit_test_region = region; + SetNeedsPushProperties(); + } } const Region& main_thread_scroll_hit_test_region() const { return rare_properties_ @@ -295,6 +298,7 @@ const std::vector<ScrollHitTestRect>& rects) { if (rare_properties_ || !rects.empty()) { EnsureRareProperties().non_composited_scroll_hit_test_rects = rects; + SetNeedsPushProperties(); } } const std::vector<ScrollHitTestRect>* non_composited_scroll_hit_test_rects() @@ -325,6 +329,7 @@ if (rare_properties_ || !wheel_event_handler_region.IsEmpty()) { EnsureRareProperties().wheel_event_handler_region = wheel_event_handler_region; + SetNeedsPushProperties(); } } const Region& wheel_event_handler_region() const { @@ -409,7 +414,7 @@ // properties that need to be pushed, when a new LayerImpl is created on the // pending tree while syncing layers from main thread, or when we recompute // visible layer properties on the pending tree. - void SetNeedsPushProperties(); + void SetNeedsPushProperties(uint8_t changed_props = kChangedGeneralProperty); virtual void RunMicroBenchmark(MicroBenchmarkImpl* benchmark); @@ -423,7 +428,7 @@ return contributes_to_drawn_render_surface_; } - void set_may_contain_video(bool yes) { may_contain_video_ = yes; } + void SetMayContainVideo(bool); bool may_contain_video() const { return may_contain_video_; } // Layers that share a sorting context id will be sorted together in 3d @@ -503,6 +508,14 @@ virtual void SetInInvisibleLayerTree() {} + enum : uint8_t { + kChangedPropertyTreeIndex = 1 << 0, + kChangedGeneralProperty = 1 << 1, + kChangedAllProperties = kChangedPropertyTreeIndex | kChangedGeneralProperty, + }; + + bool GetChangeFlag(uint8_t mask) const { return changed_properties_ & mask; } + protected: // When |will_always_push_properties| is true, the layer will not itself set // its SetNeedsPushProperties() state, as it expects to be always pushed to @@ -600,6 +613,8 @@ // |touch_action_region_|. mutable std::unique_ptr<Region> all_touch_action_regions_; + uint8_t changed_properties_ = 0u; + bool needs_push_properties_ : 1 = false; // This is set for layers that have a property because of which they are not
diff --git a/cc/layers/layer_unittest.cc b/cc/layers/layer_unittest.cc index c58e972..2184dd04 100644 --- a/cc/layers/layer_unittest.cc +++ b/cc/layers/layer_unittest.cc
@@ -92,12 +92,20 @@ ->layers_that_should_push_properties, \ grand_child.get())); -#define EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET(code_to_test) \ - code_to_test; \ - EXPECT_FALSE(root->subtree_property_changed()); \ - EXPECT_FALSE(top->subtree_property_changed()); \ - EXPECT_FALSE(child->subtree_property_changed()); \ - EXPECT_FALSE(grand_child->subtree_property_changed()); +#define EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET_IN_COMMIT(code_to_test) \ + do { \ + layer_tree_host_->WillCommit(/*completion=*/nullptr, \ + /*has_updates=*/true); \ + LayerTreeImpl::DiscardableImageMapUpdater updater(host_impl_.sync_tree()); \ + code_to_test; \ + EXPECT_FALSE(root->subtree_property_changed()); \ + EXPECT_FALSE(top->subtree_property_changed()); \ + EXPECT_FALSE(child->subtree_property_changed()); \ + EXPECT_FALSE(grand_child->subtree_property_changed()); \ + layer_tree_host_->CommitComplete( \ + commit_state->source_frame_number, \ + {base::TimeTicks(), base::TimeTicks::Now()}); \ + } while (false) #define EXPECT_SET_NEEDS_COMMIT_WAS_CALLED(code_to_test) \ do { \ @@ -397,9 +405,7 @@ host_impl_.active_tree()->source_frame_number() + 1); auto& unsafe_state = layer_tree_host_->GetThreadUnsafeCommitState(); - layer_tree_host_->WillCommit( - /*completion=*/nullptr, /*has_updates=*/true); - EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET( + EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET_IN_COMMIT( top->PushPropertiesTo(top_impl.get(), *commit_state, unsafe_state); child->PushPropertiesTo(child_impl.get(), *commit_state, unsafe_state); child2->PushPropertiesTo(child2_impl.get(), *commit_state, unsafe_state); @@ -407,8 +413,6 @@ unsafe_state); mask_layer1->PushPropertiesTo(mask_layer1_impl.get(), *commit_state, unsafe_state);); - layer_tree_host_->CommitComplete(commit_state->source_frame_number, - {base::TimeTicks(), base::TimeTicks::Now()}); // Once there is a mask layer, resizes require subtree properties to update. arbitrary_size = gfx::Size(11, 22); @@ -421,108 +425,79 @@ EXECUTE_AND_VERIFY_SUBTREE_CHANGED(top->SetMasksToBounds(true)); layer_tree_host_->VerifyAndClearExpectations(); - commit_state = layer_tree_host_->WillCommit(/*completion=*/nullptr, - /*has_updates=*/true); - - EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET( + EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET_IN_COMMIT( top->PushPropertiesTo(top_impl.get(), *commit_state, unsafe_state); child->PushPropertiesTo(child_impl.get(), *commit_state, unsafe_state); child2->PushPropertiesTo(child2_impl.get(), *commit_state, unsafe_state); grand_child->PushPropertiesTo(grand_child_impl.get(), *commit_state, unsafe_state)); - layer_tree_host_->CommitComplete(commit_state->source_frame_number, - {base::TimeTicks(), base::TimeTicks::Now()}); EXPECT_CALL_MOCK_DELEGATE(*layer_tree_host_, SetNeedsCommit()).Times(1); EXECUTE_AND_VERIFY_SUBTREE_CHANGED(top->SetContentsOpaque(true)); layer_tree_host_->VerifyAndClearExpectations(); - commit_state = layer_tree_host_->WillCommit(/*completion=*/nullptr, - /*has_updates=*/true); - EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET( + EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET_IN_COMMIT( top->PushPropertiesTo(top_impl.get(), *commit_state, unsafe_state); child->PushPropertiesTo(child_impl.get(), *commit_state, unsafe_state); child2->PushPropertiesTo(child2_impl.get(), *commit_state, unsafe_state); grand_child->PushPropertiesTo(grand_child_impl.get(), *commit_state, unsafe_state)); - layer_tree_host_->CommitComplete(commit_state->source_frame_number, - {base::TimeTicks(), base::TimeTicks::Now()}); EXPECT_CALL_MOCK_DELEGATE(*layer_tree_host_, SetNeedsCommit()).Times(1); EXECUTE_AND_VERIFY_SUBTREE_CHANGED(top->SetTrilinearFiltering(true)); layer_tree_host_->VerifyAndClearExpectations(); - commit_state = layer_tree_host_->WillCommit(/*completion=*/nullptr, - /*has_updates=*/true); - EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET( + EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET_IN_COMMIT( top->PushPropertiesTo(top_impl.get(), *commit_state, unsafe_state); child->PushPropertiesTo(child_impl.get(), *commit_state, unsafe_state); child2->PushPropertiesTo(child2_impl.get(), *commit_state, unsafe_state); grand_child->PushPropertiesTo(grand_child_impl.get(), *commit_state, unsafe_state)); - layer_tree_host_->CommitComplete(commit_state->source_frame_number, - {base::TimeTicks(), base::TimeTicks::Now()}); EXPECT_CALL_MOCK_DELEGATE(*layer_tree_host_, SetNeedsCommit()).Times(1); EXECUTE_AND_VERIFY_SUBTREE_CHANGED(top->SetTrilinearFiltering(false)); layer_tree_host_->VerifyAndClearExpectations(); - commit_state = layer_tree_host_->WillCommit(/*completion=*/nullptr, - /*has_updates=*/true); - EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET( + EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET_IN_COMMIT( top->PushPropertiesTo(top_impl.get(), *commit_state, unsafe_state); child->PushPropertiesTo(child_impl.get(), *commit_state, unsafe_state); child2->PushPropertiesTo(child2_impl.get(), *commit_state, unsafe_state); grand_child->PushPropertiesTo(grand_child_impl.get(), *commit_state, unsafe_state)); - layer_tree_host_->CommitComplete(commit_state->source_frame_number, - {base::TimeTicks(), base::TimeTicks::Now()}); EXPECT_CALL_MOCK_DELEGATE(*layer_tree_host_, SetNeedsCommit()).Times(2); top->SetRoundedCorner({1, 2, 3, 4}); EXECUTE_AND_VERIFY_SUBTREE_CHANGED(top->SetIsFastRoundedCorner(true)); layer_tree_host_->VerifyAndClearExpectations(); - commit_state = layer_tree_host_->WillCommit(/*completion=*/nullptr, - /*has_updates=*/true); - EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET( + EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET_IN_COMMIT( top->PushPropertiesTo(top_impl.get(), *commit_state, unsafe_state); child->PushPropertiesTo(child_impl.get(), *commit_state, unsafe_state); child2->PushPropertiesTo(child2_impl.get(), *commit_state, unsafe_state); grand_child->PushPropertiesTo(grand_child_impl.get(), *commit_state, unsafe_state)); - layer_tree_host_->CommitComplete(commit_state->source_frame_number, - {base::TimeTicks(), base::TimeTicks::Now()}); EXPECT_CALL_MOCK_DELEGATE(*layer_tree_host_, SetNeedsCommit()).Times(1); EXECUTE_AND_VERIFY_SUBTREE_CHANGED(top->SetHideLayerAndSubtree(true)); layer_tree_host_->VerifyAndClearExpectations(); - commit_state = layer_tree_host_->WillCommit(/*completion=*/nullptr, - /*has_updates=*/true); - EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET( + EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET_IN_COMMIT( top->PushPropertiesTo(top_impl.get(), *commit_state, unsafe_state); child->PushPropertiesTo(child_impl.get(), *commit_state, unsafe_state); child2->PushPropertiesTo(child2_impl.get(), *commit_state, unsafe_state); grand_child->PushPropertiesTo(grand_child_impl.get(), *commit_state, unsafe_state)); - layer_tree_host_->CommitComplete(commit_state->source_frame_number, - {base::TimeTicks(), base::TimeTicks::Now()}); EXPECT_CALL_MOCK_DELEGATE(*layer_tree_host_, SetNeedsCommit()).Times(1); EXECUTE_AND_VERIFY_SUBTREE_CHANGED(top->SetBlendMode(arbitrary_blend_mode)); layer_tree_host_->VerifyAndClearExpectations(); - commit_state = layer_tree_host_->WillCommit(/*completion=*/nullptr, - /*has_updates=*/true); - EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET( + EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET_IN_COMMIT( top->PushPropertiesTo(top_impl.get(), *commit_state, unsafe_state); child->PushPropertiesTo(child_impl.get(), *commit_state, unsafe_state); child2->PushPropertiesTo(child2_impl.get(), *commit_state, unsafe_state); grand_child->PushPropertiesTo(grand_child_impl.get(), *commit_state, unsafe_state)); - layer_tree_host_->CommitComplete(commit_state->source_frame_number, - {base::TimeTicks(), base::TimeTicks::Now()}); // Should be a different size than previous call, to ensure it marks tree // changed. @@ -532,16 +507,12 @@ EXECUTE_AND_VERIFY_SUBTREE_CHANGED(mask_layer1->SetBounds(arbitrary_size)); layer_tree_host_->VerifyAndClearExpectations(); - commit_state = layer_tree_host_->WillCommit(/*completion=*/nullptr, - /*has_updates=*/true); - EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET( + EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET_IN_COMMIT( top->PushPropertiesTo(top_impl.get(), *commit_state, unsafe_state); child->PushPropertiesTo(child_impl.get(), *commit_state, unsafe_state); child2->PushPropertiesTo(child2_impl.get(), *commit_state, unsafe_state); grand_child->PushPropertiesTo(grand_child_impl.get(), *commit_state, unsafe_state)); - layer_tree_host_->CommitComplete(commit_state->source_frame_number, - {base::TimeTicks(), base::TimeTicks::Now()}); FilterOperations arbitrary_filters; arbitrary_filters.Append(FilterOperation::CreateOpacityFilter(0.5f)); @@ -549,31 +520,23 @@ EXECUTE_AND_VERIFY_SUBTREE_CHANGED(top->SetFilters(arbitrary_filters)); layer_tree_host_->VerifyAndClearExpectations(); - commit_state = layer_tree_host_->WillCommit(/*completion=*/nullptr, - /*has_updates=*/true); - EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET( + EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET_IN_COMMIT( top->PushPropertiesTo(top_impl.get(), *commit_state, unsafe_state); child->PushPropertiesTo(child_impl.get(), *commit_state, unsafe_state); child2->PushPropertiesTo(child2_impl.get(), *commit_state, unsafe_state); grand_child->PushPropertiesTo(grand_child_impl.get(), *commit_state, unsafe_state)); - layer_tree_host_->CommitComplete(commit_state->source_frame_number, - {base::TimeTicks(), base::TimeTicks::Now()}); EXPECT_CALL_MOCK_DELEGATE(*layer_tree_host_, SetNeedsCommit()).Times(2); EXECUTE_AND_VERIFY_SUBTREE_CHANGED( top->SetBackdropFilters(arbitrary_filters)); - commit_state = layer_tree_host_->WillCommit(/*completion=*/nullptr, - /*has_updates=*/true); - EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET( + EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET_IN_COMMIT( top->PushPropertiesTo(top_impl.get(), *commit_state, unsafe_state); child->PushPropertiesTo(child_impl.get(), *commit_state, unsafe_state); child2->PushPropertiesTo(child2_impl.get(), *commit_state, unsafe_state); grand_child->PushPropertiesTo(grand_child_impl.get(), *commit_state, unsafe_state)); - layer_tree_host_->CommitComplete(commit_state->source_frame_number, - {base::TimeTicks(), base::TimeTicks::Now()}); layer_tree_host_->VerifyAndClearExpectations(); gfx::PointF arbitrary_point_f = gfx::PointF(0.125f, 0.25f); @@ -584,17 +547,13 @@ top->transform_tree_index()); EXPECT_TRUE(node->transform_changed); - commit_state = layer_tree_host_->WillCommit(/*completion=*/nullptr, - /*has_updates=*/true); - EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET( + EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET_IN_COMMIT( top->PushPropertiesTo(top_impl.get(), *commit_state, unsafe_state); child->PushPropertiesTo(child_impl.get(), *commit_state, unsafe_state); child2->PushPropertiesTo(child2_impl.get(), *commit_state, unsafe_state); grand_child->PushPropertiesTo(grand_child_impl.get(), *commit_state, unsafe_state); layer_tree_host_->property_trees()->ResetAllChangeTracking()); - layer_tree_host_->CommitComplete(commit_state->source_frame_number, - {base::TimeTicks(), base::TimeTicks::Now()}); EXPECT_FALSE(node->transform_changed); layer_tree_host_->VerifyAndClearExpectations(); @@ -605,15 +564,11 @@ EXPECT_TRUE(node->transform_changed); layer_tree_host_->VerifyAndClearExpectations(); - commit_state = layer_tree_host_->WillCommit(/*completion=*/nullptr, - /*has_updates=*/true); - EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET( + EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET_IN_COMMIT( child->PushPropertiesTo(child_impl.get(), *commit_state, unsafe_state); grand_child->PushPropertiesTo(grand_child_impl.get(), *commit_state, unsafe_state); layer_tree_host_->property_trees()->ResetAllChangeTracking()); - layer_tree_host_->CommitComplete(commit_state->source_frame_number, - {base::TimeTicks(), base::TimeTicks::Now()}); node = layer_tree_host_->property_trees()->transform_tree_mutable().Node( child->transform_tree_index()); EXPECT_FALSE(node->transform_changed); @@ -626,17 +581,13 @@ EXPECT_TRUE(node->transform_changed); layer_tree_host_->VerifyAndClearExpectations(); - commit_state = layer_tree_host_->WillCommit(/*completion=*/nullptr, - /*has_updates=*/true); - EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET( + EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET_IN_COMMIT( top->PushPropertiesTo(top_impl.get(), *commit_state, unsafe_state); child->PushPropertiesTo(child_impl.get(), *commit_state, unsafe_state); child2->PushPropertiesTo(child2_impl.get(), *commit_state, unsafe_state); grand_child->PushPropertiesTo(grand_child_impl.get(), *commit_state, unsafe_state); layer_tree_host_->property_trees()->ResetAllChangeTracking()); - layer_tree_host_->CommitComplete(commit_state->source_frame_number, - {base::TimeTicks(), base::TimeTicks::Now()}); gfx::Transform arbitrary_transform; arbitrary_transform.Scale3d(0.1f, 0.2f, 0.3f);
diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc index cc386cd..e7638a2 100644 --- a/cc/layers/picture_layer_impl.cc +++ b/cc/layers/picture_layer_impl.cc
@@ -145,6 +145,10 @@ layer_impl->has_non_animated_image_update_rect_ = has_non_animated_image_update_rect_; + // This hs to be cached before calling LayerImpl::PushPropertiesTo because it + // reset the flag. + bool changed_other_props = GetChangeFlag(kChangedGeneralProperty); + LayerImpl::PushPropertiesTo(base_layer); // Twin relationships should never change once established. @@ -157,33 +161,36 @@ twin_layer_ = layer_impl; layer_impl->twin_layer_ = this; - layer_impl->SetIsBackdropFilterMask(is_backdrop_filter_mask_); + if (changed_other_props) { + layer_impl->SetIsBackdropFilterMask(is_backdrop_filter_mask_); - // Solid color layers have no tilings. - DCHECK(!raster_source_->IsSolidColor() || tilings_->num_tilings() == 0); - // The pending tree should only have a high res (and possibly low res) tiling. - DCHECK_LE(tilings_->num_tilings(), - layer_tree_impl()->create_low_res_tiling() ? 2u : 1u); + // Solid color layers have no tilings. + DCHECK(!raster_source_->IsSolidColor() || tilings_->num_tilings() == 0); + // The pending tree should only have a high res (and possibly low res) + // tiling. + DCHECK_LE(tilings_->num_tilings(), + layer_tree_impl()->create_low_res_tiling() ? 2u : 1u); - layer_impl->set_gpu_raster_max_texture_size(gpu_raster_max_texture_size_); - layer_impl->UpdateRasterSourceInternal( - raster_source_, &invalidation_, tilings_.get(), &paint_worklet_records_, - discardable_image_map_.get()); - DCHECK(invalidation_.IsEmpty()); + layer_impl->set_gpu_raster_max_texture_size(gpu_raster_max_texture_size_); + layer_impl->UpdateRasterSourceInternal( + raster_source_, &invalidation_, tilings_.get(), &paint_worklet_records_, + discardable_image_map_.get()); + DCHECK(invalidation_.IsEmpty()); - // After syncing a solid color layer, the active layer has no tilings. - DCHECK(!raster_source_->IsSolidColor() || - layer_impl->tilings_->num_tilings() == 0); + // After syncing a solid color layer, the active layer has no tilings. + DCHECK(!raster_source_->IsSolidColor() || + layer_impl->tilings_->num_tilings() == 0); - layer_impl->raster_page_scale_ = raster_page_scale_; - layer_impl->raster_device_scale_ = raster_device_scale_; - layer_impl->raster_source_scale_ = raster_source_scale_; - layer_impl->raster_contents_scale_ = raster_contents_scale_; - layer_impl->low_res_raster_contents_scale_ = low_res_raster_contents_scale_; - // Simply push the value to the active tree without any extra invalidations, - // since the pending tree tiles would have this handled. This is here to - // ensure the state is consistent for future raster. - layer_impl->lcd_text_disallowed_reason_ = lcd_text_disallowed_reason_; + layer_impl->raster_page_scale_ = raster_page_scale_; + layer_impl->raster_device_scale_ = raster_device_scale_; + layer_impl->raster_source_scale_ = raster_source_scale_; + layer_impl->raster_contents_scale_ = raster_contents_scale_; + layer_impl->low_res_raster_contents_scale_ = low_res_raster_contents_scale_; + // Simply push the value to the active tree without any extra invalidations, + // since the pending tree tiles would have this handled. This is here to + // ensure the state is consistent for future raster. + layer_impl->lcd_text_disallowed_reason_ = lcd_text_disallowed_reason_; + } if (layer_tree_impl()->settings().UseLayerContextForDisplay()) { // Move tile updates over to the active layer so they get pushed to the @@ -191,7 +198,6 @@ // updates, so replacement is safe. layer_impl->updated_tiles_ = std::move(updated_tiles_); updated_tiles_.clear(); - layer_impl->SetNeedsPushProperties(); } layer_impl->SanityCheckTilingState(); @@ -758,6 +764,9 @@ << " layer bounds " << bounds().ToString() << " raster_source size " << raster_source->size().ToString(); + // TODO(vmiura): Only call SetNeedsPushProperties there is an actual change. + SetNeedsPushProperties(); + if (!raster_source_ || raster_source_->size() != raster_source->size()) { raster_source_size_changed_ = true; } @@ -794,7 +803,7 @@ // The |raster_source_| is initially null, so have to check for that for the // first frame. bool could_have_tilings = CanHaveTilings(); - raster_source_.swap(raster_source); + raster_source_ = std::move(raster_source); raster_source_->set_debug_name(DebugName()); @@ -811,7 +820,7 @@ RegisterAnimatedImages(); } } else if (recording_updated) { - RegenerateDiscardableImageMap(); + layer_tree_impl()->AddLayerNeedingUpdateDiscardableImageMap(this); } // The |new_invalidation| must be cleared before updating tilings since they @@ -851,17 +860,25 @@ } } +void PictureLayerImpl::SetRasterSourceForTesting( + scoped_refptr<RasterSource> raster_source, + const Region& invalidation) { + LayerTreeImpl::DiscardableImageMapUpdater updater(layer_tree_impl()); + Region invalidation_temp = invalidation; + UpdateRasterSource(std::move(raster_source), &invalidation_temp); +} + void PictureLayerImpl::RegenerateDiscardableImageMap() { CHECK(layer_tree_impl()->IsSyncTree()); - UnregisterAnimatedImages(); if (const auto* display_list = raster_source_->GetDisplayItemList().get()) { - scoped_refptr<DiscardableImageMap> image_map = - display_list->GenerateDiscardableImageMap(); - SetPaintWorkletInputs(image_map->paint_worklet_inputs()); - layer_tree_impl()->UpdateImageDecodingHints( - image_map->TakeDecodingModeMap()); - discardable_image_map_ = std::move(image_map); + DiscardableImageMap::DecodingModeMap decoding_mode_map; + DiscardableImageMap::PaintWorkletInputs paint_worklet_inputs; + discardable_image_map_ = display_list->GenerateDiscardableImageMap( + GetRasterInducingScrollOffsets(), &decoding_mode_map, + &paint_worklet_inputs); + SetPaintWorkletInputs(paint_worklet_inputs); + layer_tree_impl()->UpdateImageDecodingHints(decoding_mode_map); } else { SetPaintWorkletInputs({}); discardable_image_map_ = nullptr; @@ -2140,16 +2157,25 @@ const DisplayItemList::RasterInducingScrollMap& raster_inducing_scrolls = raster_source_->GetDisplayItemList()->raster_inducing_scrolls(); Region invalidation; + bool needs_update_discardable_image_map = false; for (ElementId element_id : scrolls_to_invalidate) { auto it = raster_inducing_scrolls.find(element_id); if (it != raster_inducing_scrolls.end()) { UnionUpdateRect(it->second.visual_rect); has_non_animated_image_update_rect_ = true; invalidation.Union(it->second.visual_rect); + needs_update_discardable_image_map |= it->second.has_discardable_images; } } if (!invalidation.IsEmpty()) { + if (needs_update_discardable_image_map) { + // The new map should only have changed image rects, so we don't need to + // re-register animated images and update paint worklets. + discardable_image_map_ = + raster_source_->GetDisplayItemList()->GenerateDiscardableImageMap( + GetRasterInducingScrollOffsets()); + } invalidation_.Union(invalidation); tilings_->Invalidate(invalidation); } @@ -2188,8 +2214,7 @@ } void PictureLayerImpl::SetPaintWorkletInputs( - const std::vector<DiscardableImageMap::PaintWorkletInputWithImageId>& - inputs) { + const DiscardableImageMap::PaintWorkletInputs& inputs) { // PaintWorklets are not supported when committing directly to the active // tree, so in that case the |inputs| should always be empty. DCHECK(layer_tree_impl()->IsPendingTree() || inputs.empty());
diff --git a/cc/layers/picture_layer_impl.h b/cc/layers/picture_layer_impl.h index 650bf56..a92379ce 100644 --- a/cc/layers/picture_layer_impl.h +++ b/cc/layers/picture_layer_impl.h
@@ -52,7 +52,11 @@ PictureLayerImpl& operator=(const PictureLayerImpl&) = delete; void SetIsBackdropFilterMask(bool is_backdrop_filter_mask) { + if (is_backdrop_filter_mask_ == is_backdrop_filter_mask) { + return; + } is_backdrop_filter_mask_ = is_backdrop_filter_mask; + SetNeedsPushProperties(); } bool is_backdrop_filter_mask() const { return is_backdrop_filter_mask_; } @@ -94,7 +98,11 @@ bool ShouldAnimate(PaintImage::Id paint_image_id) const override; void set_gpu_raster_max_texture_size(gfx::Size gpu_raster_max_texture_size) { + if (gpu_raster_max_texture_size_ == gpu_raster_max_texture_size) { + return; + } gpu_raster_max_texture_size_ = gpu_raster_max_texture_size; + SetNeedsPushProperties(); } gfx::Size gpu_raster_max_texture_size() { @@ -103,6 +111,9 @@ void UpdateRasterSource(scoped_refptr<RasterSource> raster_source, Region* new_invalidation); + void SetRasterSourceForTesting(scoped_refptr<RasterSource> raster_source, + const Region& invalidation = Region()); + void RegenerateDiscardableImageMap(); bool UpdateTiles(); // Mask-related functions. @@ -229,7 +240,6 @@ const PictureLayerTilingSet* pending_set, const PaintWorkletRecordMap* pending_paint_worklet_records, const DiscardableImageMap* pending_discardable_image_map); - void RegenerateDiscardableImageMap(); bool IsDirectlyCompositedImage() const; void UpdateDirectlyCompositedImageFromRasterSource(); @@ -251,8 +261,7 @@ // Set the collection of PaintWorkletInput as well as their PaintImageId that // are part of this layer. void SetPaintWorkletInputs( - const std::vector<DiscardableImageMap::PaintWorkletInputWithImageId>& - inputs); + const DiscardableImageMap::PaintWorkletInputs& inputs); LCDTextDisallowedReason ComputeLCDTextDisallowedReason( bool raster_translation_aligns_pixels) const;
diff --git a/cc/layers/picture_layer_impl_unittest.cc b/cc/layers/picture_layer_impl_unittest.cc index cd865de..714468c 100644 --- a/cc/layers/picture_layer_impl_unittest.cc +++ b/cc/layers/picture_layer_impl_unittest.cc
@@ -50,6 +50,8 @@ namespace cc { namespace { +using ::testing::ElementsAre; + #define EXPECT_BOTH_EQ(expression, x) \ do { \ EXPECT_EQ(x, pending_layer()->expression); \ @@ -3404,12 +3406,11 @@ SetWillChangeTransform(active_layer(), true); SetWillChangeTransform(pending_layer(), true); layer_bounds = gfx::Size(200, 200); - Region invalidation; // UpdateRasterSource() requires that the pending tree doesn't have tiles. pending_layer()->picture_layer_tiling_set()->RemoveAllTiles(); pending_layer()->SetBounds(layer_bounds); - pending_layer()->UpdateRasterSource( - FakeRasterSource::CreateFilled(layer_bounds), &invalidation); + pending_layer()->SetRasterSourceForTesting( + FakeRasterSource::CreateFilled(layer_bounds)); pending_layer()->PushPropertiesTo(active_layer()); SetContentsAndAnimationScalesOnBothLayers(contents_scale, device_scale, page_scale, maximum_animation_scale, @@ -3996,12 +3997,11 @@ // Raster source size change forces adjustment of raster scale. layer_bounds = gfx::Size(200, 200); - Region invalidation; // UpdateRasterSource() requires that the pending tree doesn't have tiles. pending_layer()->picture_layer_tiling_set()->RemoveAllTiles(); pending_layer()->SetBounds(layer_bounds); - pending_layer()->UpdateRasterSource( - FakeRasterSource::CreateFilled(layer_bounds), &invalidation); + pending_layer()->SetRasterSourceForTesting( + FakeRasterSource::CreateFilled(layer_bounds)); pending_layer()->PushPropertiesTo(active_layer()); SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale); EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 2.f); @@ -6689,15 +6689,26 @@ auto active_image_map = active_layer()->discardable_image_map(); EXPECT_TRUE(pending_image_map); EXPECT_EQ(pending_image_map, active_image_map); + EXPECT_THAT(pending_image_map->GetRectsForImage(image.stable_id()), + ElementsAre(gfx::Rect(-1, -1, 202, 202))); + // Simulate a raster-inducing scroll. + host_impl() + ->pending_tree() + ->property_trees() + ->scroll_tree_mutable() + .GetOrCreateSyncedScrollOffsetForTesting(scroll_element_id1) + ->SetCurrent(gfx::PointF(0, 100)); // Invalidating scroll_element_id1 will invalidate scroll visual rect. pending_layer()->InvalidateRasterInducingScrolls({scroll_element_id1}); EXPECT_EQ(info1.visual_rect, pending_layer()->invalidation().bounds()); EXPECT_TRUE(active_layer()->invalidation().IsEmpty()); - // The discardable image map should not be affected. + // And regenerate discardable image map with updated image rects. pending_image_map = pending_layer()->discardable_image_map(); EXPECT_EQ(active_image_map, active_layer()->discardable_image_map()); - EXPECT_EQ(pending_image_map, active_image_map); + EXPECT_NE(pending_image_map, active_image_map); + EXPECT_THAT(pending_image_map->GetRectsForImage(image.stable_id()), + ElementsAre(gfx::Rect(-1, -1, 202, 102))); ActivateTree(); SetupPendingTreeWithInvalidation(raster, Region()); @@ -6707,7 +6718,8 @@ active_image_map = active_layer()->discardable_image_map(); EXPECT_EQ(pending_image_map, active_image_map); - // Same for scroll_list2. + // scroll_list2 doesn't contain discardable images. Invalidating + // scroll_element_id2 will invalidate scroll visual rect only. pending_layer()->InvalidateRasterInducingScrolls({scroll_element_id2}); EXPECT_EQ(info2.visual_rect, pending_layer()->invalidation().bounds()); EXPECT_EQ(pending_image_map, pending_layer()->discardable_image_map()); @@ -6718,7 +6730,7 @@ EXPECT_TRUE(pending_layer()->invalidation().IsEmpty()); EXPECT_EQ(info2.visual_rect, active_layer()->invalidation().bounds()); EXPECT_EQ(pending_image_map, pending_layer()->discardable_image_map()); - EXPECT_EQ(pending_image_map, pending_layer()->discardable_image_map()); + EXPECT_EQ(pending_image_map, active_layer()->discardable_image_map()); } enum { @@ -6756,8 +6768,7 @@ descendant_->SetContentsOpaque(true); descendant_->SetDrawsContent(true); descendant_->SetBounds(gfx::Size(200, 200)); - Region invalidation; - descendant_->UpdateRasterSource(raster_source, &invalidation); + descendant_->SetRasterSourceForTesting(raster_source); ASSERT_TRUE(layer_->CanHaveTilings()); CreateTransformNode(layer_);
diff --git a/cc/layers/picture_layer_unittest.cc b/cc/layers/picture_layer_unittest.cc index 7e4daa1..d1c06ad1 100644 --- a/cc/layers/picture_layer_unittest.cc +++ b/cc/layers/picture_layer_unittest.cc
@@ -119,8 +119,11 @@ FakePictureLayerImpl::Create(host_impl.pending_tree(), 1)); FakePictureLayerImpl* layer_impl = static_cast<FakePictureLayerImpl*>( host_impl.pending_tree()->root_layer()); - layer->PushPropertiesTo(layer_impl, *host->GetPendingCommitState(), - host->GetThreadUnsafeCommitState()); + { + LayerTreeImpl::DiscardableImageMapUpdater updater(host_impl.pending_tree()); + layer->PushPropertiesTo(layer_impl, *host->GetPendingCommitState(), + host->GetThreadUnsafeCommitState()); + } EXPECT_EQ(invalidation_bounds, layer_impl->GetPendingInvalidation()->bounds()); @@ -213,7 +216,10 @@ const auto& unsafe_state = host->GetThreadUnsafeCommitState(); std::unique_ptr<CommitState> commit_state = host->WillCommit(/*completion=*/nullptr, /*has_updates=*/true); - layer->PushPropertiesTo(layer_impl, *commit_state, unsafe_state); + { + LayerTreeImpl::DiscardableImageMapUpdater updater(host_impl.pending_tree()); + layer->PushPropertiesTo(layer_impl, *commit_state, unsafe_state); + } host->CommitComplete(commit_state->source_frame_number, {base::TimeTicks(), base::TimeTicks::Now()}); @@ -233,8 +239,11 @@ // We should now have invalid contents and should therefore clear the // recording source. - layer->PushPropertiesTo(layer_impl, *host->GetPendingCommitState(), - host->GetThreadUnsafeCommitState()); + { + LayerTreeImpl::DiscardableImageMapUpdater updater(host_impl.pending_tree()); + layer->PushPropertiesTo(layer_impl, *host->GetPendingCommitState(), + host->GetThreadUnsafeCommitState()); + } UpdateDrawProperties(host_impl.pending_tree()); host_impl.ActivateSyncTree();
diff --git a/cc/layers/recording_source_unittest.cc b/cc/layers/recording_source_unittest.cc index 96ed392..8f16654 100644 --- a/cc/layers/recording_source_unittest.cc +++ b/cc/layers/recording_source_unittest.cc
@@ -44,7 +44,8 @@ scoped_refptr<RasterSource> raster_source = recording_source.CreateRasterSource(); scoped_refptr<DiscardableImageMap> image_map = - raster_source->GetDisplayItemList()->GenerateDiscardableImageMap(); + raster_source->GetDisplayItemList()->GenerateDiscardableImageMap( + ScrollOffsetMap()); // Tile sized iterators. These should find only one pixel ref. { @@ -108,7 +109,8 @@ scoped_refptr<RasterSource> raster_source = recording_source.CreateRasterSource(); scoped_refptr<DiscardableImageMap> image_map = - raster_source->GetDisplayItemList()->GenerateDiscardableImageMap(); + raster_source->GetDisplayItemList()->GenerateDiscardableImageMap( + ScrollOffsetMap()); // Tile sized iterators. { @@ -154,7 +156,8 @@ scoped_refptr<RasterSource> raster_source = recording_source.CreateRasterSource(); scoped_refptr<DiscardableImageMap> image_map = - raster_source->GetDisplayItemList()->GenerateDiscardableImageMap(); + raster_source->GetDisplayItemList()->GenerateDiscardableImageMap( + ScrollOffsetMap()); // Tile sized iterators. { @@ -199,7 +202,8 @@ scoped_refptr<RasterSource> raster_source = recording_source.CreateRasterSource(); scoped_refptr<DiscardableImageMap> image_map = - raster_source->GetDisplayItemList()->GenerateDiscardableImageMap(); + raster_source->GetDisplayItemList()->GenerateDiscardableImageMap( + ScrollOffsetMap()); // Tile sized iterators. These should find only one image. { @@ -267,7 +271,8 @@ scoped_refptr<RasterSource> raster_source = recording_source.CreateRasterSource(); scoped_refptr<DiscardableImageMap> image_map = - raster_source->GetDisplayItemList()->GenerateDiscardableImageMap(); + raster_source->GetDisplayItemList()->GenerateDiscardableImageMap( + ScrollOffsetMap()); // Tile sized iterators. These should find only one image. {
diff --git a/cc/layers/surface_layer.cc b/cc/layers/surface_layer.cc index effd0fff..cd2b306 100644 --- a/cc/layers/surface_layer.cc +++ b/cc/layers/surface_layer.cc
@@ -209,7 +209,6 @@ stretch_content_to_fill_bounds_.Read(*this)); layer_impl->SetSurfaceHitTestable(surface_hit_testable_.Read(*this)); layer_impl->SetHasPointerEventsNone(has_pointer_events_none_.Read(*this)); - layer_impl->set_may_contain_video(may_contain_video_.Read(*this)); if (callback_layer_tree_host_changed_.Read(*this)) { // Anytime SetLayerTreeHost is called and
diff --git a/cc/layers/video_layer_impl.cc b/cc/layers/video_layer_impl.cc index 8dc8d4e..f198a1b4 100644 --- a/cc/layers/video_layer_impl.cc +++ b/cc/layers/video_layer_impl.cc
@@ -50,7 +50,7 @@ : LayerImpl(tree_impl, id), provider_client_impl_(std::move(provider_client_impl)), video_transform_(video_transform) { - set_may_contain_video(true); + SetMayContainVideo(true); } VideoLayerImpl::~VideoLayerImpl() {
diff --git a/cc/paint/discardable_image_map.cc b/cc/paint/discardable_image_map.cc index 27f9258..e3ddc9a9 100644 --- a/cc/paint/discardable_image_map.cc +++ b/cc/paint/discardable_image_map.cc
@@ -37,9 +37,16 @@ public: Generator(DiscardableImageMap& map, - SkNoDrawCanvas& canvas, - const PaintOpBuffer& buffer) - : map_(map), canvas_(canvas) { + const PaintOpBuffer& buffer, + const gfx::Rect& bounds, + const ScrollOffsetMap& raster_inducing_scroll_offsets, + DecodingModeMap* decoding_mode_map, + PaintWorkletInputs* paint_worklet_inputs) + : map_(map), + canvas_(gfx::RectToSkIRect(bounds)), + raster_inducing_scroll_offsets_(raster_inducing_scroll_offsets), + decoding_mode_map_(decoding_mode_map), + paint_worklet_inputs_(paint_worklet_inputs) { GatherDiscardableImages(buffer, nullptr); } @@ -103,7 +110,7 @@ op_rect = PaintOp::ComputePaintRect(op, clip_rect, ctm); } - if (op_rect.IsEmpty()) { + if (!collect_invisible_images_ && op_rect.IsEmpty()) { continue; } @@ -181,12 +188,20 @@ } else if (op_type == PaintOpType::kDrawScrollingContents) { const auto& draw_scrolling_contents_op = static_cast<const DrawScrollingContentsOp&>(op); - // Collect all images under a DrawScrollingContentsOp (like what we do - // for a composited scroller), and use op_rect as the image rects to - // avoid the dependency to the scroll offset. - GatherDiscardableImages( - draw_scrolling_contents_op.display_item_list->paint_op_buffer(), - &op_rect); + if (draw_scrolling_contents_op.display_item_list + ->has_discardable_images()) { + canvas_.save(); + // Collect all images under a DrawScrollingContentsOp, to make the set + // of images not depend on the scroll offset. + base::AutoReset<bool> reset(&collect_invisible_images_, true); + gfx::PointF scroll_offset = raster_inducing_scroll_offsets_.at( + draw_scrolling_contents_op.scroll_element_id); + canvas_.translate(-scroll_offset.x(), -scroll_offset.y()); + GatherDiscardableImages( + draw_scrolling_contents_op.display_item_list->paint_op_buffer(), + top_level_op_rect); + canvas_.restore(); + } } } } @@ -278,11 +293,6 @@ SkIRect src_irect; src_rect.roundOut(&src_irect); - if (paint_image.IsPaintWorklet()) { - map_.paint_worklet_inputs_.emplace_back( - paint_image.GetPaintWorkletInput(), paint_image.stable_id()); - } - auto& rects = map_.image_id_to_rects_[paint_image.stable_id()]; if (rects.size() >= kMaxRectsSize) { rects.back().Union(image_rect); @@ -290,13 +300,17 @@ rects.push_back(image_rect); } - if (paint_image.IsLazyGenerated()) { - auto decoding_mode_it = - map_.decoding_mode_map_.find(paint_image.stable_id()); + if (paint_worklet_inputs_ && paint_image.IsPaintWorklet()) { + paint_worklet_inputs_->emplace_back(paint_image.GetPaintWorkletInput(), + paint_image.stable_id()); + } + + if (decoding_mode_map_ && paint_image.IsLazyGenerated()) { + auto decoding_mode_it = decoding_mode_map_->find(paint_image.stable_id()); // Use the decoding mode if we don't have one yet, otherwise use the more // conservative one of the two existing ones. - if (decoding_mode_it == map_.decoding_mode_map_.end()) { - map_.decoding_mode_map_[paint_image.stable_id()] = + if (decoding_mode_it == decoding_mode_map_->end()) { + (*decoding_mode_map_)[paint_image.stable_id()] = paint_image.decoding_mode(); } else { decoding_mode_it->second = PaintImage::GetConservative( @@ -333,8 +347,12 @@ } DiscardableImageMap& map_; - SkNoDrawCanvas& canvas_; + SkNoDrawCanvas canvas_; + const ScrollOffsetMap& raster_inducing_scroll_offsets_; + DecodingModeMap* const decoding_mode_map_; + PaintWorkletInputs* const paint_worklet_inputs_; bool only_gather_animated_images_ = false; + bool collect_invisible_images_ = false; }; // DiscardableImageMap::Generator DiscardableImageMap::DiscardableImageMap() = default; @@ -345,25 +363,19 @@ scoped_refptr<DiscardableImageMap> DiscardableImageMap::Generate( const PaintOpBuffer& paint_op_buffer, - const gfx::Rect& bounds) { + const gfx::Rect& bounds, + const ScrollOffsetMap& raster_inducing_scroll_offsets, + DecodingModeMap* decoding_mode_map, + PaintWorkletInputs* paint_worklet_inputs) { TRACE_EVENT0("cc", "DiscardableImageMap::Generate"); scoped_refptr<DiscardableImageMap> image_map(new DiscardableImageMap()); - if (!paint_op_buffer.has_discardable_images()) { - return image_map; - } - - SkNoDrawCanvas canvas(bounds.right(), bounds.bottom()); - Generator generator(*image_map, canvas, paint_op_buffer); + Generator generator(*image_map, paint_op_buffer, bounds, + raster_inducing_scroll_offsets, decoding_mode_map, + paint_worklet_inputs); CHECK(!image_map->images_rtree_); return image_map; } -base::flat_map<PaintImage::Id, PaintImage::DecodingMode> -DiscardableImageMap::TakeDecodingModeMap() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - return std::move(decoding_mode_map_); -} - std::vector<const DrawImage*> DiscardableImageMap::GetDiscardableImagesInRect( const gfx::Rect& rect) const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/cc/paint/discardable_image_map.h b/cc/paint/discardable_image_map.h index d9ed9593..afe4711 100644 --- a/cc/paint/discardable_image_map.h +++ b/cc/paint/discardable_image_map.h
@@ -19,6 +19,7 @@ #include "cc/paint/paint_flags.h" #include "cc/paint/paint_image.h" #include "cc/paint/paint_worklet_input.h" +#include "cc/paint/scroll_offset_map.h" #include "third_party/abseil-cpp/absl/container/inlined_vector.h" #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkRefCnt.h" @@ -54,9 +55,21 @@ PaintImage::AnimationSequenceId reset_animation_sequence_id; }; + using DecodingModeMap = + base::flat_map<PaintImage::Id, PaintImage::DecodingMode>; + using PaintWorkletInputWithImageId = + std::pair<scoped_refptr<PaintWorkletInput>, PaintImage::Id>; + using PaintWorkletInputs = std::vector<PaintWorkletInputWithImageId>; + static scoped_refptr<DiscardableImageMap> Generate( const PaintOpBuffer& paint_op_buffer, - const gfx::Rect& bounds); + const gfx::Rect& bounds, + const ScrollOffsetMap& raster_inducing_scroll_offsets, + // These data are not stored in DiscardableImageMap because they should + // be consumed immediately. The caller can omit these parameters if they + // won't be used. + DecodingModeMap* decoding_mode_map = nullptr, + PaintWorkletInputs* paint_worklet_inputs = nullptr); bool empty() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -70,17 +83,6 @@ return animated_images_metadata_; } - // This should only be called once from the compositor thread at commit time. - base::flat_map<PaintImage::Id, PaintImage::DecodingMode> - TakeDecodingModeMap(); - - using PaintWorkletInputWithImageId = - std::pair<scoped_refptr<PaintWorkletInput>, PaintImage::Id>; - const std::vector<PaintWorkletInputWithImageId>& paint_worklet_inputs() - const { - return paint_worklet_inputs_; - } - private: friend class DiscardableImageMapTest; friend class base::RefCounted<DiscardableImageMap>; @@ -94,8 +96,6 @@ std::vector<std::pair<DrawImage, gfx::Rect>> images_; // This r-tree is built lazily. The entries are DrawImage pointers in images_. mutable std::unique_ptr<RTree<const DrawImage*>> images_rtree_; - base::flat_map<PaintImage::Id, PaintImage::DecodingMode> decoding_mode_map_; - std::vector<PaintWorkletInputWithImageId> paint_worklet_inputs_; // The class should be used from single thread only. SEQUENCE_CHECKER(sequence_checker_);
diff --git a/cc/paint/discardable_image_map_unittest.cc b/cc/paint/discardable_image_map_unittest.cc index 231bacd..7386eeb 100644 --- a/cc/paint/discardable_image_map_unittest.cc +++ b/cc/paint/discardable_image_map_unittest.cc
@@ -56,6 +56,7 @@ namespace { using ::testing::_; using ::testing::Contains; +using ::testing::ElementsAre; using ::testing::Eq; using ::testing::Field; using ::testing::FieldsAre; @@ -67,12 +68,15 @@ struct PositionScaleDrawImage { PaintImage image; - gfx::Rect image_rect; + DiscardableImageMap::Rects image_rects; SkSize scale; friend void PrintTo(const PositionScaleDrawImage& img, std::ostream* os) { - *os << "image: <paint image> image_rect: " << img.image_rect.ToString() - << " scale: " << gfx::SkSizeToSizeF(img.scale).ToString(); + *os << "image: " << img.image.ToString() << " rects: "; + for (const gfx::Rect& rect : img.image_rects) { + *os << rect.ToString() << " "; + } + *os << "scale: " << gfx::SkSizeToSizeF(img.scale).ToString(); } }; @@ -105,10 +109,9 @@ image_map.images_rtree_->Search(rect, &results); for (const DrawImage* image : results) { auto image_id = image->paint_image().stable_id(); - position_draw_images.push_back(PositionScaleDrawImage{ - image->paint_image(), - ImageRectsToRegion(image_map.GetRectsForImage(image_id)).bounds(), - image->scale()}); + position_draw_images.emplace_back(image->paint_image(), + image_map.GetRectsForImage(image_id), + image->scale()); } EXPECT_EQ(draw_images.size(), position_draw_images.size()); @@ -127,8 +130,10 @@ const std::vector<PositionScaleDrawImage>& images) { std::vector<gfx::Rect> result; for (auto& image : images) { - result.push_back(image.image_rect); - result.back().Inset(1); + for (gfx::Rect rect : image.image_rects) { + rect.Inset(1); + result.push_back(rect); + } } return result; } @@ -164,7 +169,7 @@ scoped_refptr<DisplayItemList> display_list = content_layer_client.PaintContentsToDisplayList(); scoped_refptr<DiscardableImageMap> image_map = - display_list->GenerateDiscardableImageMap(); + display_list->GenerateDiscardableImageMap(ScrollOffsetMap()); for (int y = 0; y < 4; ++y) { for (int x = 0; x < 4; ++x) { @@ -235,7 +240,7 @@ scoped_refptr<DisplayItemList> display_list = content_layer_client.PaintContentsToDisplayList(); scoped_refptr<DiscardableImageMap> image_map = - display_list->GenerateDiscardableImageMap(); + display_list->GenerateDiscardableImageMap(ScrollOffsetMap()); for (int y = 0; y < 4; ++y) { for (int x = 0; x < 4; ++x) { @@ -334,7 +339,7 @@ scoped_refptr<DisplayItemList> display_list = content_layer_client.PaintContentsToDisplayList(); scoped_refptr<DiscardableImageMap> image_map = - display_list->GenerateDiscardableImageMap(); + display_list->GenerateDiscardableImageMap(ScrollOffsetMap()); for (int y = 0; y < 4; ++y) { for (int x = 0; x < 4; ++x) { @@ -367,7 +372,7 @@ scoped_refptr<DisplayItemList> display_list = content_layer_client.PaintContentsToDisplayList(); scoped_refptr<DiscardableImageMap> image_map = - display_list->GenerateDiscardableImageMap(); + display_list->GenerateDiscardableImageMap(ScrollOffsetMap()); std::vector<PositionScaleDrawImage> images = GetDiscardableImagesInRect(*image_map, gfx::Rect(0, 0, 1, 1)); @@ -395,7 +400,7 @@ display_list->Finalize(); scoped_refptr<DiscardableImageMap> image_map = - display_list->GenerateDiscardableImageMap(); + display_list->GenerateDiscardableImageMap(ScrollOffsetMap()); std::vector<PositionScaleDrawImage> images = GetDiscardableImagesInRect(*image_map, gfx::Rect(0, 0, 1, 1)); EXPECT_EQ(1u, images.size()); @@ -412,7 +417,7 @@ display_list->push<DrawRectOp>(rect, flags); display_list->EndPaintOfUnpaired(gfx::Rect(INT_MAX, INT_MAX)); display_list->Finalize(); - display_list->GenerateDiscardableImageMap(); + display_list->GenerateDiscardableImageMap(ScrollOffsetMap()); } // Test if SaveLayer and Restore work together. @@ -453,7 +458,7 @@ display_list->Finalize(); scoped_refptr<DiscardableImageMap> image_map = - display_list->GenerateDiscardableImageMap(); + display_list->GenerateDiscardableImageMap(ScrollOffsetMap()); std::vector<PositionScaleDrawImage> images = GetDiscardableImagesInRect(*image_map, gfx::Rect(0, 0, 200, 200)); EXPECT_EQ(3u, images.size()); @@ -480,7 +485,7 @@ display_list->Finalize(); scoped_refptr<DiscardableImageMap> image_map = - display_list->GenerateDiscardableImageMap(); + display_list->GenerateDiscardableImageMap(ScrollOffsetMap()); std::vector<PositionScaleDrawImage> images = GetDiscardableImagesInRect(*image_map, gfx::Rect(0, 0, 1, 1)); EXPECT_EQ(1u, images.size()); @@ -502,7 +507,7 @@ scoped_refptr<DisplayItemList> display_list = content_layer_client.PaintContentsToDisplayList(); scoped_refptr<DiscardableImageMap> image_map = - display_list->GenerateDiscardableImageMap(); + display_list->GenerateDiscardableImageMap(ScrollOffsetMap()); std::vector<PositionScaleDrawImage> images = GetDiscardableImagesInRect(*image_map, gfx::Rect(42, 42, 1, 1)); @@ -543,7 +548,7 @@ scoped_refptr<DisplayItemList> display_list = content_layer_client.PaintContentsToDisplayList(); scoped_refptr<DiscardableImageMap> image_map = - display_list->GenerateDiscardableImageMap(); + display_list->GenerateDiscardableImageMap(ScrollOffsetMap()); std::vector<PositionScaleDrawImage> images = GetDiscardableImagesInRect(*image_map, gfx::Rect(0, 0, 1, 1)); @@ -589,7 +594,7 @@ scoped_refptr<DisplayItemList> display_list = content_layer_client.PaintContentsToDisplayList(); scoped_refptr<DiscardableImageMap> image_map = - display_list->GenerateDiscardableImageMap(); + display_list->GenerateDiscardableImageMap(ScrollOffsetMap()); std::vector<PositionScaleDrawImage> images = GetDiscardableImagesInRect(*image_map, gfx::Rect(0, 0, 1, 1)); @@ -654,7 +659,7 @@ scoped_refptr<DisplayItemList> display_list = content_layer_client.PaintContentsToDisplayList(); scoped_refptr<DiscardableImageMap> image_map = - display_list->GenerateDiscardableImageMap(); + display_list->GenerateDiscardableImageMap(ScrollOffsetMap()); for (int y = 0; y < 4; ++y) { for (int x = 0; x < 4; ++x) { @@ -708,7 +713,7 @@ display_list->Finalize(); scoped_refptr<DiscardableImageMap> image_map = - display_list->GenerateDiscardableImageMap(); + display_list->GenerateDiscardableImageMap(ScrollOffsetMap()); std::vector<PositionScaleDrawImage> images = GetDiscardableImagesInRect(*image_map, visible_rect); std::vector<gfx::Rect> inset_rects = InsetImageRects(images); @@ -736,8 +741,8 @@ PaintOpBuffer root_buffer; root_buffer.push<DrawRecordOp>(internal_buffer.ReleaseAsRecord()); root_buffer.push<DrawRecordOp>(buffer2.ReleaseAsRecord()); - scoped_refptr<DiscardableImageMap> image_map = - DiscardableImageMap::Generate(root_buffer, gfx::Rect(200, 200)); + scoped_refptr<DiscardableImageMap> image_map = DiscardableImageMap::Generate( + root_buffer, gfx::Rect(200, 200), ScrollOffsetMap()); std::vector<const DrawImage*> images = image_map->GetDiscardableImagesInRect(gfx::Rect(0, 0, 5, 95)); @@ -773,7 +778,7 @@ scoped_refptr<DisplayItemList> display_list = content_layer_client.PaintContentsToDisplayList(); scoped_refptr<DiscardableImageMap> image_map = - display_list->GenerateDiscardableImageMap(); + display_list->GenerateDiscardableImageMap(ScrollOffsetMap()); const auto& animated_images_metadata = image_map->animated_images_metadata(); ASSERT_EQ(animated_images_metadata.size(), 1u); @@ -815,10 +820,11 @@ scoped_refptr<DisplayItemList> display_list = content_layer_client.PaintContentsToDisplayList(); + DiscardableImageMap::PaintWorkletInputs paint_worklet_inputs; scoped_refptr<DiscardableImageMap> image_map = - display_list->GenerateDiscardableImageMap(); + display_list->GenerateDiscardableImageMap(ScrollOffsetMap(), nullptr, + &paint_worklet_inputs); - const auto& paint_worklet_inputs = image_map->paint_worklet_inputs(); ASSERT_EQ(paint_worklet_inputs.size(), 1u); EXPECT_EQ(paint_worklet_inputs[0].first, input); @@ -859,7 +865,7 @@ EXPECT_EQ(flags.getShader()->image_analysis_state(), ImageAnalysisState::kNoAnalysis); scoped_refptr<DiscardableImageMap> image_map = - display_list->GenerateDiscardableImageMap(); + display_list->GenerateDiscardableImageMap(ScrollOffsetMap()); EXPECT_EQ(flags.getShader()->image_analysis_state(), ImageAnalysisState::kAnimatedImages); @@ -904,7 +910,7 @@ EXPECT_EQ(flags.getImageFilter()->image_analysis_state(), ImageAnalysisState::kNoAnalysis); scoped_refptr<DiscardableImageMap> image_map = - display_list->GenerateDiscardableImageMap(); + display_list->GenerateDiscardableImageMap(ScrollOffsetMap()); EXPECT_EQ(flags.getImageFilter()->image_analysis_state(), ImageAnalysisState::kAnimatedImages); @@ -938,7 +944,7 @@ display_list->Finalize(); scoped_refptr<DiscardableImageMap> image_map = - display_list->GenerateDiscardableImageMap(); + display_list->GenerateDiscardableImageMap(ScrollOffsetMap()); std::vector<PositionScaleDrawImage> draw_images = GetDiscardableImagesInRect(*image_map, visible_rect); std::vector<gfx::Rect> inset_rects = InsetImageRects(draw_images); @@ -977,7 +983,7 @@ display_list->push<DrawRectOp>(SkRect::MakeWH(200, 200), flags); display_list->EndPaintOfUnpaired(visible_rect); display_list->Finalize(); - display_list->GenerateDiscardableImageMap(); + display_list->GenerateDiscardableImageMap(ScrollOffsetMap()); EXPECT_EQ(shader_with_image->image_analysis_state(), ImageAnalysisState::kAnimatedImages); EXPECT_EQ(shader_with_shader_with_image->image_analysis_state(), @@ -1012,9 +1018,10 @@ content_layer_client.add_draw_image(sync_image, gfx::Point(20, 20)); scoped_refptr<DisplayItemList> display_list = content_layer_client.PaintContentsToDisplayList(); + DiscardableImageMap::DecodingModeMap decode_hints; scoped_refptr<DiscardableImageMap> image_map = - display_list->GenerateDiscardableImageMap(); - auto decode_hints = image_map->TakeDecodingModeMap(); + display_list->GenerateDiscardableImageMap(ScrollOffsetMap(), + &decode_hints); EXPECT_EQ(decode_hints.size(), 3u); EXPECT_TRUE(base::Contains(decode_hints, 1)); EXPECT_TRUE(base::Contains(decode_hints, 2)); @@ -1022,9 +1029,6 @@ EXPECT_EQ(decode_hints[1], PaintImage::DecodingMode::kUnspecified); EXPECT_EQ(decode_hints[2], PaintImage::DecodingMode::kAsync); EXPECT_EQ(decode_hints[3], PaintImage::DecodingMode::kSync); - - decode_hints = image_map->TakeDecodingModeMap(); - EXPECT_EQ(decode_hints.size(), 0u); } TEST_F(DiscardableImageMapTest, DecodingModeHintsDuplicates) { @@ -1078,10 +1082,11 @@ content_layer_client.add_draw_image(sync_image3, gfx::Point(50, 50)); scoped_refptr<DisplayItemList> display_list = content_layer_client.PaintContentsToDisplayList(); + DiscardableImageMap::DecodingModeMap decode_hints; scoped_refptr<DiscardableImageMap> image_map = - display_list->GenerateDiscardableImageMap(); + display_list->GenerateDiscardableImageMap(ScrollOffsetMap(), + &decode_hints); - auto decode_hints = image_map->TakeDecodingModeMap(); EXPECT_EQ(decode_hints.size(), 3u); EXPECT_TRUE(base::Contains(decode_hints, 1)); EXPECT_TRUE(base::Contains(decode_hints, 2)); @@ -1092,9 +1097,6 @@ EXPECT_EQ(decode_hints[2], PaintImage::DecodingMode::kSync); // 3 was async and sync, so the result should be sync EXPECT_EQ(decode_hints[3], PaintImage::DecodingMode::kSync); - - decode_hints = image_map->TakeDecodingModeMap(); - EXPECT_EQ(decode_hints.size(), 0u); } TEST_F(DiscardableImageMapTest, TracksImageRegions) { @@ -1113,7 +1115,7 @@ scoped_refptr<DisplayItemList> display_list = content_layer_client.PaintContentsToDisplayList(); scoped_refptr<DiscardableImageMap> image_map = - display_list->GenerateDiscardableImageMap(); + display_list->GenerateDiscardableImageMap(ScrollOffsetMap()); std::vector<gfx::Rect> rects = {gfx::Rect(100, 100), gfx::Rect(400, 400, 100, 100)}; @@ -1167,20 +1169,37 @@ display_list->EndPaintOfPairedEnd(); display_list->Finalize(); + ScrollOffsetMap scroll_offsets; + scroll_offsets[scroll_element_id1] = gfx::PointF(); + scroll_offsets[scroll_element_id2] = gfx::PointF(); + scoped_refptr<DiscardableImageMap> image_map = - display_list->GenerateDiscardableImageMap(); - // All images appearances should be collected, including those currently out - // of view. The image rect is the union of the appearances of each image, - // using the bounding box of the containing DrawScrollingContentsOps. - gfx::Rect expected_rect(-1, -1, 302, 502); + display_list->GenerateDiscardableImageMap(scroll_offsets); SkSize expected_scale = SkSize::Make(1, 1); + EXPECT_THAT(GetDiscardableImagesInRect(*image_map, gfx::Rect(1000, 1000)), + ElementsAre(FieldsAre(ImageIsSame(image1), + ElementsAre(gfx::Rect(-1, -1, 102, 202), + gfx::Rect(99, 299, 102, 202)), + expected_scale), + FieldsAre(ImageIsSame(image1), + ElementsAre(gfx::Rect(-1, -1, 102, 202), + gfx::Rect(99, 299, 102, 202)), + expected_scale))); + + // The first scroller scrolls to make both images invisible. + scroll_offsets[scroll_element_id1] = gfx::PointF(200, 100); + // The second scroller scrolls to make both images visible. + scroll_offsets[scroll_element_id2] = gfx::PointF(0, 250); + image_map = display_list->GenerateDiscardableImageMap(scroll_offsets); EXPECT_THAT( GetDiscardableImagesInRect(*image_map, gfx::Rect(1000, 1000)), - UnorderedElementsAre( - FieldsAre(ImageIsSame(image1), expected_rect, expected_scale), - FieldsAre(ImageIsSame(image1), expected_rect, expected_scale), - FieldsAre(ImageIsSame(image2), expected_rect, expected_scale), - FieldsAre(ImageIsSame(image2), expected_rect, expected_scale))); + ElementsAre( + FieldsAre(ImageIsSame(image1), + ElementsAre(gfx::Rect(), gfx::Rect(99, 299, 102, 52)), + expected_scale), + FieldsAre(ImageIsSame(image2), + ElementsAre(gfx::Rect(), gfx::Rect(199, 399, 102, 102)), + expected_scale))); } #if BUILDFLAG(SKIA_SUPPORT_SKOTTIE) @@ -1197,7 +1216,7 @@ scoped_refptr<DisplayItemList> display_list = content_layer_client.PaintContentsToDisplayList(); scoped_refptr<DiscardableImageMap> image_map = - display_list->GenerateDiscardableImageMap(); + display_list->GenerateDiscardableImageMap(ScrollOffsetMap()); EXPECT_THAT(GetDiscardableImagesInRect(*image_map, gfx::Rect(2048, 2048)), IsEmpty()); } @@ -1227,7 +1246,7 @@ scoped_refptr<DisplayItemList> display_list = content_layer_client.PaintContentsToDisplayList(); scoped_refptr<DiscardableImageMap> image_map = - display_list->GenerateDiscardableImageMap(); + display_list->GenerateDiscardableImageMap(ScrollOffsetMap()); // Left Half of screen should return no images. EXPECT_THAT(GetDiscardableImagesInRect(*image_map, gfx::Rect(1023, 2048)), IsEmpty()); @@ -1267,7 +1286,7 @@ scoped_refptr<DisplayItemList> display_list = content_layer_client.PaintContentsToDisplayList(); scoped_refptr<DiscardableImageMap> image_map = - display_list->GenerateDiscardableImageMap(); + display_list->GenerateDiscardableImageMap(ScrollOffsetMap()); std::vector<PositionScaleDrawImage> images_out = GetDiscardableImagesInRect(*image_map, visible_rect); ASSERT_THAT(images_out, SizeIs(2)); @@ -1316,7 +1335,7 @@ display_list->Finalize(); scoped_refptr<DiscardableImageMap> image_map = - display_list->GenerateDiscardableImageMap(); + display_list->GenerateDiscardableImageMap(ScrollOffsetMap()); std::vector<const DrawImage*> images = image_map->GetDiscardableImagesInRect(gfx::Rect(0, 0, 200, 200)); EXPECT_EQ(3u, images.size());
diff --git a/cc/paint/display_item_list.cc b/cc/paint/display_item_list.cc index 51d84e6e..3794e0d 100644 --- a/cc/paint/display_item_list.cc +++ b/cc/paint/display_item_list.cc
@@ -313,15 +313,18 @@ } } -scoped_refptr<DiscardableImageMap> -DisplayItemList::GenerateDiscardableImageMap() const { +scoped_refptr<DiscardableImageMap> DisplayItemList::GenerateDiscardableImageMap( + const ScrollOffsetMap& raster_inducing_scroll_offsets, + DiscardableImageMap::DecodingModeMap* decoding_mode_map, + DiscardableImageMap::PaintWorkletInputs* paint_worklet_inputs) const { #if DCHECK_IS_ON() DCHECK(IsFinalized()); #endif // Bounds are only used to size an SkNoDrawCanvas. - return DiscardableImageMap::Generate(paint_op_buffer_, - bounds().value_or(kMaxBounds)); + return DiscardableImageMap::Generate( + paint_op_buffer_, bounds().value_or(kMaxBounds), + raster_inducing_scroll_offsets, decoding_mode_map, paint_worklet_inputs); } bool DisplayItemList::GetColorIfSolidInRect(const gfx::Rect& rect,
diff --git a/cc/paint/display_item_list.h b/cc/paint/display_item_list.h index 9df8eb6..260d5a7c 100644 --- a/cc/paint/display_item_list.h +++ b/cc/paint/display_item_list.h
@@ -160,7 +160,10 @@ } size_t OpBytesUsed() const { return paint_op_buffer_.paint_ops_size(); } - scoped_refptr<DiscardableImageMap> GenerateDiscardableImageMap() const; + scoped_refptr<DiscardableImageMap> GenerateDiscardableImageMap( + const ScrollOffsetMap& raster_inducing_scroll_offsets, + DiscardableImageMap::DecodingModeMap* = nullptr, + DiscardableImageMap::PaintWorkletInputs* = nullptr) const; void EmitTraceSnapshot() const;
diff --git a/cc/raster/raster_source_unittest.cc b/cc/raster/raster_source_unittest.cc index 9512538..47552b4 100644 --- a/cc/raster/raster_source_unittest.cc +++ b/cc/raster/raster_source_unittest.cc
@@ -224,7 +224,8 @@ scoped_refptr<RasterSource> raster = recording_source.CreateRasterSource(); scoped_refptr<DiscardableImageMap> image_map = - raster->GetDisplayItemList()->GenerateDiscardableImageMap(); + raster->GetDisplayItemList()->GenerateDiscardableImageMap( + ScrollOffsetMap()); // Tile sized iterators. These should find only one pixel ref. {
diff --git a/cc/test/fake_mask_layer_impl.cc b/cc/test/fake_mask_layer_impl.cc index 0de3f4e..7cdd412 100644 --- a/cc/test/fake_mask_layer_impl.cc +++ b/cc/test/fake_mask_layer_impl.cc
@@ -15,8 +15,7 @@ scoped_refptr<RasterSource> raster_source) : PictureLayerImpl(tree_impl, id) { SetBounds(raster_source->size()); - Region region; - UpdateRasterSource(raster_source, ®ion); + SetRasterSourceForTesting(raster_source); } std::unique_ptr<FakeMaskLayerImpl> FakeMaskLayerImpl::Create(
diff --git a/cc/test/fake_picture_layer_impl.cc b/cc/test/fake_picture_layer_impl.cc index a60eec0..6d05107b 100644 --- a/cc/test/fake_picture_layer_impl.cc +++ b/cc/test/fake_picture_layer_impl.cc
@@ -86,10 +86,9 @@ void FakePictureLayerImpl::SetRasterSource( scoped_refptr<RasterSource> raster_source, const Region& invalidation) { - Region invalidation_temp = invalidation; set_gpu_raster_max_texture_size( layer_tree_impl()->GetDeviceViewport().size()); - UpdateRasterSource(raster_source, &invalidation_temp); + SetRasterSourceForTesting(raster_source, invalidation); } size_t FakePictureLayerImpl::GetNumberOfTilesWithResources() const {
diff --git a/cc/test/fake_picture_layer_impl.h b/cc/test/fake_picture_layer_impl.h index 43d8294..96dd59c 100644 --- a/cc/test/fake_picture_layer_impl.h +++ b/cc/test/fake_picture_layer_impl.h
@@ -87,13 +87,25 @@ size_t append_quads_count() { return append_quads_count_; } const Region& invalidation() const { return invalidation_; } - void set_invalidation(const Region& region) { invalidation_ = region; } + void set_invalidation(const Region& region) { + if (invalidation_ == region) { + return; + } + invalidation_ = region; + SetNeedsPushProperties(); + } gfx::Rect viewport_rect_for_tile_priority_in_content_space() { return viewport_rect_for_tile_priority_in_content_space_; } - void set_fixed_tile_size(const gfx::Size& size) { fixed_tile_size_ = size; } + void set_fixed_tile_size(const gfx::Size& size) { + if (fixed_tile_size_ == size) { + return; + } + fixed_tile_size_ = size; + SetNeedsPushProperties(); + } void CreateAllTiles(); void SetAllTilesReady();
diff --git a/cc/test/paint_image_matchers.h b/cc/test/paint_image_matchers.h index cd2ebfd2..1bba1f2 100644 --- a/cc/test/paint_image_matchers.h +++ b/cc/test/paint_image_matchers.h
@@ -12,6 +12,10 @@ namespace cc { +inline void PrintTo(const PaintImage& image, std::ostream* os) { + *os << image.ToString(); +} + // Checks `arg.IsSameForTesting(image)`. // Mainly used in container matchers: // std::vector<PaintImage> images;
diff --git a/cc/tiles/tile_manager_unittest.cc b/cc/tiles/tile_manager_unittest.cc index 0d3a553..194a68b 100644 --- a/cc/tiles/tile_manager_unittest.cc +++ b/cc/tiles/tile_manager_unittest.cc
@@ -2131,8 +2131,7 @@ std::unique_ptr<PictureLayerImpl> layer = PictureLayerImpl::Create(host_impl()->pending_tree(), 1); layer->SetBounds(size); - Region invalidation; - layer->UpdateRasterSource(raster, &invalidation); + layer->SetRasterSourceForTesting(raster); PictureLayerTilingSet* tiling_set = layer->picture_layer_tiling_set(); layer->set_contributes_to_drawn_render_surface(true);
diff --git a/cc/trees/damage_tracker_unittest.cc b/cc/trees/damage_tracker_unittest.cc index 7e6a713..0b4a55c5 100644 --- a/cc/trees/damage_tracker_unittest.cc +++ b/cc/trees/damage_tracker_unittest.cc
@@ -1753,9 +1753,8 @@ CreateEffectNode(child); auto* mask_layer = AddLayerInActiveTree<FakePictureLayerImpl>(); SetupMaskProperties(child, mask_layer); - Region empty_invalidation; - mask_layer->UpdateRasterSource( - FakeRasterSource::CreateFilled(child->bounds()), &empty_invalidation); + mask_layer->SetRasterSourceForTesting( + FakeRasterSource::CreateFilled(child->bounds())); // Add opacity and a grand_child so that the render surface persists even // after we remove the mask.
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index 2f44dff..ee95dc4d 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc
@@ -838,9 +838,14 @@ sync_tree()->UpdateDrawProperties(update_tiles, update_image_animation_controller); - // Defer invalidating images until UpdateDrawProperties is performed since - // that updates whether an image should be animated based on its visibility - // and the updated data for the image from the main frame. + sync_tree()->InvalidateRasterInducingScrolls( + pending_invalidation_raster_inducing_scrolls_); + pending_invalidation_raster_inducing_scrolls_.clear(); + + // Defer invalidating images until UpdateDrawProperties and + // InvalidateRasterInducingScroll is performed since those update whether an + // image should be animated based on its visibility and the updated data for + // the image from the main frame. PaintImageIdFlatSet images_to_invalidate = tile_manager_.TakeImagesToInvalidateOnSyncTree(); @@ -870,14 +875,6 @@ sync_tree()->InvalidateRegionForImages(images_to_invalidate); - sync_tree()->set_did_raster_inducing_scroll(false); - if (!pending_invalidation_raster_inducing_scrolls_.empty()) { - base::flat_set<ElementId> scrolls_to_invalidate; - std::swap(scrolls_to_invalidate, - pending_invalidation_raster_inducing_scrolls_); - sync_tree()->InvalidateRasterInducingScrolls(scrolls_to_invalidate); - } - // Note that it is important to push the state for checkerboarded and animated // images prior to PrepareTiles here when committing to the active tree. This // is because new tiles on the active tree depend on tree specific state
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc index b6e9ee4..053a109c 100644 --- a/cc/trees/layer_tree_host_impl_unittest.cc +++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -10960,7 +10960,7 @@ auto* root = SetupRootLayer<DidDrawCheckLayer>(host_impl_->active_tree(), big_size); auto* video_layer = AddLayer<DidDrawCheckLayer>(host_impl_->active_tree()); - video_layer->set_may_contain_video(true); + video_layer->SetMayContainVideo(true); CopyProperties(root, video_layer); UpdateDrawProperties(host_impl_->active_tree()); EXPECT_TRUE(MayContainVideoBitSetOnFrameData(host_impl_.get())); @@ -15750,7 +15750,6 @@ InvalidLayerNotAddedToRasterQueue) { CreatePendingTree(); - Region empty_invalidation; scoped_refptr<RasterSource> raster_source_with_tiles( FakeRasterSource::CreateFilled(gfx::Size(10, 10))); @@ -15760,7 +15759,7 @@ host_impl_->active_tree()->GetDeviceViewport().size()); layer->SetDrawsContent(true); layer->tilings()->AddTiling(gfx::AxisTransform2d(), raster_source_with_tiles); - layer->UpdateRasterSource(raster_source_with_tiles, &empty_invalidation); + layer->SetRasterSourceForTesting(raster_source_with_tiles); layer->tilings()->tiling_at(0)->set_resolution( TileResolution::HIGH_RESOLUTION); layer->tilings()->tiling_at(0)->CreateAllTilesForTesting(); @@ -17603,11 +17602,9 @@ root->SetNeedsPushProperties(); // Add a PaintWorkletInput to the PictureLayerImpl. - scoped_refptr<RasterSource> raster_source_with_pws( - FakeRasterSource::CreateFilledWithPaintWorklet(root->bounds())); - Region empty_invalidation; - root->UpdateRasterSource(raster_source_with_pws, &empty_invalidation); - + scoped_refptr<RasterSource> raster_source_with_pws = + FakeRasterSource::CreateFilledWithPaintWorklet(root->bounds()); + root->SetRasterSourceForTesting(raster_source_with_pws); UpdateDrawProperties(host_impl_->pending_tree()); // Since we have dirty PaintWorklets, committing will not cause tile @@ -17652,10 +17649,9 @@ root->SetNeedsPushProperties(); // Add some PaintWorklets. - scoped_refptr<RasterSource> raster_source_with_pws( - FakeRasterSource::CreateFilledWithPaintWorklet(root->bounds())); - Region empty_invalidation; - root->UpdateRasterSource(raster_source_with_pws, &empty_invalidation); + scoped_refptr<RasterSource> raster_source_with_pws = + FakeRasterSource::CreateFilledWithPaintWorklet(root->bounds()); + root->SetRasterSourceForTesting(raster_source_with_pws); UpdateDrawProperties(host_impl_->pending_tree()); @@ -17698,10 +17694,9 @@ root->SetNeedsPushProperties(); // Add a PaintWorkletInput to the PictureLayerImpl. - scoped_refptr<RasterSource> raster_source_with_pws( - FakeRasterSource::CreateFilledWithPaintWorklet(root->bounds())); - Region empty_invalidation; - root->UpdateRasterSource(raster_source_with_pws, &empty_invalidation); + scoped_refptr<RasterSource> raster_source_with_pws = + FakeRasterSource::CreateFilledWithPaintWorklet(root->bounds()); + root->SetRasterSourceForTesting(raster_source_with_pws); UpdateDrawProperties(host_impl_->pending_tree());
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc index ef27083..8e7b74d 100644 --- a/cc/trees/layer_tree_impl.cc +++ b/cc/trees/layer_tree_impl.cc
@@ -434,11 +434,12 @@ void LayerTreeImpl::InvalidateRasterInducingScrolls( const base::flat_set<ElementId>& scrolls_to_invalidate) { + DCHECK(IsSyncTree()); if (scrolls_to_invalidate.empty()) { + did_raster_inducing_scroll_ = false; return; } - DCHECK(IsSyncTree()); - set_did_raster_inducing_scroll(true); + did_raster_inducing_scroll_ = true; for (PictureLayerImpl* picture_layer : picture_layers_) { picture_layer->InvalidateRasterInducingScrolls(scrolls_to_invalidate); } @@ -703,22 +704,30 @@ ClearSurfaceRanges(); SetSurfaceRanges(commit_state.SurfaceRanges()); } - TreeSynchronizer::PushLayerProperties(commit_state, unsafe_state, this); - lifecycle().AdvanceTo(LayerTreeLifecycle::kSyncedLayerProperties); - for (const ElementId& id : commit_state.scrollers_clobbering_active_value) { - property_trees()->scroll_tree_mutable().SetScrollOffsetClobberActiveValue( - id); + { + DiscardableImageMapUpdater updater(this); + TreeSynchronizer::PushLayerProperties(commit_state, unsafe_state, this); + lifecycle().AdvanceTo(LayerTreeLifecycle::kSyncedLayerProperties); + + for (const ElementId& id : commit_state.scrollers_clobbering_active_value) { + property_trees()->scroll_tree_mutable().SetScrollOffsetClobberActiveValue( + id); + } + + // This must happen after synchronizing property trees and after pushing + // properties, which updates the clobber_active_value flag (specifically in + // Layer::PushPropertiesTo). + // TODO(pdr): Enforce this comment with DCHECKS and a lifecycle state. + property_trees()->scroll_tree_mutable().PushScrollUpdatesFromMainThread( + unsafe_state.property_trees, this, + settings().commit_fractional_scroll_deltas); + + // The scope should end (when the DiscardableImageMapUpdater will update + // discardable image maps) after scroll updates because the discardable + // image map may depend on raster-inducing scroll offsets. } - // This must happen after synchronizing property trees and after pushing - // properties, which updates the clobber_active_value flag (specifically in - // Layer::PushPropertiesTo). - // TODO(pdr): Enforce this comment with DCHECKS and a lifecycle state. - property_trees()->scroll_tree_mutable().PushScrollUpdatesFromMainThread( - unsafe_state.property_trees, this, - settings().commit_fractional_scroll_deltas); - PullLayerTreePropertiesFrom(commit_state); PassSwapPromises(std::move(commit_state.swap_promises)); @@ -947,7 +956,7 @@ target_tree->set_trace_id(trace_id()); target_tree->set_background_color(background_color()); target_tree->set_have_scroll_event_handlers(have_scroll_event_handlers()); - target_tree->set_did_raster_inducing_scroll(did_raster_inducing_scroll()); + target_tree->did_raster_inducing_scroll_ = did_raster_inducing_scroll_; target_tree->set_event_listener_properties( EventListenerClass::kTouchStartOrMove, event_listener_properties(EventListenerClass::kTouchStartOrMove)); @@ -3054,4 +3063,26 @@ host_impl_->RequestImplSideInvalidationForRerasterTiling(); } +void LayerTreeImpl::AddLayerNeedingUpdateDiscardableImageMap( + PictureLayerImpl* layer) { + CHECK(discardable_image_map_updater_); + discardable_image_map_updater_->AddLayerNeedingUpdate(layer); +} + +LayerTreeImpl::DiscardableImageMapUpdater::DiscardableImageMapUpdater( + LayerTreeImpl* layer_tree_impl) + : layer_tree_impl_(layer_tree_impl) { + CHECK(layer_tree_impl->IsSyncTree()); + CHECK(!layer_tree_impl->discardable_image_map_updater_); + layer_tree_impl_->discardable_image_map_updater_ = this; +} + +LayerTreeImpl::DiscardableImageMapUpdater::~DiscardableImageMapUpdater() { + DCHECK_EQ(layer_tree_impl_->discardable_image_map_updater_, this); + for (auto& layer : layers_needing_update_) { + layer->RegenerateDiscardableImageMap(); + } + layer_tree_impl_->discardable_image_map_updater_ = nullptr; +} + } // namespace cc
diff --git a/cc/trees/layer_tree_impl.h b/cc/trees/layer_tree_impl.h index b9264ca..13ede79 100644 --- a/cc/trees/layer_tree_impl.h +++ b/cc/trees/layer_tree_impl.h
@@ -26,7 +26,6 @@ #include "cc/layers/layer_impl.h" #include "cc/layers/layer_list_iterator.h" #include "cc/metrics/event_metrics.h" -#include "cc/paint/discardable_image_map.h" #include "cc/resources/ui_resource_client.h" #include "cc/trees/browser_controls_params.h" #include "cc/trees/layer_tree_host.h" @@ -718,9 +717,6 @@ bool did_raster_inducing_scroll() const { return did_raster_inducing_scroll_; } - void set_did_raster_inducing_scroll(bool did_raster_scroll_impl) { - did_raster_inducing_scroll_ = did_raster_scroll_impl; - } // See LayerTreeHost. EventListenerProperties event_listener_properties( @@ -814,6 +810,24 @@ void SetViewTransitionContentRect(const viz::ViewTransitionElementResourceId&, const gfx::RectF&); + void AddLayerNeedingUpdateDiscardableImageMap(PictureLayerImpl* layer); + + class CC_EXPORT DiscardableImageMapUpdater { + STACK_ALLOCATED(); + + public: + explicit DiscardableImageMapUpdater(LayerTreeImpl* layer_tree_impl); + ~DiscardableImageMapUpdater(); + + void AddLayerNeedingUpdate(PictureLayerImpl* layer) { + layers_needing_update_.push_back(layer); + } + + private: + LayerTreeImpl* const layer_tree_impl_; + std::vector<PictureLayerImpl*> layers_needing_update_; + }; + protected: float ClampPageScaleFactorToLimits(float page_scale_factor) const; void PushPageScaleFactorAndLimits(const float* page_scale_factor, @@ -997,6 +1011,10 @@ // See `CommitState::primary_main_frame_item_sequence_number`. int64_t primary_main_frame_item_sequence_number_ = RenderFrameMetadata::kInvalidItemSequenceNumber; + + // Used during PullPropertiesFrom(). + STACK_ALLOCATED_IGNORE("Correctness ensured by DiscardableImageMapUpdater") + raw_ptr<DiscardableImageMapUpdater> discardable_image_map_updater_; }; } // namespace cc
diff --git a/cc/trees/layer_tree_impl_unittest.cc b/cc/trees/layer_tree_impl_unittest.cc index feac51b8..87be7d09 100644 --- a/cc/trees/layer_tree_impl_unittest.cc +++ b/cc/trees/layer_tree_impl_unittest.cc
@@ -2453,13 +2453,12 @@ CopyProperties(root, child2); CopyProperties(root, child3); - Region empty_invalidation; - scoped_refptr<RasterSource> raster_source1( - FakeRasterSource::CreateFilledWithPaintWorklet(child1->bounds())); - child1->UpdateRasterSource(raster_source1, &empty_invalidation); - scoped_refptr<RasterSource> raster_source3( - FakeRasterSource::CreateFilledWithPaintWorklet(child3->bounds())); - child3->UpdateRasterSource(raster_source3, &empty_invalidation); + scoped_refptr<RasterSource> raster_source1 = + FakeRasterSource::CreateFilledWithPaintWorklet(child1->bounds()); + child1->SetRasterSourceForTesting(raster_source1); + scoped_refptr<RasterSource> raster_source3 = + FakeRasterSource::CreateFilledWithPaintWorklet(child3->bounds()); + child3->SetRasterSourceForTesting(raster_source3); // The set should correctly track which layers are in it. const base::flat_set<raw_ptr<PictureLayerImpl, CtnExperimental>>& layers = @@ -2469,9 +2468,10 @@ EXPECT_TRUE(layers.contains(child3)); // Test explicitly removing a layer from the set. - scoped_refptr<RasterSource> empty_raster_source( - FakeRasterSource::CreateFilled(child1->bounds())); - child1->UpdateRasterSource(empty_raster_source, &empty_invalidation); + scoped_refptr<RasterSource> empty_raster_source = + FakeRasterSource::CreateFilled(child1->bounds()); + child1->SetRasterSourceForTesting(empty_raster_source); + EXPECT_EQ(layers.size(), 1u); EXPECT_FALSE(layers.contains(child1));
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn index 9f046f2c..7ae2e00 100644 --- a/chrome/BUILD.gn +++ b/chrome/BUILD.gn
@@ -1652,7 +1652,6 @@ deps = [ ":dependencies", - "//chrome/browser/flags:flags_android", "//chrome/browser/ui", "//chrome/child", "//chrome/common", @@ -1660,19 +1659,17 @@ "//chrome/common/profiler", "//chrome/gpu", "//chrome/renderer", - "//components/crash/android:crash_android", "//components/minidump_uploader", "//components/safe_browsing:buildflags", "//components/safe_browsing/android:safe_browsing_api_handler", "//components/safe_browsing/android:safe_browsing_mobile", "//components/stylus_handwriting/android", - "//components/variations:variations_associated_data", "//content/public/app", ] # Explicit dependency required for JNI registration to be able to # find the native side functions. - if (is_component_build) { + if (is_android && is_component_build) { deps += [ "//components/viz/service", "//device/gamepad", @@ -1680,6 +1677,13 @@ ] } + if (is_android) { + deps += [ + "//chrome/browser/flags:flags_android", + "//components/crash/android:crash_android", + ] + } + if (is_chromeos) { public_deps += [ "//ui/lottie" ] deps += [ "//chrome/browser/ash/schedqos" ]
diff --git a/chrome/android/expectations/monochrome_64_32_public_bundle.proguard_flags.expected b/chrome/android/expectations/monochrome_64_32_public_bundle.proguard_flags.expected index 057ddb20..89f35e9 100644 --- a/chrome/android/expectations/monochrome_64_32_public_bundle.proguard_flags.expected +++ b/chrome/android/expectations/monochrome_64_32_public_bundle.proguard_flags.expected
@@ -140,16 +140,16 @@ # Use assumevalues in addition to assumenosideeffects block because Google3 proguard cannot parse # assumenosideeffects blocks which overwrite return value. -assumevalues class ** { - @org.chromium.build.annotations.AssumeNonNull *** *(...) return _NONNULL_; + @org.chromium.build.annotations.OptimizeAsNonNull *** *(...) return _NONNULL_; } -assumenosideeffects class ** { - @org.chromium.build.annotations.AssumeNonNull *** *(...); + @org.chromium.build.annotations.OptimizeAsNonNull *** *(...); } -assumevalues class ** { - @org.chromium.build.annotations.AssumeNonNull *** * return _NONNULL_; + @org.chromium.build.annotations.OptimizeAsNonNull *** * return _NONNULL_; } -assumenosideeffects class ** { - @org.chromium.build.annotations.AssumeNonNull *** *; + @org.chromium.build.annotations.OptimizeAsNonNull *** *; } # File: ../../base/android/proguard/chromium_apk.flags
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/ReorderDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/ReorderDelegate.java index 12a124df..dac7e61 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/ReorderDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/ReorderDelegate.java
@@ -150,6 +150,10 @@ return Boolean.TRUE.equals(mInReorderModeSupplier.get()); } + boolean isReorderingTab() { + return getInReorderMode() && mActiveStrategy == mTabStrategy; + } + boolean getReorderingForTabDrop() { return getInReorderMode() && mActiveStrategy == mExternalViewDragDropReorderStrategy; } @@ -556,18 +560,15 @@ // we should not set the new offset here, and instead let the tab slide back to its // idealX. if (!getInReorderMode()) return; - // 3.b. Since we just moved the tab we're dragging, adjust its offset so it stays in - // the same apparent position. - offset += oldIdealX - mInteractingTab.getIdealX(); - // 3.c. When the strip is scrolling, deltaX is already accounted for by idealX. This - // is because it uses the scroll offset which has already been adjusted by deltaX. - if (mLastReorderScrollTime != 0) offset -= deltaX; - // 3.d. Group titles can affect minScrollOffset. When scrolled near the end of the - // strip, the scrollOffset being clamped can affect the apparent position. - oldScrollOffset += oldStartMargin - mScrollDelegate.getReorderStartMargin(); - offset -= - MathUtils.flipSignIf( - (mScrollDelegate.getScrollOffset() - oldScrollOffset), isRtl); + + offset = + adjustOffsetAfterReorder( + mInteractingTab, + offset, + deltaX, + oldIdealX, + oldScrollOffset, + oldStartMargin); } // 4. Limit offset based on tab position. First tab can't drag left, last tab can't drag @@ -695,9 +696,9 @@ StripLayoutTab interactingTab, float offset, int curIndex) { - boolean towardEnd = (offset >= 0) ^ LocalizationUtils.isLayoutRtl(); + boolean towardEnd = isOffsetTowardEnd(offset); Tab curTab = mModel.getTabAt(curIndex); - Tab adjTab = mModel.getTabAt(curIndex + (towardEnd ? 1 : -1)); + Tab adjTab = mModel.getTabAt(/* index= */ curIndex + (towardEnd ? 1 : -1)); boolean isInGroup = mTabGroupModelFilter.isTabInTabGroup(curTab); boolean mayDragInOrOutOfGroup = adjTab == null @@ -707,7 +708,12 @@ // Case A: Not interacting with tab groups. if (!mayDragInOrOutOfGroup) { - return maybeSwapTab(stripTabs, interactingTab, offset, curIndex); + if (adjTab == null || Math.abs(offset) <= getTabSwapThreshold()) return false; + + int destIndex = towardEnd ? curIndex + 2 : curIndex - 1; + mModel.moveTab(interactingTab.getTabId(), destIndex); + animateViewSliding(stripTabs[curIndex]); + return true; } // Case B: Maybe drag out of group. @@ -844,44 +850,48 @@ } /** - * Swaps the interacting tab with the adjacent tab, if the drag threshold has been reached. - * Animates accordingly. - * - * @param stripTabs The list of {@link StripLayoutTab}. - * @param interactingTab The tab to swap with adjacent tab. - * @param offset The distance the interacting tab has been dragged from its ideal position. - * @param curIndex The index of the interacting tab. - * @return {@code True} if the reorder was successful. {@code False} otherwise. + * @param offset The offset of the current drag. + * @return {@code true} if we're dragging towards the end of the strip. {@code false} otherwise. */ - private boolean maybeSwapTab( - StripLayoutTab[] stripTabs, StripLayoutTab interactingTab, float offset, int curIndex) { - // TODO(crbug.com/372546700): Migrate to the pattern we use for the other reorder cases. - // i.e. check if we've reached the drag threshold in #reorderTabIfThresholdReached. - final float moveThreshold = REORDER_OVERLAP_SWITCH_PERCENTAGE * getEffectiveTabWidth(); - boolean pastLeftThreshold = offset < -moveThreshold; - boolean pastRightThreshold = offset > moveThreshold; - boolean isNotRightMost = curIndex < stripTabs.length - 1; - boolean isNotLeftMost = curIndex > 0; + private boolean isOffsetTowardEnd(float offset) { + return (offset >= 0) ^ LocalizationUtils.isLayoutRtl(); + } - if (LocalizationUtils.isLayoutRtl()) { - boolean oldLeft = pastLeftThreshold; - pastLeftThreshold = pastRightThreshold; - pastRightThreshold = oldLeft; - } + /** + * Adjusts the drag offset such that no apparent movement occurs for the view after a reorder is + * processed. e.g. account for new idealX, scroll offset clamping, etc. + * + * @param interactingView The view that is being dragged for reorder. + * @param offset The previous drag offset. + * @param deltaX The change in drag offset since it was last processed. + * @param oldIdealX The interacting view's {@code idealX} prior to the reorder. + * @param oldScrollOffset The scroll offset prior to the reorder. + * @param oldStartMargin The start margin prior to the reorder. + * @return The new drag offset to prevent any apparent movement. + */ + private float adjustOffsetAfterReorder( + StripLayoutView interactingView, + float offset, + float deltaX, + float oldIdealX, + float oldScrollOffset, + float oldStartMargin) { + // Account for the new idealX after reorder. + offset += oldIdealX - interactingView.getIdealX(); + // When the strip is scrolling, deltaX is already accounted for by idealX. This is because + // it uses the scroll offset which has already been adjusted by deltaX. + if (mLastReorderScrollTime != 0) offset -= deltaX; + // When scrolled near the end of the strip, the scrollOffset being clamped can affect the + // apparent position. + oldScrollOffset += oldStartMargin - mScrollDelegate.getReorderStartMargin(); + float scrollOffsetDelta = mScrollDelegate.getScrollOffset() - oldScrollOffset; + offset -= MathUtils.flipSignIf(scrollOffsetDelta, LocalizationUtils.isLayoutRtl()); + return offset; + } - int destIndex = Tab.INVALID_TAB_ID; - if (pastRightThreshold && isNotRightMost) { - destIndex = curIndex + 2; - } else if (pastLeftThreshold && isNotLeftMost) { - destIndex = curIndex - 1; - } - - if (destIndex == Tab.INVALID_TAB_ID) return false; - - // Move the tab, then animate the adjacent tab sliding. - mModel.moveTab(interactingTab.getTabId(), destIndex); - animateViewSliding(stripTabs[curIndex]); - return true; + /** Returns the threshold to swap the interacting views with an adjacent tab. */ + private float getTabSwapThreshold() { + return getEffectiveTabWidth() * REORDER_OVERLAP_SWITCH_PERCENTAGE; } /** @@ -894,23 +904,17 @@ return dragOutThreshold + (towardEnd ? 0 : groupTitle.getWidth()); } - /** - * @return The threshold to drag into a group. - */ + /** Returns the threshold to drag into a group. */ private float getDragInThreshold() { return getHalfTabWidth() * REORDER_OVERLAP_SWITCH_PERCENTAGE; } - /** - * @return Half of mEffectiveTabWidth. - */ + /** Returns half of {@code mEffectiveTabWidth}. */ private float getHalfTabWidth() { return getEffectiveTabWidth() / 2; } - /** - * @return Current effective tab width (accounting for overlap). - */ + /** Returns the current effective tab width (accounting for overlap). */ private float getEffectiveTabWidth() { return (mTabWidthSupplier.get() - TAB_OVERLAP_WIDTH_DP); } @@ -923,6 +927,7 @@ StripLayoutGroupTitle mInteractingGroupTitle; ArrayList<StripLayoutView> mInteractingViews = new ArrayList<>(); StripLayoutTab mSelectedTab; + StripLayoutTab mFirstTabInGroup; StripLayoutTab mLastTabInGroup; @Override @@ -937,6 +942,7 @@ List<StripLayoutTab> groupedTabs = StripLayoutUtils.getGroupedTabs( mModel, stripTabs, mInteractingGroupTitle.getRootId()); + mFirstTabInGroup = groupedTabs.get(0); mLastTabInGroup = groupedTabs.get(groupedTabs.size() - 1); mLastTabInGroup.setForceHideEndDivider(/* forceHide= */ true); mInteractingViews.addAll(groupedTabs); @@ -968,9 +974,24 @@ float endX, float deltaX, @ReorderType int reorderType) { - // TODO(crbug.com/376069497): Implement. Currently just offsetting for testing. + float oldIdealX = mInteractingGroupTitle.getIdealX(); + float oldScrollOffset = mScrollDelegate.getScrollOffset(); + float offset = mInteractingGroupTitle.getOffsetX() + deltaX; + + if (reorderGroupIfThresholdReached(stripTabs, offset)) { + offset = + adjustOffsetAfterReorder( + mInteractingGroupTitle, + offset, + deltaX, + oldIdealX, + oldScrollOffset, + /* oldStartMargin= */ 0.f); + } + + // TODO(crbug.com/388563582): Clamp to scrollable region. for (StripLayoutView view : mInteractingViews) { - view.setOffsetX(view.getOffsetX() + deltaX); + view.setOffsetX(offset); } } @@ -1029,6 +1050,48 @@ public StripLayoutView getInteractingView() { return mInteractingGroupTitle; } + + /** + * Handles the two different reordering cases: + * + * <pre> + * A] Dragging past an adjacent group. + * B] Dragging past an adjacent (ungrouped_ tab. + * </pre> + * + * If the group has been dragged past the threshold for the given case, update the {@link + * TabModel} and return {@code true}. Else, return {@code false}. + * + * @param stripTabs The list of {@link StripLayoutTab}. + * @param offset The distance the group has been dragged from its ideal position. + * @return {@code True} if the reorder was successful. {@code False} otherwise. + */ + private boolean reorderGroupIfThresholdReached(StripLayoutTab[] stripTabs, float offset) { + boolean towardEnd = isOffsetTowardEnd(offset); + int firstTabIndex = + StripLayoutUtils.findIndexForTab(stripTabs, mFirstTabInGroup.getTabId()); + int lastTabIndex = + StripLayoutUtils.findIndexForTab(stripTabs, mLastTabInGroup.getTabId()); + + // Find the tab we're dragging past. Return if none (i.e. dragging towards strip edge). + int adjTabIndex = towardEnd ? lastTabIndex + 1 : firstTabIndex - 1; + if (adjTabIndex >= stripTabs.length || adjTabIndex < 0) return false; + StripLayoutTab adjStripTab = stripTabs[adjTabIndex]; + + if (mTabGroupModelFilter.isTabInTabGroup(mModel.getTabById(adjStripTab.getTabId()))) { + // Case A: Attempt to drag past adjacent group. + // TODO(crbug.com/376066293): Implement. + return false; + } else { + // Case B: Attempt to drab past ungrouped tab. + if (Math.abs(offset) <= getTabSwapThreshold()) return false; + + int destIndex = towardEnd ? adjTabIndex + 1 : adjTabIndex; + mTabGroupModelFilter.moveRelatedTabs(mInteractingGroupTitle.getRootId(), destIndex); + animateViewSliding(adjStripTab); + return true; + } + } } // ============================================================================================
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java index 94ef73d..8c7af30 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java
@@ -1281,7 +1281,7 @@ // 2. Swap the tabs. StripLayoutUtils.moveElement(mStripTabs, index, newIndex); if (!mMovingGroup) { - if (mReorderDelegate.getInReorderMode()) { + if (mReorderDelegate.isReorderingTab()) { // Update strip start and end margins to create more space for first tab or last tab // to drag out of group. mReorderDelegate.setEdgeMarginsForReorder(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/feedback/ChromeFeedbackCollector.java b/chrome/android/java/src/org/chromium/chrome/browser/feedback/ChromeFeedbackCollector.java index 0f4a8f3c..cc827cd2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/feedback/ChromeFeedbackCollector.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/feedback/ChromeFeedbackCollector.java
@@ -62,7 +62,6 @@ sources.add(new DeviceInfoFeedbackSource()); sources.add(new UrlFeedbackSource(initParams.url)); sources.add(new VariationsFeedbackSource(initParams.profile)); - sources.add(new VariationsStateFeedbackSource(initParams.profile)); sources.add(new HistogramFeedbackSource(initParams.profile)); sources.add(new LowEndDeviceFeedbackSource()); sources.add(new IMEFeedbackSource());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/handler/PaymentHandlerMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/handler/PaymentHandlerMediator.java index c5d9501..d9450a86 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/handler/PaymentHandlerMediator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/handler/PaymentHandlerMediator.java
@@ -221,7 +221,7 @@ // Implement WebContentsObserver: @Override - public void destroy() { + public void onDestroy() { ApplicationStatus.unregisterActivityStateListener(mActivityStateListener); switch (mCloseReason) { @@ -255,7 +255,6 @@ } mHandler.removeCallbacksAndMessages(null); hideScrim(); - super.destroy(); // Stops observing the web contents and cleans up associated references. } private void hideScrim() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsObserver.java index 08bcddf..e3958f95 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsObserver.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsObserver.java
@@ -381,7 +381,7 @@ } @Override - public void destroy() { + public void onDestroy() { MediaCaptureNotificationServiceImpl.updateMediaNotificationForTab( ContextUtils.getApplicationContext(), mTab.getId(), null, mLastUrl); BluetoothNotificationManager.updateBluetoothNotificationForTab( @@ -398,7 +398,6 @@ null, mLastUrl, mTab.isIncognito()); - super.destroy(); } } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/TabsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/TabsTest.java index d68f563..8bc54bd9 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/TabsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/TabsTest.java
@@ -849,8 +849,7 @@ WebContentsObserver observer = new WebContentsObserver(tab.getWebContents()) { @Override - public void destroy() { - super.destroy(); + public void onDestroy() { webContentsDestroyed.notifyCalled(); } };
diff --git a/chrome/android/webapk/libs/runtime_library/src/org/chromium/webapk/lib/runtime_library/WebApkServiceImpl.java b/chrome/android/webapk/libs/runtime_library/src/org/chromium/webapk/lib/runtime_library/WebApkServiceImpl.java index 11c5723..9b9e8f5 100644 --- a/chrome/android/webapk/libs/runtime_library/src/org/chromium/webapk/lib/runtime_library/WebApkServiceImpl.java +++ b/chrome/android/webapk/libs/runtime_library/src/org/chromium/webapk/lib/runtime_library/WebApkServiceImpl.java
@@ -18,7 +18,11 @@ import android.text.TextUtils; import android.util.Log; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; + /** Implements services offered by the WebAPK to Chrome. */ +@NullMarked public class WebApkServiceImpl extends IWebApkApi.Stub { public static final String KEY_SMALL_ICON_ID = "small_icon_id"; @@ -114,7 +118,8 @@ } @Override - public PendingIntent requestNotificationPermission(String channelName, String channelId) { + public @Nullable PendingIntent requestNotificationPermission( + String channelName, String channelId) { Log.w( TAG, "Should NOT reach WebApkServiceImpl#requestNotificationPermission(String," @@ -123,7 +128,7 @@ } /** Returns the package name of the task's base activity. */ - private static String getTaskBaseActivityPackageName(ActivityManager.AppTask task) { + private static @Nullable String getTaskBaseActivityPackageName(ActivityManager.AppTask task) { try { ActivityManager.RecentTaskInfo info = task.getTaskInfo(); if (info != null && info.baseActivity != null) {
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index f2ca1bf..0c50d984 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -4302,7 +4302,7 @@ {"feedback-include-variations", flag_descriptions::kFeedbackIncludeVariationsName, flag_descriptions::kFeedbackIncludeVariationsDescription, - kOsWin | kOsLinux | kOsMac | kOsAndroid, + kOsWin | kOsLinux | kOsMac, FEATURE_VALUE_TYPE(variations::kFeedbackIncludeVariations)}, #endif {"ui-disable-partial-swap", flag_descriptions::kUiPartialSwapName, @@ -11115,6 +11115,10 @@ flag_descriptions::kPermissionPredictionsV3Description, kOsAll, FEATURE_VALUE_TYPE(permissions::features::kPermissionPredictionsV3)}, + {"permissions-ai-v1", flag_descriptions::kPermissionsAIv1Name, + flag_descriptions::kPermissionsAIv1Description, kOsDesktop, + FEATURE_VALUE_TYPE(permissions::features::kPermissionsAIv1)}, + #if BUILDFLAG(IS_CHROMEOS) {"exclude-display-in-mirror-mode", flag_descriptions::kExcludeDisplayInMirrorModeName,
diff --git a/chrome/browser/accessibility/hierarchysnapshotter/android/java/src/org/chromium/chrome/browser/accessibility/hierarchysnapshotter/HierarchySnapshotter.java b/chrome/browser/accessibility/hierarchysnapshotter/android/java/src/org/chromium/chrome/browser/accessibility/hierarchysnapshotter/HierarchySnapshotter.java index 52c0745b..521d094 100644 --- a/chrome/browser/accessibility/hierarchysnapshotter/android/java/src/org/chromium/chrome/browser/accessibility/hierarchysnapshotter/HierarchySnapshotter.java +++ b/chrome/browser/accessibility/hierarchysnapshotter/android/java/src/org/chromium/chrome/browser/accessibility/hierarchysnapshotter/HierarchySnapshotter.java
@@ -5,12 +5,14 @@ package org.chromium.chrome.browser.accessibility.hierarchysnapshotter; import org.chromium.base.ServiceLoaderUtil; +import org.chromium.build.annotations.NullMarked; /** * Base class to handle the HierarchySnapshotter functionality. This will allow Chrome to output * custom AccessibilityNodeInfo attributes during ui dumps, such as those used by uiautomator or * go/HSV. */ +@NullMarked public class HierarchySnapshotter { /** Initialize a HierarchySnapshotter. */ public static void initialize() {
diff --git a/chrome/browser/accessibility/hierarchysnapshotter/android/java/src/org/chromium/chrome/browser/accessibility/hierarchysnapshotter/HierarchySnapshotterDelegate.java b/chrome/browser/accessibility/hierarchysnapshotter/android/java/src/org/chromium/chrome/browser/accessibility/hierarchysnapshotter/HierarchySnapshotterDelegate.java index e5fd51f..865e993 100644 --- a/chrome/browser/accessibility/hierarchysnapshotter/android/java/src/org/chromium/chrome/browser/accessibility/hierarchysnapshotter/HierarchySnapshotterDelegate.java +++ b/chrome/browser/accessibility/hierarchysnapshotter/android/java/src/org/chromium/chrome/browser/accessibility/hierarchysnapshotter/HierarchySnapshotterDelegate.java
@@ -4,10 +4,13 @@ package org.chromium.chrome.browser.accessibility.hierarchysnapshotter; +import org.chromium.build.annotations.NullMarked; + /** * Base class for defining methods where different behavior is required by downstream targets for * the HierarchySnapshotter. */ +@NullMarked public class HierarchySnapshotterDelegate { /** * @see {@link HierarchySnapshotter#initialize()}
diff --git a/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.cc b/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.cc index 971ecfae..f15081d 100644 --- a/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.cc +++ b/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.cc
@@ -31,6 +31,8 @@ group_ui_parent_layer_(cc::slim::Layer::Create()), scrollable_strip_layer_(cc::slim::Layer::Create()), foreground_layer_(cc::slim::Layer::Create()), + foreground_tabs_(cc::slim::Layer::Create()), + foreground_group_titles_(cc::slim::Layer::Create()), new_tab_button_(cc::slim::UIResourceLayer::Create()), new_tab_button_background_(cc::slim::UIResourceLayer::Create()), left_fade_(cc::slim::UIResourceLayer::Create()), @@ -59,10 +61,15 @@ group_ui_parent_layer_->SetIsDrawable(true); scrollable_strip_layer_->SetIsDrawable(true); foreground_layer_->SetIsDrawable(true); + foreground_tabs_->SetIsDrawable(true); + foreground_group_titles_->SetIsDrawable(true); tab_strip_layer_->SetIsDrawable(true); + tab_strip_layer_->AddChild(group_ui_parent_layer_); tab_strip_layer_->AddChild(scrollable_strip_layer_); tab_strip_layer_->AddChild(foreground_layer_); + foreground_layer_->AddChild(foreground_group_titles_); + foreground_layer_->AddChild(foreground_tabs_); tab_strip_layer_->AddChild(left_fade_); tab_strip_layer_->AddChild(right_fade_); @@ -422,7 +429,7 @@ if (foreground != layer->foreground()) { if (foreground) { - foreground_layer_->AddChild(layer->layer()); + foreground_tabs_->AddChild(layer->layer()); } else { scrollable_strip_layer_->AddChild(layer->layer()); } @@ -486,7 +493,7 @@ // Foreground if needed. if (foreground != layer->foreground()) { if (foreground) { - foreground_layer_->AddChild(layer->layer()); + foreground_group_titles_->AddChild(layer->layer()); } else { group_ui_parent_layer_->AddChild(layer->layer()); }
diff --git a/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.h b/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.h index f92a17d..e00247c 100644 --- a/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.h +++ b/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.h
@@ -207,6 +207,8 @@ scoped_refptr<cc::slim::Layer> group_ui_parent_layer_; scoped_refptr<cc::slim::Layer> scrollable_strip_layer_; scoped_refptr<cc::slim::Layer> foreground_layer_; + scoped_refptr<cc::slim::Layer> foreground_tabs_; + scoped_refptr<cc::slim::Layer> foreground_group_titles_; scoped_refptr<cc::slim::UIResourceLayer> new_tab_button_; scoped_refptr<cc::slim::UIResourceLayer> new_tab_button_background_; scoped_refptr<cc::slim::UIResourceLayer> left_fade_;
diff --git a/chrome/browser/android/httpclient/public/src/org/chromium/chrome/browser/android/httpclient/ChromeHttpClient.java b/chrome/browser/android/httpclient/public/src/org/chromium/chrome/browser/android/httpclient/ChromeHttpClient.java index 5e3075ef..0f56111 100644 --- a/chrome/browser/android/httpclient/public/src/org/chromium/chrome/browser/android/httpclient/ChromeHttpClient.java +++ b/chrome/browser/android/httpclient/public/src/org/chromium/chrome/browser/android/httpclient/ChromeHttpClient.java
@@ -4,9 +4,12 @@ package org.chromium.chrome.browser.android.httpclient; +import org.chromium.build.annotations.NullMarked; + import java.util.Map; /** A simple HttpClient interface. */ +@NullMarked public interface ChromeHttpClient { void send( String url,
diff --git a/chrome/browser/android/httpclient/public/src/org/chromium/chrome/browser/android/httpclient/HttpResponseCallback.java b/chrome/browser/android/httpclient/public/src/org/chromium/chrome/browser/android/httpclient/HttpResponseCallback.java index 800c7c00..5195583 100644 --- a/chrome/browser/android/httpclient/public/src/org/chromium/chrome/browser/android/httpclient/HttpResponseCallback.java +++ b/chrome/browser/android/httpclient/public/src/org/chromium/chrome/browser/android/httpclient/HttpResponseCallback.java
@@ -4,9 +4,12 @@ package org.chromium.chrome.browser.android.httpclient; +import org.chromium.build.annotations.NullMarked; + import java.util.Map; /** HttpClient callback interface. */ +@NullMarked public interface HttpResponseCallback { void accept(int status, byte[] body, Map<String, String> headers); }
diff --git a/chrome/browser/android/lifecycle/DEPS b/chrome/browser/android/lifecycle/DEPS index 7cf2601..5cf8d3d 100644 --- a/chrome/browser/android/lifecycle/DEPS +++ b/chrome/browser/android/lifecycle/DEPS
@@ -2,6 +2,7 @@ include_rules = [ "+base/android", + "+build/android", "-content/public/android", "+content/public/android/java/src/org/chromium/content_public",
diff --git a/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/ActivityLifecycleDispatcher.java b/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/ActivityLifecycleDispatcher.java index 65c4c00..c55bc82 100644 --- a/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/ActivityLifecycleDispatcher.java +++ b/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/ActivityLifecycleDispatcher.java
@@ -6,10 +6,13 @@ import androidx.annotation.IntDef; +import org.chromium.build.annotations.NullMarked; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** Manages registration of {@link LifecycleObserver} instances. */ +@NullMarked public interface ActivityLifecycleDispatcher { /** A set of states that represent the last state change of an Activity. */ @Retention(RetentionPolicy.SOURCE)
diff --git a/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/ActivityLifecycleDispatcherProvider.java b/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/ActivityLifecycleDispatcherProvider.java index 75213e8..b82dd0e 100644 --- a/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/ActivityLifecycleDispatcherProvider.java +++ b/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/ActivityLifecycleDispatcherProvider.java
@@ -4,7 +4,10 @@ package org.chromium.chrome.browser.lifecycle; +import org.chromium.build.annotations.NullMarked; + /** Simple interface that provides {@link ActivityLifecycleDispatcher}. */ +@NullMarked public interface ActivityLifecycleDispatcherProvider { /** Return the {@link ActivityLifecycleDispatcher} associated with this provider. */
diff --git a/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/ActivityResultWithNativeObserver.java b/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/ActivityResultWithNativeObserver.java index 09c4c11..c17bcb88 100644 --- a/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/ActivityResultWithNativeObserver.java +++ b/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/ActivityResultWithNativeObserver.java
@@ -6,10 +6,13 @@ import android.content.Intent; +import org.chromium.build.annotations.NullMarked; + /** * Implement this interface and register in {@link ActivityLifecycleDispatcher} to receive * activity result methods. */ +@NullMarked public interface ActivityResultWithNativeObserver extends LifecycleObserver { /** * Called when {@link
diff --git a/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/ConfigurationChangedObserver.java b/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/ConfigurationChangedObserver.java index 89fb054..7b59b00 100644 --- a/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/ConfigurationChangedObserver.java +++ b/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/ConfigurationChangedObserver.java
@@ -6,10 +6,13 @@ import android.content.res.Configuration; +import org.chromium.build.annotations.NullMarked; + /** * Implement this interface and register in {@link ActivityLifecycleDispatcher} to be notified of * configuration changes. */ +@NullMarked public interface ConfigurationChangedObserver extends LifecycleObserver { /** * Called when the Activity configuration changes. See
diff --git a/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/DestroyObserver.java b/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/DestroyObserver.java index 37b3152f..0df209eb 100644 --- a/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/DestroyObserver.java +++ b/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/DestroyObserver.java
@@ -4,10 +4,13 @@ package org.chromium.chrome.browser.lifecycle; +import org.chromium.build.annotations.NullMarked; + /** * Implement this interface and register in {@link * org.chromium.chrome.browser.init.ActivityLifecycleDispatcher} to receive destroy events. */ +@NullMarked public interface DestroyObserver extends LifecycleObserver { /** Called when activity is being destroyed. */ void onDestroy();
diff --git a/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/InflationObserver.java b/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/InflationObserver.java index b6b312c..7f2da905 100644 --- a/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/InflationObserver.java +++ b/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/InflationObserver.java
@@ -4,10 +4,13 @@ package org.chromium.chrome.browser.lifecycle; +import org.chromium.build.annotations.NullMarked; + /** * Implement this interface and register in {@link ActivityLifecycleDispatcher} to receive * inflation-related events. */ +@NullMarked public interface InflationObserver extends LifecycleObserver { /** * Called immediately before the view hierarchy is inflated.
diff --git a/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/LifecycleObserver.java b/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/LifecycleObserver.java index 3bbf7fe..87400ff 100644 --- a/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/LifecycleObserver.java +++ b/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/LifecycleObserver.java
@@ -4,5 +4,8 @@ package org.chromium.chrome.browser.lifecycle; +import org.chromium.build.annotations.NullMarked; + /** Parent interface for lifecycle observer interfaces. */ +@NullMarked public interface LifecycleObserver {}
diff --git a/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/NativeInitObserver.java b/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/NativeInitObserver.java index 8c522309..943ab89 100644 --- a/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/NativeInitObserver.java +++ b/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/NativeInitObserver.java
@@ -4,10 +4,13 @@ package org.chromium.chrome.browser.lifecycle; +import org.chromium.build.annotations.NullMarked; + /** * Implement this interface and register in {@link ActivityLifecycleDispatcher} to get notified of * native having been loaded. */ +@NullMarked public interface NativeInitObserver extends LifecycleObserver { /** Called when the native library has finished loading. */ void onFinishNativeInitialization();
diff --git a/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/OnUserLeaveHintObserver.java b/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/OnUserLeaveHintObserver.java index 4375f69..2f78703 100644 --- a/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/OnUserLeaveHintObserver.java +++ b/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/OnUserLeaveHintObserver.java
@@ -4,10 +4,13 @@ package org.chromium.chrome.browser.lifecycle; +import org.chromium.build.annotations.NullMarked; + /** * Implement this interface and register in {@link ActivityLifecycleDispatcher} to receive * onUserLeaveHint events. */ +@NullMarked public interface OnUserLeaveHintObserver extends LifecycleObserver { /** Called when an activity is about to go into the background as the result of user choice. */ void onUserLeaveHint();
diff --git a/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/PauseResumeWithNativeObserver.java b/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/PauseResumeWithNativeObserver.java index 714bcb7..7c61e84 100644 --- a/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/PauseResumeWithNativeObserver.java +++ b/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/PauseResumeWithNativeObserver.java
@@ -4,10 +4,13 @@ package org.chromium.chrome.browser.lifecycle; +import org.chromium.build.annotations.NullMarked; + /** * Implement this interface and register in {@link ActivityLifecycleDispatcher} to receive pause and * resume with native events. */ +@NullMarked public interface PauseResumeWithNativeObserver extends LifecycleObserver { /** * Called when activity is resumed, provided that native is initialized.
diff --git a/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/RecreateObserver.java b/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/RecreateObserver.java index 4a27594a..a9060d0 100644 --- a/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/RecreateObserver.java +++ b/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/RecreateObserver.java
@@ -4,11 +4,14 @@ package org.chromium.chrome.browser.lifecycle; +import org.chromium.build.annotations.NullMarked; + /** * Implement this interface and register in {@link ActivityLifecycleDispatcher} to receive activity * recreate events. * */ +@NullMarked public interface RecreateObserver extends LifecycleObserver { /** Called when the activity is going to recreate. */ void onRecreate();
diff --git a/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/SaveInstanceStateObserver.java b/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/SaveInstanceStateObserver.java index 7ad79b8..edf0131 100644 --- a/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/SaveInstanceStateObserver.java +++ b/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/SaveInstanceStateObserver.java
@@ -6,10 +6,13 @@ import android.os.Bundle; +import org.chromium.build.annotations.NullMarked; + /** * Implement this interface and register in {@link ActivityLifecycleDispatcher} to receive * onSaveInstanceState events. */ +@NullMarked public interface SaveInstanceStateObserver extends LifecycleObserver { /** Called before activity begins to stop. */ void onSaveInstanceState(Bundle outState);
diff --git a/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/StartStopWithNativeObserver.java b/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/StartStopWithNativeObserver.java index 799975e5..9b541f72 100644 --- a/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/StartStopWithNativeObserver.java +++ b/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/StartStopWithNativeObserver.java
@@ -4,10 +4,13 @@ package org.chromium.chrome.browser.lifecycle; +import org.chromium.build.annotations.NullMarked; + /** * Implement this interface and register in {@link ActivityLifecycleDispatcher} to receive start and * stop with native events. */ +@NullMarked public interface StartStopWithNativeObserver extends LifecycleObserver { /** * Called when activity is started, provided that native is initialized.
diff --git a/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/TopResumedActivityChangedObserver.java b/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/TopResumedActivityChangedObserver.java index ce98d32..e89b846 100644 --- a/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/TopResumedActivityChangedObserver.java +++ b/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/TopResumedActivityChangedObserver.java
@@ -6,10 +6,13 @@ import android.app.Activity; +import org.chromium.build.annotations.NullMarked; + /** * Implement this interface and register in {@link ActivityLifecycleDispatcher} to receive * onTopResumedActivityChanged events. */ +@NullMarked public interface TopResumedActivityChangedObserver extends LifecycleObserver { /** * Called when an activity gets or loses the top resumed position in the system. See {@link
diff --git a/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/WindowFocusChangedObserver.java b/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/WindowFocusChangedObserver.java index 9072eeb..616ade74 100644 --- a/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/WindowFocusChangedObserver.java +++ b/chrome/browser/android/lifecycle/java/src/org/chromium/chrome/browser/lifecycle/WindowFocusChangedObserver.java
@@ -4,10 +4,13 @@ package org.chromium.chrome.browser.lifecycle; +import org.chromium.build.annotations.NullMarked; + /** * Implement this interface and register in {@link ActivityLifecycleDispatcher} to receive * onWindowFocusChange events. */ +@NullMarked public interface WindowFocusChangedObserver extends LifecycleObserver { /** Called when the current Window of the activity gains or loses focus. */ void onWindowFocusChanged(boolean hasFocus);
diff --git a/chrome/browser/android/messages/java/src/org/chromium/chrome/browser/messages/MessagesResourceMapperInitializer.java b/chrome/browser/android/messages/java/src/org/chromium/chrome/browser/messages/MessagesResourceMapperInitializer.java index dc7529e..3be23da1 100644 --- a/chrome/browser/android/messages/java/src/org/chromium/chrome/browser/messages/MessagesResourceMapperInitializer.java +++ b/chrome/browser/android/messages/java/src/org/chromium/chrome/browser/messages/MessagesResourceMapperInitializer.java
@@ -6,7 +6,10 @@ import org.jni_zero.NativeMethods; +import org.chromium.build.annotations.NullMarked; + /** Helper class to initialize ResourceIdMapper for MessageDispatcherBridge. */ +@NullMarked public class MessagesResourceMapperInitializer { /** Calls native method to initialize ResourceIdMapper for MessageDispatcherBridge. */ public static void init() {
diff --git a/chrome/browser/android/metrics/java/src/org/chromium/chrome/browser/metrics/AppUpdateInfoDelegate.java b/chrome/browser/android/metrics/java/src/org/chromium/chrome/browser/metrics/AppUpdateInfoDelegate.java index e2a2e91..6b355f8 100644 --- a/chrome/browser/android/metrics/java/src/org/chromium/chrome/browser/metrics/AppUpdateInfoDelegate.java +++ b/chrome/browser/android/metrics/java/src/org/chromium/chrome/browser/metrics/AppUpdateInfoDelegate.java
@@ -3,7 +3,10 @@ // found in the LICENSE file. package org.chromium.chrome.browser.metrics; +import org.chromium.build.annotations.NullMarked; + /** Base class for defining methods where different behavior is required by downstream targets. */ +@NullMarked public class AppUpdateInfoDelegate { public void emitToHistogram() {} }
diff --git a/chrome/browser/apps/guest_view/web_view_browsertest.cc b/chrome/browser/apps/guest_view/web_view_browsertest.cc index ae2762e93..7b5bf5c 100644 --- a/chrome/browser/apps/guest_view/web_view_browsertest.cc +++ b/chrome/browser/apps/guest_view/web_view_browsertest.cc
@@ -6385,14 +6385,10 @@ WebViewPPAPITest::DescribeParams); IN_PROC_BROWSER_TEST_P(WebViewPPAPITest, Shim_TestPlugin) { - SKIP_FOR_MPARCH(); // TODO(crbug.com/40202416): Enable test for MPArch. - TestHelper("testPlugin", "web_view/shim", NO_TEST_SERVER); } IN_PROC_BROWSER_TEST_P(WebViewPPAPITest, Shim_TestPluginLoadPermission) { - SKIP_FOR_MPARCH(); // TODO(crbug.com/40202416): Enable test for MPArch. - TestHelper("testPluginLoadPermission", "web_view/shim", NO_TEST_SERVER); } #endif // BUILDFLAG(ENABLE_PPAPI)
diff --git a/chrome/browser/apps/link_capturing/link_capturing_navigation_throttle.cc b/chrome/browser/apps/link_capturing/link_capturing_navigation_throttle.cc index 593848b..0e93829f 100644 --- a/chrome/browser/apps/link_capturing/link_capturing_navigation_throttle.cc +++ b/chrome/browser/apps/link_capturing/link_capturing_navigation_throttle.cc
@@ -17,7 +17,7 @@ #include "chrome/browser/profiles/keep_alive/scoped_profile_keep_alive.h" // nogncheck https://crbug.com/1474116 #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser_finder.h" // nogncheck https://crbug.com/1474984 -#include "chrome/browser/ui/web_applications/navigation_capturing_navigation_handle_user_data.h" // nogncheck https://crbug.com/377760841 +#include "chrome/browser/ui/web_applications/navigation_capturing_process.h" // nogncheck https://crbug.com/377760841 #include "chrome/browser/web_applications/web_app_ui_manager.h" #include "chrome/browser/web_applications/web_app_utils.h" #include "components/keep_alive_registry/keep_alive_types.h" @@ -272,8 +272,7 @@ // Exit early if the reimplementation data is attached, to avoid running two // different throttles simultaneously. Note: this cannot be checked in // `MaybeCreate()` since the data might get attached after it's executed. - if (web_app::NavigationCapturingNavigationHandleUserData:: - GetForNavigationHandle(*handle)) { + if (web_app::NavigationCapturingProcess::GetForNavigationHandle(*handle)) { return content::NavigationThrottle::PROCEED; }
diff --git a/chrome/browser/ash/bruschetta/bruschetta_download.cc b/chrome/browser/ash/bruschetta/bruschetta_download.cc index 3f3abc4..6d02ef4f 100644 --- a/chrome/browser/ash/bruschetta/bruschetta_download.cc +++ b/chrome/browser/ash/bruschetta/bruschetta_download.cc
@@ -133,6 +133,7 @@ auto path = scoped_temp_dir_->GetPath().Append("download"); auto req = std::make_unique<network::ResourceRequest>(); req->url = url_; + req->site_for_cookies = net::SiteForCookies::FromUrl(url_); loader_ = network::SimpleURLLoader::Create(std::move(req), kBruschettaTrafficAnnotation); network_context_ = std::make_unique<BruschettaNetworkContext>(profile);
diff --git a/chrome/browser/ash/input_method/BUILD.gn b/chrome/browser/ash/input_method/BUILD.gn index 08e85a4..3ef94ec 100644 --- a/chrome/browser/ash/input_method/BUILD.gn +++ b/chrome/browser/ash/input_method/BUILD.gn
@@ -209,13 +209,13 @@ "//chrome/common:channel_info", "//chrome/common:chrome_features", "//chrome/common:constants", + "//chromeos/ash/components/editor_menu/public/cpp", "//chromeos/ash/components/file_manager:constants", "//chromeos/ash/components/language_preferences", "//chromeos/ash/components/settings", "//chromeos/ash/components/specialized_features", "//chromeos/ash/services/federated/public/mojom", "//chromeos/ash/services/ime:constants", - "//chromeos/components/editor_menu/public/cpp", "//chromeos/components/kiosk", "//chromeos/components/magic_boost/public/cpp", "//chromeos/constants",
diff --git a/chrome/browser/ash/input_method/editor_mediator.cc b/chrome/browser/ash/input_method/editor_mediator.cc index d76d2c3..627acfb9 100644 --- a/chrome/browser/ash/input_method/editor_mediator.cc +++ b/chrome/browser/ash/input_method/editor_mediator.cc
@@ -26,7 +26,7 @@ #include "chrome/browser/ash/magic_boost/magic_boost_controller_ash.h" #include "chrome/browser/ash/profiles/profile_helper.h" #include "chrome/browser/ui/webui/ash/mako/mako_bubble_coordinator.h" -#include "chromeos/components/editor_menu/public/cpp/editor_helpers.h" +#include "chromeos/ash/components/editor_menu/public/cpp/editor_helpers.h" #include "chromeos/components/magic_boost/public/cpp/magic_boost_state.h" #include "ui/base/ime/ash/ime_bridge.h" #include "ui/display/screen.h"
diff --git a/chrome/browser/browsing_data/android/java/src/org/chromium/chrome/browser/browsing_data/TimePeriodUtils.java b/chrome/browser/browsing_data/android/java/src/org/chromium/chrome/browser/browsing_data/TimePeriodUtils.java index 2acf91a..e03a2fc 100644 --- a/chrome/browser/browsing_data/android/java/src/org/chromium/chrome/browser/browsing_data/TimePeriodUtils.java +++ b/chrome/browser/browsing_data/android/java/src/org/chromium/chrome/browser/browsing_data/TimePeriodUtils.java
@@ -6,12 +6,13 @@ import android.content.Context; -import androidx.annotation.NonNull; +import org.chromium.build.annotations.NullMarked; import java.util.ArrayList; import java.util.List; /** A utility class to provide functionalities around clear browsing data {@link TimePeriod}. */ +@NullMarked public class TimePeriodUtils { /** An option to be shown in the time period spiner. */ public static class TimePeriodSpinnerOption { @@ -45,7 +46,7 @@ * Returns the Array of time periods. Options are displayed in the same order as they appear * in the array. */ - public static TimePeriodSpinnerOption[] getTimePeriodSpinnerOptions(@NonNull Context context) { + public static TimePeriodSpinnerOption[] getTimePeriodSpinnerOptions(Context context) { List<TimePeriodSpinnerOption> options = new ArrayList<>(); options.add( new TimePeriodSpinnerOption( @@ -71,7 +72,7 @@ } /** Returns the string associated with the time period. */ - public static String getTimePeriodString(@NonNull Context context, @TimePeriod int timePeriod) { + public static String getTimePeriodString(Context context, @TimePeriod int timePeriod) { switch (timePeriod) { case TimePeriod.LAST_15_MINUTES: return context.getString(R.string.clear_browsing_data_tab_period_15_minutes);
diff --git a/chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/DataSharingTabManager.java b/chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/DataSharingTabManager.java index ba630a6..1a29093 100644 --- a/chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/DataSharingTabManager.java +++ b/chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/DataSharingTabManager.java
@@ -408,6 +408,11 @@ DataSharingMetrics.JoinActionStateAndroid.ADD_MEMBER_SUCCESS); assert groupData.getGroupId().equals(groupToken.collaborationId); } + + @Override + public void onSessionFinished() { + // TODO(haileywang) : Implement this. + } }; String tabGroupName = preview.title; if (TextUtils.isEmpty(tabGroupName)) { @@ -684,6 +689,11 @@ DataSharingMetrics.recordShareActionFlowState( DataSharingMetrics.ShareActionStateAndroid.BOTTOM_SHEET_DISMISSED); } + + @Override + public void onSessionFinished() { + // TODO(haileywang) : Implement this. + } }; String sessionId = @@ -830,6 +840,11 @@ tabGroupSyncService.onTabGroupUnShareComplete( existingGroup.localId, success); } + + @Override + public void onSessionFinished() { + // TODO(haileywang) : Implement this. + } }; DataSharingManageUiConfig manageConfig = new DataSharingManageUiConfig.Builder()
diff --git a/chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/InstantMessageDelegateImpl.java b/chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/InstantMessageDelegateImpl.java index 3df9b43..a7b07b8c7 100644 --- a/chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/InstantMessageDelegateImpl.java +++ b/chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/InstantMessageDelegateImpl.java
@@ -409,6 +409,12 @@ .with(MessageBannerProperties.TITLE, title) .with(MessageBannerProperties.PRIMARY_BUTTON_TEXT, buttonText) .with(MessageBannerProperties.ICON, icon) + .with( + MessageBannerProperties.ICON_ROUNDED_CORNER_RADIUS_PX, + icon.getIntrinsicWidth()) + .with( + MessageBannerProperties.ICON_TINT_COLOR, + MessageBannerProperties.TINT_NONE) .with(MessageBannerProperties.ON_PRIMARY_ACTION, onPrimary) .with(MessageBannerProperties.ON_FULLY_VISIBLE, onVisibleChange) .build();
diff --git a/chrome/browser/enterprise/platform_auth/extensible_enterprise_sso_provider_mac.mm b/chrome/browser/enterprise/platform_auth/extensible_enterprise_sso_provider_mac.mm index 4f8f626..a9ddb38 100644 --- a/chrome/browser/enterprise/platform_auth/extensible_enterprise_sso_provider_mac.mm +++ b/chrome/browser/enterprise/platform_auth/extensible_enterprise_sso_provider_mac.mm
@@ -25,6 +25,79 @@ #import "net/url_request/url_request.h" #import "url/gurl.h" +namespace { + +// Adds the header from `headers_response` with the `headers_key` into +// `auth_headers`. `headers_key` is either "prt_headers" or "device_headers". +// `headers_response` has the following format example. +// { +// "prt_headers": [ +// { +// "header": { +// "x-ms-RefreshTokenCredential": "prt_header_value" +// }, +// "home_account_id": "123-123-1234" +// }, +// { +// "header": { +// "x-ms-RefreshTokenCredential1": "prt_header_value_1" +// }, +// "home_account_id": "abc-abc-abcd" +// }, +// { +// "header": { +// "x-ms-RefreshTokenCredential2": "prt_header_value_2" +// }, +// "home_account_id": "123-abc-12ab" +// } +// ], +// "device_headers": [ +// { +// "header": { +// "x-ms-DeviceCredential": "device_header_value" +// }, +// "tenant_id": "qwe-qwe-qwer" +// } +// ] +// } +void AddMSAuthHeadersFromResponse(net::HttpRequestHeaders& auth_headers, + NSDictionary* headers_response, + NSString* headers_key) { + static NSString* const kHeader(@"header"); + NSArray* headers = headers_response[headers_key]; + auto headers_key_str = base::SysNSStringToUTF8(headers_key); + + for (NSDictionary* header in headers) { + NSDictionary* header_definition = [header valueForKey:kHeader]; + for (NSString* key in header_definition) { + auto header_name = base::SysNSStringToUTF8(key); + + if (!net::HttpUtil::IsValidHeaderName(header_name)) { + VLOG_POLICY(2, EXTENSIBLE_SSO) + << "[ExtensibleEnterpriseSSO] Invalid header name " + << headers_key_str << " : " << header_name; + continue; + } + + auto header_value = base::SysNSStringToUTF8( + net::FixNSStringIncorrectlyDecodedAsLatin1(header[key])); + if (!net::HttpUtil::IsValidHeaderValue(header_value)) { + VLOG_POLICY(2, EXTENSIBLE_SSO) + << "[ExtensibleEnterpriseSSO] Invalid header value " + << headers_key_str << " : " << header_value; + continue; + } + + VLOG_POLICY(2, EXTENSIBLE_SSO) + << "[ExtensibleEnterpriseSSO] Header added : " << "{ " << header_name + << ": " << header_value << "}"; + auth_headers.SetHeader(header_name, header_value); + } + } +} + +} // namespace + // Interface that provides a presentation context to the platform // and a delegate for the authorization controller. @interface SSOServiceAuthControllerDelegate @@ -59,9 +132,10 @@ (enterprise_auth::PlatformAuthProviderManager::GetDataCallback) callback { _callback = std::move(callback); + NSURL* nativeUrl = net::NSURLWithGURL(url); ASAuthorizationSingleSignOnProvider* auth_provider = [ASAuthorizationSingleSignOnProvider - authorizationProviderWithIdentityProviderURL:net::NSURLWithGURL(url)]; + authorizationProviderWithIdentityProviderURL:nativeUrl]; if (!auth_provider.canPerformAuthorization) { std::move(_callback).Run(net::HttpRequestHeaders()); @@ -72,6 +146,21 @@ // Create a request for `url`. ASAuthorizationSingleSignOnRequest* request = [auth_provider createRequest]; + + request.requestedOperation = @"get_sso_cookies"; + if (@available(macOS 12, *)) { + request.userInterfaceEnabled = NO; + } + + request.authorizationOptions = @[ + [NSURLQueryItem queryItemWithName:@"sso_url" + value:nativeUrl.absoluteString], + // Response headers to fetch. + // “0” -> All headers, "1" -> PRT headers only, "2" -> Device headers only. + [NSURLQueryItem queryItemWithName:@"types_of_header" value:@"0"], + [NSURLQueryItem queryItemWithName:@"msg_protocol_ver" value:@"4"], + ]; + _controller = [[ASAuthorizationController alloc] initWithAuthorizationRequests:[NSArray arrayWithObject:request]]; _controller.delegate = self; @@ -86,56 +175,30 @@ // HttpRequestHeaders from `authorization`. - (void)authorizationController:(ASAuthorizationController*)controller didCompleteWithAuthorization:(ASAuthorization*)authorization { + static NSString* const kPrtHeaders(@"prt_headers"); + static NSString* const kDeviceHeaders(@"device_headers"); + VLOG_POLICY(2, EXTENSIBLE_SSO) << "[ExtensibleEnterpriseSSO] Fetching headers completed."; ASAuthorizationSingleSignOnCredential* credential = authorization.credential; NSDictionary* headers = credential.authenticatedResponse.allHeaderFields; - static constexpr std::string_view kHeaderPrefix("x-ms-"); - static constexpr std::string_view kSetCookieHeaderKey("Set-Cookie"); - net::HttpRequestHeaders auth_headers; - std::string unused_headers; - for (NSString* key in headers) { - const std::string header_name = base::SysNSStringToUTF8(key); - if (!net::HttpUtil::IsValidHeaderName(header_name)) { - VLOG_POLICY(2, EXTENSIBLE_SSO) - << "[ExtensibleEnterpriseSSO] Invalid header name " << header_name; - continue; - } - const std::string header_value = base::SysNSStringToUTF8( - net::FixNSStringIncorrectlyDecodedAsLatin1(headers[key])); - if (!net::HttpUtil::IsValidHeaderValue(header_value)) { - VLOG_POLICY(2, EXTENSIBLE_SSO) - << "[ExtensibleEnterpriseSSO] Invalid header value " << header_value; - continue; - } - - // If the header name begins with 'x-ms-', attach the it as a new header. - if (base::StartsWith(header_name, kHeaderPrefix, - base::CompareCase::INSENSITIVE_ASCII)) { - auth_headers.SetHeader(header_name, header_value); - continue; - } - - // If the header is 'Set-Cookie', add it to the list of cookies. - if (header_name == kSetCookieHeaderKey) { - net::cookie_util::ParsedRequestCookies parsed_cookies; - net::cookie_util::ParseRequestCookieLine(header_value, &parsed_cookies); - auth_headers.SetHeader( - net::HttpRequestHeaders::kCookie, - net::cookie_util::SerializeRequestCookieLine(parsed_cookies)); - continue; - } - - // Keep track of unused headers - unused_headers = base::StrCat( - {unused_headers, "{ ", header_name, " : ", header_value, " }, "}); + // This is for logging purposes only. + { + NSString* headers_as_json_str = [[NSString alloc] + initWithData:[NSJSONSerialization dataWithJSONObject:headers + options:0 + error:nil] + encoding:NSUTF8StringEncoding]; + VLOG_POLICY(2, EXTENSIBLE_SSO) + << "[ExtensibleEnterpriseSSO] Headers: " + << base::SysNSStringToUTF8(headers_as_json_str); } - VLOG_POLICY(2, EXTENSIBLE_SSO) - << "[ExtensibleEnterpriseSSO - Unused Headers] : " << unused_headers; - VLOG_POLICY(2, EXTENSIBLE_SSO) - << "[ExtensibleEnterpriseSSO - Headers] " << auth_headers.ToString(); + net::HttpRequestHeaders auth_headers; + AddMSAuthHeadersFromResponse(auth_headers, headers, kPrtHeaders); + AddMSAuthHeadersFromResponse(auth_headers, headers, kDeviceHeaders); + std::move(_callback).Run(std::move(auth_headers)); }
diff --git a/chrome/browser/extensions/api/braille_display_private/BUILD.gn b/chrome/browser/extensions/api/braille_display_private/BUILD.gn index c426555..476b036 100644 --- a/chrome/browser/extensions/api/braille_display_private/BUILD.gn +++ b/chrome/browser/extensions/api/braille_display_private/BUILD.gn
@@ -52,7 +52,6 @@ public_deps += [ "//third_party/libbrlapi" ] deps += [ - "//components/nacl/common:minimal_content_dummy", "//content/public/browser", "//content/public/common", ]
diff --git a/chrome/browser/extensions/api/document_scan/BUILD.gn b/chrome/browser/extensions/api/document_scan/BUILD.gn index 31f1195..14ff05a 100644 --- a/chrome/browser/extensions/api/document_scan/BUILD.gn +++ b/chrome/browser/extensions/api/document_scan/BUILD.gn
@@ -20,6 +20,8 @@ "document_scan_type_converters.h", "scanner_discovery_runner.cc", "scanner_discovery_runner.h", + "simple_scan_runner.cc", + "simple_scan_runner.h", "start_scan_runner.cc", "start_scan_runner.h", ]
diff --git a/chrome/browser/extensions/api/document_scan/document_scan_api.cc b/chrome/browser/extensions/api/document_scan/document_scan_api.cc index 2bb08f7..8233000 100644 --- a/chrome/browser/extensions/api/document_scan/document_scan_api.cc +++ b/chrome/browser/extensions/api/document_scan/document_scan_api.cc
@@ -45,7 +45,7 @@ DocumentScanAPIHandler::Get(browser_context()) ->SimpleScan( - mime_types, + extension_, mime_types, base::BindOnce(&DocumentScanScanFunction::OnScanCompleted, this)); return RespondLater();
diff --git a/chrome/browser/extensions/api/document_scan/document_scan_api_handler.cc b/chrome/browser/extensions/api/document_scan/document_scan_api_handler.cc index 301ed5cd..7eeffac9 100644 --- a/chrome/browser/extensions/api/document_scan/document_scan_api_handler.cc +++ b/chrome/browser/extensions/api/document_scan/document_scan_api_handler.cc
@@ -8,7 +8,6 @@ #include <limits> #include <utility> -#include "base/base64.h" #include "base/check.h" #include "base/check_is_test.h" #include "base/containers/contains.h" @@ -21,6 +20,7 @@ #include "chrome/browser/ash/crosapi/document_scan_ash.h" #include "chrome/browser/extensions/api/document_scan/document_scan_type_converters.h" #include "chrome/browser/extensions/api/document_scan/scanner_discovery_runner.h" +#include "chrome/browser/extensions/api/document_scan/simple_scan_runner.h" #include "chrome/browser/extensions/api/document_scan/start_scan_runner.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/extensions/api/document_scan.h" @@ -35,25 +35,6 @@ namespace { -// Error messages that can be included in a response when scanning fails. -constexpr char kNoScannersAvailableError[] = "No scanners available"; -constexpr char kUnsupportedMimeTypesError[] = "Unsupported MIME types"; -constexpr char kScanImageError[] = "Failed to scan image"; -constexpr char kVirtualPrinterUnavailableError[] = - "Virtual USB printer unavailable"; - -// The name of the virtual USB printer used for testing. -constexpr char kVirtualUSBPrinter[] = "DavieV Virtual USB Printer (USB)"; - -// The testing MIME type. -constexpr char kTestingMimeType[] = "testing"; - -// The PNG MIME type. -constexpr char kScannerImageMimeTypePng[] = "image/png"; - -// The PNG image data URL prefix of a scanned image. -constexpr char kPngImageDataUrlPrefix[] = "data:image/png;base64,"; - crosapi::mojom::DocumentScan* GetDocumentScanInterface() { // CrosapiManager is not always initialized in tests. if (!crosapi::CrosapiManager::IsInitialized()) { @@ -142,76 +123,25 @@ } void DocumentScanAPIHandler::SimpleScan( + scoped_refptr<const Extension> extension, const std::vector<std::string>& mime_types, SimpleScanCallback callback) { - bool should_use_virtual_usb_printer = false; - if (base::Contains(mime_types, kTestingMimeType)) { - should_use_virtual_usb_printer = true; - } else if (!base::Contains(mime_types, kScannerImageMimeTypePng)) { - std::move(callback).Run(std::nullopt, kUnsupportedMimeTypesError); - return; - } - - document_scan_->GetScannerNames( - base::BindOnce(&DocumentScanAPIHandler::OnSimpleScanNamesReceived, - weak_ptr_factory_.GetWeakPtr(), - should_use_virtual_usb_printer, std::move(callback))); -} - -void DocumentScanAPIHandler::OnSimpleScanNamesReceived( - bool force_virtual_usb_printer, - SimpleScanCallback callback, - const std::vector<std::string>& scanner_names) { - if (scanner_names.empty()) { - std::move(callback).Run(std::nullopt, kNoScannersAvailableError); - return; - } - - // TODO(pstew): Call a delegate method here to select a scanner and options. - // The first scanner supporting one of the requested MIME types used to be - // selected. The testing MIME type dictates that the virtual USB printer - // should be used if available. Otherwise, since all of the scanners always - // support PNG, select the first scanner in the list. - - std::string scanner_name; - if (force_virtual_usb_printer) { - if (!base::Contains(scanner_names, kVirtualUSBPrinter)) { - std::move(callback).Run(std::nullopt, kVirtualPrinterUnavailableError); - return; - } - - scanner_name = kVirtualUSBPrinter; - } else { - scanner_name = scanner_names[0]; - } - - document_scan_->ScanFirstPage( - scanner_name, + auto runner = + std::make_unique<SimpleScanRunner>(std::move(extension), document_scan_); + SimpleScanRunner* raw_runner = runner.get(); + raw_runner->Start( + std::move(mime_types), base::BindOnce(&DocumentScanAPIHandler::OnSimpleScanCompleted, - weak_ptr_factory_.GetWeakPtr(), std::move(callback))); + weak_ptr_factory_.GetWeakPtr(), std::move(runner), + std::move(callback))); } void DocumentScanAPIHandler::OnSimpleScanCompleted( + std::unique_ptr<SimpleScanRunner> runner, SimpleScanCallback callback, - crosapi::mojom::ScanFailureMode failure_mode, - const std::optional<std::string>& scan_data) { - // TODO(pstew): Enlist a delegate to display received scan in the UI and - // confirm that this scan should be sent to the caller. If this is a - // multi-page scan, provide a means for adding additional scanned images up to - // the requested limit. - if (!scan_data.has_value() || - failure_mode != crosapi::mojom::ScanFailureMode::kNoFailure) { - std::move(callback).Run(std::nullopt, kScanImageError); - return; - } - - std::string image_base64 = base::Base64Encode(scan_data.value()); - api::document_scan::ScanResults scan_results; - scan_results.data_urls.push_back(kPngImageDataUrlPrefix + - std::move(image_base64)); - scan_results.mime_type = kScannerImageMimeTypePng; - - std::move(callback).Run(std::move(scan_results), std::nullopt); + std::optional<api::document_scan::ScanResults> scan_results, + std::optional<std::string> error) { + std::move(callback).Run(std::move(scan_results), std::move(error)); } void DocumentScanAPIHandler::GetScannerList(
diff --git a/chrome/browser/extensions/api/document_scan/document_scan_api_handler.h b/chrome/browser/extensions/api/document_scan/document_scan_api_handler.h index 80e57b2e..331b81e 100644 --- a/chrome/browser/extensions/api/document_scan/document_scan_api_handler.h +++ b/chrome/browser/extensions/api/document_scan/document_scan_api_handler.h
@@ -38,6 +38,7 @@ class Extension; class ScannerDiscoveryRunner; +class SimpleScanRunner; class StartScanRunner; // Handles chrome.documentScan API function calls. @@ -94,7 +95,8 @@ // Scans one page from the first available scanner on the system and passes // the result to `callback`. `mime_types` is a list of MIME types the caller // is willing to receive back as the image format. - void SimpleScan(const std::vector<std::string>& mime_types, + void SimpleScan(scoped_refptr<const Extension> extension, + const std::vector<std::string>& mime_types, SimpleScanCallback callback); // If the user approves, gets a list of available scanners that match @@ -232,12 +234,11 @@ // Cleanup all handles and state for the given extension. void ExtensionCleanup(const ExtensionId& id); - void OnSimpleScanNamesReceived(bool force_virtual_usb_printer, - SimpleScanCallback callback, - const std::vector<std::string>& scanner_names); - void OnSimpleScanCompleted(SimpleScanCallback callback, - crosapi::mojom::ScanFailureMode failure_mode, - const std::optional<std::string>& scan_data); + void OnSimpleScanCompleted( + std::unique_ptr<SimpleScanRunner> runner, + SimpleScanCallback callback, + std::optional<api::document_scan::ScanResults> scan_results, + std::optional<std::string> error); void SendGetScannerListRequest(const api::document_scan::DeviceFilter& filter, GetScannerListCallback callback);
diff --git a/chrome/browser/extensions/api/document_scan/document_scan_api_handler_unittest.cc b/chrome/browser/extensions/api/document_scan/document_scan_api_handler_unittest.cc index c222e01..c420d05b 100644 --- a/chrome/browser/extensions/api/document_scan/document_scan_api_handler_unittest.cc +++ b/chrome/browser/extensions/api/document_scan/document_scan_api_handler_unittest.cc
@@ -227,7 +227,8 @@ TEST_F(DocumentScanAPIHandlerTest, SimpleScan_NoScannersAvailableError) { GetDocumentScan().SetGetScannerNamesResponse({}); SimpleScanFuture future; - document_scan_api_handler_->SimpleScan({"image/png"}, future.GetCallback()); + document_scan_api_handler_->SimpleScan(extension_, {"image/png"}, + future.GetCallback()); const auto& [scan_results, error] = future.Get(); EXPECT_FALSE(scan_results.has_value()); EXPECT_EQ("No scanners available", error); @@ -235,7 +236,7 @@ TEST_F(DocumentScanAPIHandlerTest, SimpleScan_MissingMimeTypesError) { SimpleScanFuture future; - document_scan_api_handler_->SimpleScan({}, future.GetCallback()); + document_scan_api_handler_->SimpleScan(extension_, {}, future.GetCallback()); const auto& [scan_results, error] = future.Get(); EXPECT_FALSE(scan_results.has_value()); EXPECT_EQ("Unsupported MIME types", error); @@ -243,7 +244,8 @@ TEST_F(DocumentScanAPIHandlerTest, SimpleScan_UnsupportedMimeTypesError) { SimpleScanFuture future; - document_scan_api_handler_->SimpleScan({"image/tiff"}, future.GetCallback()); + document_scan_api_handler_->SimpleScan(extension_, {"image/tiff"}, + future.GetCallback()); const auto& [scan_results, error] = future.Get(); EXPECT_FALSE(scan_results.has_value()); EXPECT_EQ("Unsupported MIME types", error); @@ -253,7 +255,8 @@ GetDocumentScan().SetGetScannerNamesResponse({kTestScannerName}); GetDocumentScan().SetScanResponse(std::nullopt); SimpleScanFuture future; - document_scan_api_handler_->SimpleScan({"image/png"}, future.GetCallback()); + document_scan_api_handler_->SimpleScan(extension_, {"image/png"}, + future.GetCallback()); const auto& [scan_results, error] = future.Get(); EXPECT_FALSE(scan_results.has_value()); EXPECT_EQ("Failed to scan image", error); @@ -264,7 +267,8 @@ const std::vector<std::string> scan_data = {kScanDataItem}; GetDocumentScan().SetScanResponse(scan_data); SimpleScanFuture future; - document_scan_api_handler_->SimpleScan({"image/png"}, future.GetCallback()); + document_scan_api_handler_->SimpleScan(extension_, {"image/png"}, + future.GetCallback()); const auto& [scan_results, error] = future.Get(); EXPECT_FALSE(error.has_value()); ASSERT_TRUE(scan_results.has_value()); @@ -279,7 +283,8 @@ TEST_F(DocumentScanAPIHandlerTest, SimpleScan_TestingMIMETypeError) { GetDocumentScan().SetGetScannerNamesResponse({kTestScannerName}); SimpleScanFuture future; - document_scan_api_handler_->SimpleScan({"testing"}, future.GetCallback()); + document_scan_api_handler_->SimpleScan(extension_, {"testing"}, + future.GetCallback()); const auto& [scan_results, error] = future.Get(); EXPECT_FALSE(scan_results.has_value()); EXPECT_EQ("Virtual USB printer unavailable", error); @@ -291,7 +296,7 @@ const std::vector<std::string> scan_data = {kScanDataItem}; GetDocumentScan().SetScanResponse(scan_data); SimpleScanFuture future; - document_scan_api_handler_->SimpleScan({"image/png", "testing"}, + document_scan_api_handler_->SimpleScan(extension_, {"image/png", "testing"}, future.GetCallback()); const auto& [scan_results, error] = future.Get(); EXPECT_FALSE(error.has_value());
diff --git a/chrome/browser/extensions/api/document_scan/simple_scan_runner.cc b/chrome/browser/extensions/api/document_scan/simple_scan_runner.cc new file mode 100644 index 0000000..01d9341 --- /dev/null +++ b/chrome/browser/extensions/api/document_scan/simple_scan_runner.cc
@@ -0,0 +1,129 @@ +// Copyright 2025 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/extensions/api/document_scan/simple_scan_runner.h" + +#include "base/base64.h" +#include "base/containers/contains.h" +#include "base/strings/utf_string_conversions.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/extensions/extensions_dialogs.h" +#include "chrome/common/pref_names.h" +#include "chromeos/crosapi/mojom/document_scan.mojom.h" +#include "components/prefs/pref_service.h" +#include "extensions/browser/image_loader.h" +#include "extensions/common/extension.h" +#include "ui/gfx/image/image.h" +#include "ui/gfx/image/image_skia.h" +#include "ui/views/native_window_tracker.h" + +namespace extensions { + +namespace { + +// Error messages that can be included in a response when scanning fails. +constexpr char kNoScannersAvailableError[] = "No scanners available"; +constexpr char kScanImageError[] = "Failed to scan image"; +constexpr char kUnsupportedMimeTypesError[] = "Unsupported MIME types"; +constexpr char kVirtualPrinterUnavailableError[] = + "Virtual USB printer unavailable"; + +// Special MIME type that triggers use of virtual-usb-printer for scanning. +constexpr char kTestingMimeType[] = "testing"; + +// The name of the virtual USB printer used for testing. +constexpr char kVirtualUSBPrinter[] = "DavieV Virtual USB Printer (USB)"; + +// The PNG MIME type. +constexpr char kScannerImageMimeTypePng[] = "image/png"; + +// The PNG image data URL prefix of a scanned image. +constexpr char kPngImageDataUrlPrefix[] = "data:image/png;base64,"; + +} // namespace + +SimpleScanRunner::SimpleScanRunner(scoped_refptr<const Extension> extension, + crosapi::mojom::DocumentScan* document_scan) + : extension_(std::move(extension)), document_scan_(document_scan) { + CHECK(extension_); +} + +SimpleScanRunner::~SimpleScanRunner() = default; + +void SimpleScanRunner::Start(std::vector<std::string> mime_types, + SimpleScanCallback callback) { + CHECK(!callback_) << "scan call already in progress"; + callback_ = std::move(callback); + mime_types_ = std::move(mime_types); + + bool should_use_virtual_usb_printer = false; + if (base::Contains(mime_types_, kTestingMimeType)) { + should_use_virtual_usb_printer = true; + } else if (!base::Contains(mime_types_, kScannerImageMimeTypePng)) { + std::move(callback_).Run(std::nullopt, kUnsupportedMimeTypesError); + return; + } + + document_scan_->GetScannerNames(base::BindOnce( + &SimpleScanRunner::OnSimpleScanNamesReceived, + weak_ptr_factory_.GetWeakPtr(), should_use_virtual_usb_printer)); +} + +const ExtensionId& SimpleScanRunner::extension_id() const { + return extension_->id(); +} + +void SimpleScanRunner::OnSimpleScanNamesReceived( + bool force_virtual_usb_printer, + const std::vector<std::string>& scanner_names) { + if (scanner_names.empty()) { + std::move(callback_).Run(std::nullopt, kNoScannersAvailableError); + return; + } + + // TODO(pstew): Call a delegate method here to select a scanner and options. + // The first scanner supporting one of the requested MIME types used to be + // selected. The testing MIME type dictates that the virtual USB printer + // should be used if available. Otherwise, since all of the scanners always + // support PNG, select the first scanner in the list. + + std::string scanner_name; + if (force_virtual_usb_printer) { + if (!base::Contains(scanner_names, kVirtualUSBPrinter)) { + std::move(callback_).Run(std::nullopt, kVirtualPrinterUnavailableError); + return; + } + + scanner_name = kVirtualUSBPrinter; + } else { + scanner_name = scanner_names[0]; + } + + document_scan_->ScanFirstPage( + scanner_name, base::BindOnce(&SimpleScanRunner::OnSimpleScanCompleted, + weak_ptr_factory_.GetWeakPtr())); +} + +void SimpleScanRunner::OnSimpleScanCompleted( + crosapi::mojom::ScanFailureMode failure_mode, + const std::optional<std::string>& scan_data) { + // TODO(pstew): Enlist a delegate to display received scan in the UI and + // confirm that this scan should be sent to the caller. If this is a + // multi-page scan, provide a means for adding additional scanned images up to + // the requested limit. + if (!scan_data.has_value() || + failure_mode != crosapi::mojom::ScanFailureMode::kNoFailure) { + std::move(callback_).Run(std::nullopt, kScanImageError); + return; + } + + std::string image_base64 = base::Base64Encode(scan_data.value()); + api::document_scan::ScanResults scan_results; + scan_results.data_urls.push_back(kPngImageDataUrlPrefix + + std::move(image_base64)); + scan_results.mime_type = kScannerImageMimeTypePng; + + std::move(callback_).Run(std::move(scan_results), std::nullopt); +} + +} // namespace extensions
diff --git a/chrome/browser/extensions/api/document_scan/simple_scan_runner.h b/chrome/browser/extensions/api/document_scan/simple_scan_runner.h new file mode 100644 index 0000000..c1ff124 --- /dev/null +++ b/chrome/browser/extensions/api/document_scan/simple_scan_runner.h
@@ -0,0 +1,61 @@ +// Copyright 2025 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_EXTENSIONS_API_DOCUMENT_SCAN_SIMPLE_SCAN_RUNNER_H_ +#define CHROME_BROWSER_EXTENSIONS_API_DOCUMENT_SCAN_SIMPLE_SCAN_RUNNER_H_ + +#include <optional> +#include <string> + +#include "base/functional/callback.h" +#include "base/memory/raw_ptr.h" +#include "base/memory/weak_ptr.h" +#include "chrome/common/extensions/api/document_scan.h" +#include "chromeos/crosapi/mojom/document_scan.mojom.h" +#include "extensions/common/extension_id.h" + +namespace extensions { + +class Extension; + +// Handles API requests from chrome.documentScan.scan including selecting a +// scanner and collecting the returned results. +class SimpleScanRunner { + public: + using SimpleScanCallback = base::OnceCallback<void( + std::optional<api::document_scan::ScanResults> scan_results, + std::optional<std::string> error)>; + using SimpleScanRunnerCallback = + base::OnceCallback<void(crosapi::mojom::ScanFailureMode, + const std::optional<std::string>&)>; + + SimpleScanRunner(scoped_refptr<const Extension> extension, + crosapi::mojom::DocumentScan* document_scan); + + ~SimpleScanRunner(); + + void Start(std::vector<std::string> mime_types, SimpleScanCallback callback); + + const ExtensionId& extension_id() const; + + private: + void OnSimpleScanNamesReceived(bool force_virtual_usb_printer, + const std::vector<std::string>& scanner_names); + void OnSimpleScanCompleted(crosapi::mojom::ScanFailureMode failure_mode, + const std::optional<std::string>& scan_data); + + scoped_refptr<const Extension> extension_; + + const raw_ptr<crosapi::mojom::DocumentScan> document_scan_; + + // Parameters for the in-progress call. + std::vector<std::string> mime_types_; + SimpleScanCallback callback_; + + base::WeakPtrFactory<SimpleScanRunner> weak_ptr_factory_{this}; +}; + +} // namespace extensions + +#endif // CHROME_BROWSER_EXTENSIONS_API_DOCUMENT_SCAN_SIMPLE_SCAN_RUNNER_H_
diff --git a/chrome/browser/extensions/content_security_policy_apitest.cc b/chrome/browser/extensions/content_security_policy_apitest.cc index 9a5ed9d..c2c1afd 100644 --- a/chrome/browser/extensions/content_security_policy_apitest.cc +++ b/chrome/browser/extensions/content_security_policy_apitest.cc
@@ -4,11 +4,8 @@ #include "base/strings/stringprintf.h" #include "chrome/browser/extensions/chrome_test_extension_loader.h" -#include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_switches.h" -#include "chrome/test/base/ui_test_utils.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" #include "extensions/common/extension.h" @@ -16,9 +13,21 @@ #include "extensions/test/test_extension_dir.h" #include "net/dns/mock_host_resolver.h" +#if BUILDFLAG(IS_ANDROID) +#include "chrome/browser/extensions/extension_platform_apitest.h" +#else +#include "chrome/browser/extensions/extension_apitest.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/test/base/ui_test_utils.h" +#endif + namespace extensions { +#if BUILDFLAG(IS_ANDROID) +using ExtensionCspApiTest = ExtensionPlatformApiTest; +#else using ExtensionCspApiTest = ExtensionApiTest; +#endif IN_PROC_BROWSER_TEST_F(ExtensionCspApiTest, ContentSecurityPolicy) { ASSERT_TRUE(StartEmbeddedTestServer()); @@ -120,7 +129,10 @@ ASSERT_TRUE(RunExtensionTest(test_dir.UnpackedPath(), {}, {})) << message_; } +#if !BUILDFLAG(IS_ANDROID) // Tests that MV3 disallows localhost in packed extensions. +// TODO(https://crbug.com/371434193): Enable on Android once packed extensions +// are supported. IN_PROC_BROWSER_TEST_F(ExtensionCspApiTest, ManifestV3DisallowsLocalhostForPackedExtensions) { ASSERT_TRUE(StartEmbeddedTestServer()); @@ -186,6 +198,7 @@ EXPECT_EQ(2u, console_observer.messages().size()); } +#endif // !BUILDFLAG(IS_ANDROID) // A simple subclass that also sets up page navigation with the host resolver. class ExtensionCspApiTestWithPageNavigation : public ExtensionCspApiTest {
diff --git a/chrome/browser/extensions/desktop_android/desktop_android_extension_system.cc b/chrome/browser/extensions/desktop_android/desktop_android_extension_system.cc index b2fbfff..7f023db 100644 --- a/chrome/browser/extensions/desktop_android/desktop_android_extension_system.cc +++ b/chrome/browser/extensions/desktop_android/desktop_android_extension_system.cc
@@ -101,6 +101,12 @@ scoped_refptr<const Extension> extension) override {} void PostDeactivateExtension( scoped_refptr<const Extension> extension) override {} + void PreUninstallExtension( + scoped_refptr<const Extension> extension) override {} + void PostUninstallExtension(scoped_refptr<const Extension> extension, + base::OnceClosure done_callback) override {} + void PostNotifyUninstallExtension( + scoped_refptr<const Extension> extension) override {} void ShowExtensionDisabledError(const Extension* extension, bool is_remote_install) override {}
diff --git a/chrome/browser/extensions/extension_platform_apitest.cc b/chrome/browser/extensions/extension_platform_apitest.cc index 2ec9866..e23a9a4 100644 --- a/chrome/browser/extensions/extension_platform_apitest.cc +++ b/chrome/browser/extensions/extension_platform_apitest.cc
@@ -19,6 +19,7 @@ #include "build/build_config.h" #include "chrome/browser/extensions/api_test_util.h" #include "content/public/common/content_switches.h" +#include "content/public/test/browser_test_utils.h" #include "extensions/browser/api/test/test_api.h" #include "extensions/common/constants.h" #include "extensions/common/extension.h" @@ -134,6 +135,11 @@ url_to_open = extension->GetResourceURL(run_options.extension_url); } + // If there is a page url to load, navigate it. + if (!url_to_open.is_empty()) { + OpenURL(url_to_open, run_options.open_in_incognito); + } + { base::test::ScopedRunLoopTimeout timeout( FROM_HERE, std::nullopt, @@ -210,4 +216,13 @@ net::EmbeddedTestServer::CERT_TEST_NAMES); } +void ExtensionPlatformApiTest::OpenURL(const GURL& url, + bool open_in_incognito) { + if (open_in_incognito) { + PlatformOpenURLOffTheRecord(profile(), url); + } else { + ASSERT_TRUE(content::NavigateToURL(GetActiveWebContents(), url)); + } +} + } // namespace extensions
diff --git a/chrome/browser/extensions/extension_platform_apitest.h b/chrome/browser/extensions/extension_platform_apitest.h index 4fb8a4f..4d47d1c 100644 --- a/chrome/browser/extensions/extension_platform_apitest.h +++ b/chrome/browser/extensions/extension_platform_apitest.h
@@ -134,6 +134,8 @@ } private: + void OpenURL(const GURL& url, bool open_in_incognito); + // Hold details of the test, set in C++, which can be accessed by // javascript using chrome.test.getConfig(). std::unique_ptr<base::Value::Dict> test_config_;
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc index 007ed46..2400563 100644 --- a/chrome/browser/extensions/extension_service.cc +++ b/chrome/browser/extensions/extension_service.cc
@@ -814,104 +814,8 @@ UninstallReason reason, std::u16string* error, base::OnceClosure done_callback) { - CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - - scoped_refptr<const Extension> extension = - registry_->GetInstalledExtension(transient_extension_id); - - // Callers should not send us nonexistent extensions. - CHECK(extension.get()); - - ManagementPolicy* by_policy = system_->management_policy(); - // Policy change which triggers an uninstall will always set - // |external_uninstall| to true so this is the only way to uninstall - // managed extensions. - // Shared modules being uninstalled will also set |external_uninstall| to true - // so that we can guarantee users don't uninstall a shared module. - // (crbug.com/273300) - // TODO(rdevlin.cronin): This is probably not right. We should do something - // else, like include an enum IS_INTERNAL_UNINSTALL or IS_USER_UNINSTALL so - // we don't do this. - bool external_uninstall = - (reason == UNINSTALL_REASON_INTERNAL_MANAGEMENT) || - (reason == UNINSTALL_REASON_COMPONENT_REMOVED) || - (reason == UNINSTALL_REASON_MIGRATED) || - (reason == UNINSTALL_REASON_REINSTALL) || - (reason == UNINSTALL_REASON_ORPHANED_EXTERNAL_EXTENSION) || - (reason == UNINSTALL_REASON_ORPHANED_SHARED_MODULE); - if (!external_uninstall && - (!by_policy->UserMayModifySettings(extension.get(), error) || - by_policy->MustRemainInstalled(extension.get(), error))) { - ExtensionRegistry::Get(profile_)->TriggerOnUninstallationDenied( - extension.get()); - return false; - } - - InstallVerifier::Get(GetBrowserContext())->Remove(extension->id()); - - UMA_HISTOGRAM_ENUMERATION("Extensions.UninstallType", extension->GetType(), - 100); - - // Unload before doing more cleanup to ensure that nothing is hanging on to - // any of these resources. - UnloadExtension(extension->id(), UnloadedExtensionReason::UNINSTALL); - - // `UnloadExtension` ignores extensions that are `BLOCKLISTED` or `BLOCKED` - if (registry_->blocklisted_extensions().Contains(extension->id())) - registry_->RemoveBlocklisted(extension->id()); - if (registry_->blocked_extensions().Contains(extension->id())) - registry_->RemoveBlocked(extension->id()); - - // Prepare barrier closure for UninstallExtensionOnFileThread() task (if - // applicable) and DataDeleter::StartDeleting(). - bool is_unpacked_location = - Manifest::IsUnpackedLocation(extension->location()); - base::RepeatingClosure subtask_done_callback = base::DoNothing(); - if (!done_callback.is_null()) { - int num_tasks = is_unpacked_location ? 1 : 2; - subtask_done_callback = - base::BarrierClosure(num_tasks, std::move(done_callback)); - } - - // Delete extensions in profile directory (from webstore, or from .crx), but - // do not delete unpacked in a folder outside the profile directory. - if (!SkipDeleteExtensionDir(*extension, profile_->GetPath())) { - // Extensions installed from webstore or .crx are versioned in subdirs so we - // delete the parent dir. Unpacked (installed from .zip rather than folder) - // are not versioned so we just delete the single installation directory. - base::FilePath extension_dir_to_delete = - is_unpacked_location ? extension->path() : extension->path().DirName(); - - base::FilePath extensions_install_dir = - is_unpacked_location ? unpacked_install_directory_ : install_directory_; - - // Tell the backend to start deleting the installed extension on the file - // thread. - if (!GetExtensionFileTaskRunner()->PostTaskAndReply( - FROM_HERE, - base::BindOnce(&ExtensionService::UninstallExtensionOnFileThread, - extension->id(), profile_->GetProfileUserName(), - std::move(extensions_install_dir), - std::move(extension_dir_to_delete), - profile_->GetPath()), - subtask_done_callback)) { - NOTREACHED(); - } - } - - DataDeleter::StartDeleting(profile_, extension.get(), subtask_done_callback); - - extension_registrar_.UntrackTerminatedExtension(extension->id()); - - // Notify interested parties that we've uninstalled this extension. - ExtensionRegistry::Get(profile_)->TriggerOnUninstalled(extension.get(), - reason); - - delayed_installs_.Remove(extension->id()); - extension_prefs_->OnExtensionUninstalled( - extension->id(), extension->location(), external_uninstall); - - return true; + return extension_registrar_.UninstallExtension( + transient_extension_id, reason, error, std::move(done_callback)); } // static @@ -1153,6 +1057,59 @@ UpdateActiveExtensionsInCrashReporter(); } +void ExtensionService::PreUninstallExtension( + scoped_refptr<const Extension> extension) { + InstallVerifier::Get(GetBrowserContext())->Remove(extension->id()); +} + +void ExtensionService::PostUninstallExtension( + scoped_refptr<const Extension> extension, + base::OnceClosure done_callback) { + // Prepare barrier closure for UninstallExtensionOnFileThread() task (if + // applicable) and DataDeleter::StartDeleting(). + bool is_unpacked_location = + Manifest::IsUnpackedLocation(extension->location()); + base::RepeatingClosure subtask_done_callback = base::DoNothing(); + if (!done_callback.is_null()) { + int num_tasks = is_unpacked_location ? 1 : 2; + subtask_done_callback = + base::BarrierClosure(num_tasks, std::move(done_callback)); + } + + // Delete extensions in profile directory (from webstore, or from .crx), but + // do not delete unpacked in a folder outside the profile directory. + if (!SkipDeleteExtensionDir(*extension, profile_->GetPath())) { + // Extensions installed from webstore or .crx are versioned in subdirs so we + // delete the parent dir. Unpacked (installed from .zip rather than folder) + // are not versioned so we just delete the single installation directory. + base::FilePath extension_dir_to_delete = + is_unpacked_location ? extension->path() : extension->path().DirName(); + + base::FilePath extensions_install_dir = + is_unpacked_location ? unpacked_install_directory_ : install_directory_; + + // Tell the backend to start deleting the installed extension on the file + // thread. + if (!GetExtensionFileTaskRunner()->PostTaskAndReply( + FROM_HERE, + base::BindOnce(&ExtensionService::UninstallExtensionOnFileThread, + extension->id(), profile_->GetProfileUserName(), + std::move(extensions_install_dir), + std::move(extension_dir_to_delete), + profile_->GetPath()), + subtask_done_callback)) { + NOTREACHED(); + } + } + + DataDeleter::StartDeleting(profile_, extension.get(), subtask_done_callback); +} + +void ExtensionService::PostNotifyUninstallExtension( + scoped_refptr<const Extension> extension) { + delayed_installs_.Remove(extension->id()); +} + content::BrowserContext* ExtensionService::GetBrowserContext() const { // Implemented in the .cc file to avoid adding a profile.h dependency to // extension_service.h.
diff --git a/chrome/browser/extensions/extension_service.h b/chrome/browser/extensions/extension_service.h index 1751cdad1..8348081 100644 --- a/chrome/browser/extensions/extension_service.h +++ b/chrome/browser/extensions/extension_service.h
@@ -541,6 +541,11 @@ void PostActivateExtension(scoped_refptr<const Extension> extension) override; void PostDeactivateExtension( scoped_refptr<const Extension> extension) override; + void PreUninstallExtension(scoped_refptr<const Extension> extension) override; + void PostUninstallExtension(scoped_refptr<const Extension> extension, + base::OnceClosure done_callback) override; + void PostNotifyUninstallExtension( + scoped_refptr<const Extension> extension) override; void LoadExtensionForReload( const ExtensionId& extension_id, const base::FilePath& path,
diff --git a/chrome/browser/feedback/android/BUILD.gn b/chrome/browser/feedback/android/BUILD.gn index 2c675b6..324c3169 100644 --- a/chrome/browser/feedback/android/BUILD.gn +++ b/chrome/browser/feedback/android/BUILD.gn
@@ -68,7 +68,6 @@ "java/src/org/chromium/chrome/browser/feedback/SystemInfoFeedbackSource.java", "java/src/org/chromium/chrome/browser/feedback/UrlFeedbackSource.java", "java/src/org/chromium/chrome/browser/feedback/VariationsFeedbackSource.java", - "java/src/org/chromium/chrome/browser/feedback/VariationsStateFeedbackSource.java", ] deps = [ ":feedback_collector_java",
diff --git a/chrome/browser/feedback/android/java/src/org/chromium/chrome/browser/feedback/VariationsStateFeedbackSource.java b/chrome/browser/feedback/android/java/src/org/chromium/chrome/browser/feedback/VariationsStateFeedbackSource.java deleted file mode 100644 index 7c64b7c..0000000 --- a/chrome/browser/feedback/android/java/src/org/chromium/chrome/browser/feedback/VariationsStateFeedbackSource.java +++ /dev/null
@@ -1,25 +0,0 @@ -// Copyright 2025 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.chrome.browser.feedback; - -import org.chromium.chrome.browser.profiles.Profile; -import org.chromium.components.variations.VariationsAssociatedData; - -import java.util.Map; - -/** Grabs feedback about the current command-line variations. */ -class VariationsStateFeedbackSource implements FeedbackSource { - private final boolean mIsOffTheRecord; - - VariationsStateFeedbackSource(Profile profile) { - mIsOffTheRecord = profile.isOffTheRecord(); - } - - @Override - public Map<String, String> getFeedback() { - if (mIsOffTheRecord) return null; - return VariationsAssociatedData.getVariationsStateFeedbackMap(); - } -}
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index f2bcd8af..7e5d15a 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -2847,8 +2847,12 @@ }, { "name": "enable-edid-based-display-ids", - "owners": [ "gildekel@chromium.org", "//ui/display/OWNERS", "chromeos-gfx-display@chromium.org" ], - "expiry_milestone": 130 + "owners": [ + "gildekel@chromium.org", + "//ui/display/OWNERS", + "chromeos-gfx-display@chromium.org" + ], + "expiry_milestone": 150 }, { "name": "enable-educational-tip-module", @@ -2977,7 +2981,7 @@ { "name": "enable-extensible-enterprise-sso", "owners": [ "ydago@chromium.org", "cbe-magic@google.com" ], - "expiry_milestone": 130 + "expiry_milestone": 135 }, { "name": "enable-extension-ai-data-collection", @@ -6828,6 +6832,14 @@ "expiry_milestone": 140 }, { + "name": "permissions-ai-v1", + "owners": [ + "elklm@chromium.org", + "//components/permissions/PERMISSIONS_OWNERS" + ], + "expiry_milestone": 144 + }, + { "name": "permissive-usb-passthrough", "owners": [ "drmasquatch@chromium.org" @@ -7480,7 +7492,7 @@ { "name": "render-arc-notifications-by-chrome", "owners": [ "shuminghao@google.com", "arc-framework@google.com" ], - "expiry_milestone": 134 + "expiry_milestone": 138 }, { "name": "render-document",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 3244e1f..3569566 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -3010,8 +3010,15 @@ const char kPermissionPredictionsV3Description[] = "Use the Permission Predictions Service V3 to surface permission requests " "using a quieter UI when the likelihood of the user granting the " - "permission is predicted to be low. Requires " - "and `Safe Browsing` to be enabled."; + "permission is predicted to be low. Requires and `Safe Browsing` to be " + "enabled."; + +const char kPermissionsAIv1Name[] = "PermissionsAI"; +const char kPermissionsAIv1Description[] = + "Use the Permission Predictions Service and Gemini Nano v2 to surface " + "permission requests using a quieter UI when the likelihood of the user " + "granting the permission is predicted to be low. Requires and `Safe " + "Browsing` to be enabled."; const char kPermissionQuietChipName[] = "Quiet Permission Chip Experiment"; const char kPermissionQuietChipDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index b3e868ac..df0cb740 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -1737,6 +1737,9 @@ extern const char kPermissionPredictionsV3Name[]; extern const char kPermissionPredictionsV3Description[]; +extern const char kPermissionsAIv1Name[]; +extern const char kPermissionsAIv1Description[]; + extern const char kPermissionQuietChipName[]; extern const char kPermissionQuietChipDescription[];
diff --git a/chrome/browser/glic/BUILD.gn b/chrome/browser/glic/BUILD.gn index 6519357..066e49e 100644 --- a/chrome/browser/glic/BUILD.gn +++ b/chrome/browser/glic/BUILD.gn
@@ -91,6 +91,10 @@ "//ui/webui", "//url", ] + + if (is_mac) { + deps += [ "//ui/accelerated_widget_mac" ] + } } mojom("mojo_bindings") {
diff --git a/chrome/browser/glic/glic_window_controller.cc b/chrome/browser/glic/glic_window_controller.cc index ec112a9f..3a143f73 100644 --- a/chrome/browser/glic/glic_window_controller.cc +++ b/chrome/browser/glic/glic_window_controller.cc
@@ -395,7 +395,7 @@ window_resize_animation_.reset(); window_resize_animation_ = std::make_unique<GlicWindowResizeAnimation>( glic_window_widget_.get(), GetGlicView(), size, - /*duration=*/base::Milliseconds(0), + /*duration=*/base::Milliseconds(150), base::BindOnce(&GlicWindowController::ResizeFinished, GetWeakPtr())); return true; } @@ -481,6 +481,9 @@ void GlicWindowController::HandleAttachmentToBrowserWindows( views::Widget* widget) { + // This should only ever be called after a move is completed. + CHECK(!in_move_loop_); + content::BrowserContext* glic_browser_context = GetGlicView()->web_view()->GetBrowserContext(); @@ -494,8 +497,6 @@ // Loops through all browsers in activation order with the latest accessed // browser first. for (Browser* browser : BrowserList::GetInstance()->OrderedByActivation()) { - views::Widget* window_widget = - browser->window()->AsBrowserView()->GetWidget(); if (!IsBrowserGlicCompatible(browser)) { continue; } @@ -515,14 +516,17 @@ // If there is no active drag (i.e. the previous drag has ended) // then determine whether the glic window should be attached or detached // from the browser window. - if (!in_move_loop_) { - if (corner_distance < kAttachmentDistanceThreshold) { - AttachToBrowser(browser); - } else if (glic_window_widget_->parent() == window_widget) { - // If farther than the attachment threshold from the current parent - // widget, reparent under an empty holder widget. - MaybeCreateHolderWindowAndReparent(); - } + if (corner_distance < kAttachmentDistanceThreshold) { + AttachToBrowser(browser); + return; + } + + if (glic_window_widget_->parent() == + browser->window()->AsBrowserView()->GetWidget()) { + // If farther than the attachment threshold from the current parent + // widget, reparent under an empty holder widget. + MaybeCreateHolderWindowAndReparent(); + return; } } }
diff --git a/chrome/browser/glic/glic_window_resize_animation.cc b/chrome/browser/glic/glic_window_resize_animation.cc index 6056334..1d6116c 100644 --- a/chrome/browser/glic/glic_window_resize_animation.cc +++ b/chrome/browser/glic/glic_window_resize_animation.cc
@@ -9,6 +9,11 @@ #include "ui/views/controls/webview/webview.h" #include "ui/views/widget/widget.h" +#if BUILDFLAG(IS_MAC) +#include "ui/accelerated_widget_mac/ca_transaction_observer.h" +#include "ui/display/screen.h" +#endif + namespace glic { GlicWindowResizeAnimation::GlicWindowResizeAnimation( @@ -17,7 +22,25 @@ gfx::Size new_size, base::TimeDelta duration, FinishedCallback finished_callback) - : finished_callback_(std::move(finished_callback)) { + : widget_(widget), + view_(view), + finished_callback_(std::move(finished_callback)) { +#if BUILDFLAG(IS_MAC) + // Intentionally disable this block until we can test. + volatile bool enabled = false; + if (enabled) { + int64_t display_id = + display::Screen::GetScreen() + ->GetDisplayNearestWindow(widget->GetNativeWindow()) + .id(); + display_link_ = ui::DisplayLinkMac::GetForDisplay(display_id); + vsync_callback_mac_ = display_link_->RegisterCallback(base::BindRepeating( + &GlicWindowResizeAnimation::Vsync, base::Unretained(this))); + CreateAnimationCurve(widget->GetSize(), new_size, duration); + return; + } +#endif + widget->SetSize(new_size); view->web_view()->SetSize(new_size); base::SequencedTaskRunner::GetCurrentDefault()->PostTask( @@ -32,4 +55,73 @@ std::move(finished_callback_).Run(); } +#if BUILDFLAG(IS_MAC) +void GlicWindowResizeAnimation::CreateAnimationCurve(gfx::Size start_size, + gfx::Size final_size, + base::TimeDelta duration) { + double refresh_rate = display_link_->GetRefreshRate(); + base::TimeDelta step_duration = base::Milliseconds(16); + if (refresh_rate) { + step_duration = base::Seconds(1) / refresh_rate; + } + + // We use a minimum of 1 step to avoid pathological edge cases. + int steps = duration / step_duration; + steps = std::max(steps, 1); + + int step_width = (final_size.width() - start_size.width()) / steps; + int step_height = (final_size.height() - start_size.height()) / steps; + auto now = base::TimeTicks::Now(); + for (int i = 1; i < steps + 1; ++i) { + int new_height = start_size.height() + i * step_height; + int new_width = start_size.width() + i * step_width; + + // To avoid rounding issues, the final step should use final_size. + if (i == steps) { + new_width = final_size.width(); + new_height = final_size.height(); + } + + AnimationStep step; + step.time = now + i * step_duration; + step.size = gfx::Size(new_width, new_height); + animation_curve_.push_back(step); + } +} + +void GlicWindowResizeAnimation::Vsync(ui::VSyncParamsMac) { + CHECK(!animation_curve_.empty()); + + // We may need to skip some steps if chrome was unable to render in time. + auto now = base::TimeTicks::Now(); + size_t step_to_use = 0; + for (size_t i = 0; i < animation_curve_.size(); ++i) { + if (animation_curve_[i].time < now) { + step_to_use = i; + } + } + + // Delete all steps up through and including the one used. + gfx::Size next_size = animation_curve_[step_to_use].size; + animation_curve_.erase(animation_curve_.begin(), + animation_curve_.begin() + step_to_use + 1); + + // This ensures that the web contents resize occurs in sync with the window + // resize. + ui::CATransactionCoordinator::Get().Synchronize(); + + widget_->SetSize(next_size); + view_->web_view()->SetSize(next_size); + + // If the animation curve is now empty, we're finished. + if (animation_curve_.empty()) { + vsync_callback_mac_.reset(); + display_link_.reset(); + base::SequencedTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, base::BindOnce(&GlicWindowResizeAnimation::Finished, + weak_ptr_factory_.GetWeakPtr())); + } +} +#endif + } // namespace glic
diff --git a/chrome/browser/glic/glic_window_resize_animation.h b/chrome/browser/glic/glic_window_resize_animation.h index 8a75fe9..9bde2a9 100644 --- a/chrome/browser/glic/glic_window_resize_animation.h +++ b/chrome/browser/glic/glic_window_resize_animation.h
@@ -8,8 +8,13 @@ #include "base/callback_list.h" #include "base/memory/weak_ptr.h" #include "base/time/time.h" +#include "build/build_config.h" #include "ui/gfx/geometry/rect_f.h" +#if BUILDFLAG(IS_MAC) +#include "ui/display/mac/display_link_mac.h" +#endif + namespace views { class Widget; } // namespace views @@ -40,6 +45,36 @@ // destroyed after posting the task but before the task is run. void Finished(); +#if BUILDFLAG(IS_MAC) + // The mac implementation for window resize uses vsync-aligned frame-by-frame + // steps. It synchronizes between window server and chrome via + // CATransactionCoordinator. + + // This is a linear animation curve. Each step of the animation is stored with + // an expected timestamp. Each frame of the animation removes at least one + // step from the animation curve, possibly multiple steps if chrome is unable + // to render in time. + void CreateAnimationCurve(gfx::Size start_size, + gfx::Size final_size, + base::TimeDelta duration); + + // Vsync callbacks. + void Vsync(ui::VSyncParamsMac); + + // Vectors of sizes and expected timestamps + struct AnimationStep { + gfx::Size size; + base::TimeTicks time; + }; + std::vector<AnimationStep> animation_curve_; + + scoped_refptr<ui::DisplayLinkMac> display_link_; + std::unique_ptr<ui::VSyncCallbackMac> vsync_callback_mac_; +#endif + + raw_ptr<views::Widget> widget_; + raw_ptr<GlicView> view_; + FinishedCallback finished_callback_; base::WeakPtrFactory<GlicWindowResizeAnimation> weak_ptr_factory_{this}; };
diff --git a/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.cc b/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.cc index a0b4a9d9..34437c8 100644 --- a/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.cc +++ b/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.cc
@@ -133,8 +133,8 @@ const std::string& input) { if (allow) { ChromePluginServiceFilter::GetInstance()->AuthorizeAllPlugins( - web_view_permission_helper()->web_view_guest()->web_contents(), true, - identifier); + web_view_permission_helper()->web_view_guest()->GetGuestMainFrame(), + true, identifier); } }
diff --git a/chrome/browser/image_descriptions/android/java/src/org/chromium/chrome/browser/image_descriptions/ImageDescriptionsDialog.java b/chrome/browser/image_descriptions/android/java/src/org/chromium/chrome/browser/image_descriptions/ImageDescriptionsDialog.java index de162149..9f85ba5 100644 --- a/chrome/browser/image_descriptions/android/java/src/org/chromium/chrome/browser/image_descriptions/ImageDescriptionsDialog.java +++ b/chrome/browser/image_descriptions/android/java/src/org/chromium/chrome/browser/image_descriptions/ImageDescriptionsDialog.java
@@ -155,8 +155,7 @@ } @Override - public void destroy() { - super.destroy(); + public void onDestroy() { // If no dismissal cause has been set, web contents were destroyed. if (mDismissalCause == DialogDismissalCause.UNKNOWN) { mDismissalCause = DialogDismissalCause.WEB_CONTENTS_DESTROYED;
diff --git a/chrome/browser/media/webrtc/conditional_focus_browsertest.cc b/chrome/browser/media/webrtc/conditional_focus_interactive_uitest.cc similarity index 90% rename from chrome/browser/media/webrtc/conditional_focus_browsertest.cc rename to chrome/browser/media/webrtc/conditional_focus_interactive_uitest.cc index 234fe4b..aa60f030 100644 --- a/chrome/browser/media/webrtc/conditional_focus_browsertest.cc +++ b/chrome/browser/media/webrtc/conditional_focus_interactive_uitest.cc
@@ -64,7 +64,7 @@ // Essentially depends on InProcessBrowserTest, but WebRtcTestBase provides // detection of JS errors. -class ConditionalFocusBrowserTest : public WebRtcTestBase { +class ConditionalFocusInteractiveUiTest : public WebRtcTestBase { public: void SetUpInProcessBrowserTestFixture() override { WebRtcTestBase::SetUpInProcessBrowserTestFixture(); @@ -200,7 +200,7 @@ #define MAYBE_CapturedTabFocusedIfNoExplicitCallToFocus \ CapturedTabFocusedIfNoExplicitCallToFocus #endif -IN_PROC_BROWSER_TEST_F(ConditionalFocusBrowserTest, +IN_PROC_BROWSER_TEST_F(ConditionalFocusInteractiveUiTest, MAYBE_CapturedTabFocusedIfNoExplicitCallToFocus) { SetUpTestTabs(); Capture(0, FocusEnumValue::kNoValue); @@ -215,7 +215,7 @@ #define MAYBE_CapturedTabFocusedIfExplicitlyCallingFocus \ CapturedTabFocusedIfExplicitlyCallingFocus #endif -IN_PROC_BROWSER_TEST_F(ConditionalFocusBrowserTest, +IN_PROC_BROWSER_TEST_F(ConditionalFocusInteractiveUiTest, MAYBE_CapturedTabFocusedIfExplicitlyCallingFocus) { SetUpTestTabs(); Capture(0, FocusEnumValue::kFocusCapturedSurface); @@ -224,14 +224,14 @@ // This class only uses the values of FocusEnumValue that lead to the capturing // application keeping focus. -class ConditionalFocusBrowserTestWithFocusCapturingApplication - : public ConditionalFocusBrowserTest, +class ConditionalFocusInteractiveUiTestWithFocusCapturingApplication + : public ConditionalFocusInteractiveUiTest, public testing::WithParamInterface<FocusEnumValue> { public: - ConditionalFocusBrowserTestWithFocusCapturingApplication() + ConditionalFocusInteractiveUiTestWithFocusCapturingApplication() : focus_behavior_(GetParam()) {} - ~ConditionalFocusBrowserTestWithFocusCapturingApplication() override = + ~ConditionalFocusInteractiveUiTestWithFocusCapturingApplication() override = default; protected: @@ -240,7 +240,7 @@ INSTANTIATE_TEST_SUITE_P( _, - ConditionalFocusBrowserTestWithFocusCapturingApplication, + ConditionalFocusInteractiveUiTestWithFocusCapturingApplication, testing::Values(FocusEnumValue::kFocusCapturingApplication, FocusEnumValue::kNoFocusChange)); @@ -252,8 +252,9 @@ #define MAYBE_CapturedTabNotFocusedIfExplicitlyCallingNoFocus \ CapturedTabNotFocusedIfExplicitlyCallingNoFocus #endif -IN_PROC_BROWSER_TEST_P(ConditionalFocusBrowserTestWithFocusCapturingApplication, - MAYBE_CapturedTabNotFocusedIfExplicitlyCallingNoFocus) { +IN_PROC_BROWSER_TEST_P( + ConditionalFocusInteractiveUiTestWithFocusCapturingApplication, + MAYBE_CapturedTabNotFocusedIfExplicitlyCallingNoFocus) { SetUpTestTabs(); Capture(0, focus_behavior_); // Whereas calls to Wait() in previous tests served to minimize flakiness, @@ -272,7 +273,7 @@ CapturedTabFocusedIfAppWaitsTooLongBeforeCallingFocus #endif IN_PROC_BROWSER_TEST_P( - ConditionalFocusBrowserTestWithFocusCapturingApplication, + ConditionalFocusInteractiveUiTestWithFocusCapturingApplication, MAYBE_CapturedTabFocusedIfAppWaitsTooLongBeforeCallingFocus) { SetUpTestTabs(); Capture(15000, focus_behavior_); @@ -283,7 +284,8 @@ // conditional focus window before focus occurs. Rather, that is just the // hard-limit that is employed in case the application attempts abuse by // blocking the main thread for too long. -IN_PROC_BROWSER_TEST_F(ConditionalFocusBrowserTest, FocusTriggeredByMicrotask) { +IN_PROC_BROWSER_TEST_F(ConditionalFocusInteractiveUiTest, + FocusTriggeredByMicrotask) { SetUpTestTabs(); Capture(0, FocusEnumValue::kNoValue); // Recall that the test fixture set the conditional focus window to 5s. @@ -292,7 +294,7 @@ EXPECT_EQ(ActiveTab(), Tab::kCapturedTab); } -IN_PROC_BROWSER_TEST_F(ConditionalFocusBrowserTest, +IN_PROC_BROWSER_TEST_F(ConditionalFocusInteractiveUiTest, UserFocusChangeSuppressesFocusDecision) { SetUpTestTabs(); @@ -313,7 +315,7 @@ browser()->tab_strip_model()->GetWebContentsAt(0)); } -IN_PROC_BROWSER_TEST_F(ConditionalFocusBrowserTest, +IN_PROC_BROWSER_TEST_F(ConditionalFocusInteractiveUiTest, ExceptionRaisedIfFocusCalledAfterMicrotaskExecutes) { // Setup. SetUpTestTabs(); @@ -325,7 +327,7 @@ "is closed."); } -IN_PROC_BROWSER_TEST_F(ConditionalFocusBrowserTest, FocusBeforeCapture) { +IN_PROC_BROWSER_TEST_F(ConditionalFocusInteractiveUiTest, FocusBeforeCapture) { // Setup. SetUpTestTabs(); CallSetFocusBehaviorBeforeCapture(FocusEnumValue::kFocusCapturedSurface); @@ -338,8 +340,9 @@ #else #define MAYBE_NoFocusBeforeCapture NoFocusBeforeCapture #endif -IN_PROC_BROWSER_TEST_P(ConditionalFocusBrowserTestWithFocusCapturingApplication, - MAYBE_NoFocusBeforeCapture) { +IN_PROC_BROWSER_TEST_P( + ConditionalFocusInteractiveUiTestWithFocusCapturingApplication, + MAYBE_NoFocusBeforeCapture) { // Setup. SetUpTestTabs(); CallSetFocusBehaviorBeforeCapture(focus_behavior_); @@ -358,8 +361,9 @@ #define MAYBE_NoFocusAfterCaptureOverrideFocusBeforeCapture \ NoFocusAfterCaptureOverrideFocusBeforeCapture #endif -IN_PROC_BROWSER_TEST_P(ConditionalFocusBrowserTestWithFocusCapturingApplication, - MAYBE_NoFocusAfterCaptureOverrideFocusBeforeCapture) { +IN_PROC_BROWSER_TEST_P( + ConditionalFocusInteractiveUiTestWithFocusCapturingApplication, + MAYBE_NoFocusAfterCaptureOverrideFocusBeforeCapture) { // Setup. SetUpTestTabs(); CallSetFocusBehaviorBeforeCapture(FocusEnumValue::kFocusCapturedSurface, @@ -379,8 +383,9 @@ #define MAYBE_FocusAfterCaptureOverrideNoFocusBeforeCapture \ FocusAfterCaptureOverrideNoFocusBeforeCapture #endif -IN_PROC_BROWSER_TEST_P(ConditionalFocusBrowserTestWithFocusCapturingApplication, - MAYBE_FocusAfterCaptureOverrideNoFocusBeforeCapture) { +IN_PROC_BROWSER_TEST_P( + ConditionalFocusInteractiveUiTestWithFocusCapturingApplication, + MAYBE_FocusAfterCaptureOverrideNoFocusBeforeCapture) { // Setup. SetUpTestTabs(); CallSetFocusBehaviorBeforeCapture(focus_behavior_,
diff --git a/chrome/browser/passage_embeddings/embedder_tab_observer.cc b/chrome/browser/passage_embeddings/embedder_tab_observer.cc index 674af96..426bc867 100644 --- a/chrome/browser/passage_embeddings/embedder_tab_observer.cc +++ b/chrome/browser/passage_embeddings/embedder_tab_observer.cc
@@ -44,7 +44,7 @@ void OnGotEmbeddings(base::ElapsedTimer embeddings_computation_timer, std::vector<mojom::PassageEmbeddingsResultPtr> results, ComputeEmbeddingsStatus status) { - if (status != ComputeEmbeddingsStatus::KSuccess) { + if (status != ComputeEmbeddingsStatus::kSuccess) { return; } VLOG(3) << "Embeddings computed in "
diff --git a/chrome/browser/plugins/chrome_plugin_service_filter.cc b/chrome/browser/plugins/chrome_plugin_service_filter.cc index bb2fee5e..0f5c82c 100644 --- a/chrome/browser/plugins/chrome_plugin_service_filter.cc +++ b/chrome/browser/plugins/chrome_plugin_service_filter.cc
@@ -91,14 +91,15 @@ } void ChromePluginServiceFilter::AuthorizeAllPlugins( - content::WebContents* web_contents, + content::RenderFrameHost* main_render_frame_host, bool load_blocked, const std::string& identifier) { DCHECK_CURRENTLY_ON(BrowserThread::UI); + CHECK(!main_render_frame_host->GetParent()); // Authorize all plugins is intended for the granting access to only // the currently active page, so we iterate on the main frame. - web_contents->GetPrimaryMainFrame()->ForEachRenderFrameHost( + main_render_frame_host->ForEachRenderFrameHost( [](content::RenderFrameHost* render_frame_host) { ChromePluginServiceFilter::GetInstance()->AuthorizePlugin( render_frame_host->GetProcess()->GetDeprecatedID(), @@ -106,7 +107,7 @@ }); if (load_blocked) { - web_contents->GetPrimaryMainFrame() + main_render_frame_host ->ForEachRenderFrameHost( [&identifier](content::RenderFrameHost* render_frame_host) { mojo::AssociatedRemote<chrome::mojom::ChromeRenderFrame>
diff --git a/chrome/browser/plugins/chrome_plugin_service_filter.h b/chrome/browser/plugins/chrome_plugin_service_filter.h index 763ee8ef..88b3864 100644 --- a/chrome/browser/plugins/chrome_plugin_service_filter.h +++ b/chrome/browser/plugins/chrome_plugin_service_filter.h
@@ -22,7 +22,7 @@ class Profile; namespace content { -class WebContents; +class RenderFrameHost; } // This class must be created (by calling the |GetInstance| method) on the UI @@ -41,11 +41,11 @@ void AuthorizePlugin(int render_process_id, const base::FilePath& plugin_path); - // Authorizes all plugins for a given WebContents. If |load_blocked| is true, - // then the renderer is told to load the plugin with given |identifier| (or - // pllugins if |identifier| is empty). - // This method can only be called on the UI thread. - void AuthorizeAllPlugins(content::WebContents* web_contents, + // Authorizes all plugins for a given RenderFrameHost and its children. If + // |load_blocked| is true, then the renderer is told to load the plugin with + // given |identifier| (or pllugins if |identifier| is empty). This method can + // only be called on the UI thread. + void AuthorizeAllPlugins(content::RenderFrameHost* main_render_frame_host, bool load_blocked, const std::string& identifier);
diff --git a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromeSharedPreferences.java b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromeSharedPreferences.java index 9309571..1ef5589 100644 --- a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromeSharedPreferences.java +++ b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromeSharedPreferences.java
@@ -10,7 +10,7 @@ import org.chromium.base.shared_preferences.PreferenceKeyRegistry; import org.chromium.base.shared_preferences.SharedPreferencesManager; import org.chromium.build.BuildConfig; -import org.chromium.build.annotations.AssumeNonNull; +import org.chromium.build.annotations.OptimizeAsNonNull; @JNINamespace("android::shared_preferences") public class ChromeSharedPreferences { @@ -26,7 +26,7 @@ /** * @return The //base SharedPreferencesManager singleton. */ - @AssumeNonNull + @OptimizeAsNonNull @CalledByNative public static SharedPreferencesManager getInstance() { return SharedPreferencesManager.getInstanceForRegistry(REGISTRY);
diff --git a/chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.cc b/chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.cc index d8ef039..a7fe25e 100644 --- a/chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.cc +++ b/chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.cc
@@ -17,13 +17,15 @@ // static NoStatePrefetchContents* ChromeNoStatePrefetchContentsDelegate::FromWebContents( content::WebContents* web_contents) { - if (!web_contents) + if (!web_contents) { return nullptr; + } NoStatePrefetchManager* no_state_prefetch_manager = NoStatePrefetchManagerFactory::GetForBrowserContext( web_contents->GetBrowserContext()); - if (!no_state_prefetch_manager) + if (!no_state_prefetch_manager) { return nullptr; + } return no_state_prefetch_manager->GetNoStatePrefetchContents(web_contents); }
diff --git a/chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_link_manager_factory.cc b/chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_link_manager_factory.cc index d3dc4f6..04524a3 100644 --- a/chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_link_manager_factory.cc +++ b/chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_link_manager_factory.cc
@@ -45,9 +45,11 @@ content::BrowserContext* context) const { NoStatePrefetchManager* no_state_prefetch_manager = NoStatePrefetchManagerFactory::GetForBrowserContext(context); - if (!no_state_prefetch_manager) + if (!no_state_prefetch_manager) { return nullptr; - return std::make_unique<NoStatePrefetchLinkManager>(no_state_prefetch_manager); + } + return std::make_unique<NoStatePrefetchLinkManager>( + no_state_prefetch_manager); } } // namespace prerender
diff --git a/chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_tab_helper.cc b/chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_tab_helper.cc index a26a66f..882ba556 100644 --- a/chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_tab_helper.cc +++ b/chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_tab_helper.cc
@@ -22,16 +22,19 @@ NoStatePrefetchTabHelper::~NoStatePrefetchTabHelper() = default; void NoStatePrefetchTabHelper::PrimaryPageChanged(content::Page& page) { - if (page.GetMainDocument().IsErrorDocument()) + if (page.GetMainDocument().IsErrorDocument()) { return; + } NoStatePrefetchManager* no_state_prefetch_manager = NoStatePrefetchManagerFactory::GetForBrowserContext( web_contents()->GetBrowserContext()); - if (!no_state_prefetch_manager) + if (!no_state_prefetch_manager) { return; - if (no_state_prefetch_manager->IsWebContentsPrefetching(web_contents())) + } + if (no_state_prefetch_manager->IsWebContentsPrefetching(web_contents())) { return; + } no_state_prefetch_manager->RecordNavigation( page.GetMainDocument().GetLastCommittedURL()); }
diff --git a/chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_test_utils.cc b/chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_test_utils.cc index 946eeac..697d0fdd 100644 --- a/chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_test_utils.cc +++ b/chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_test_utils.cc
@@ -115,8 +115,9 @@ skip_final_checks_(ignore_final_status) {} TestNoStatePrefetchContents::~TestNoStatePrefetchContents() { - if (skip_final_checks_) + if (skip_final_checks_) { return; + } EXPECT_EQ(expected_final_status_, final_status()) << " when testing URL " << prefetch_url().path() @@ -126,15 +127,17 @@ // A used NoStatePrefetchContents will only be destroyed when we swap out // WebContents, at the end of a navigation caused by a call to // NavigateToURLImpl(). - if (final_status() == FINAL_STATUS_USED) + if (final_status() == FINAL_STATUS_USED) { EXPECT_TRUE(new_main_frame_); + } } bool TestNoStatePrefetchContents::CheckURL(const GURL& url) { // Prevent FINAL_STATUS_UNSUPPORTED_SCHEME when navigating to about:crash in // the PrerenderRendererCrash test. - if (url.spec() != blink::kChromeUICrashURL) + if (url.spec() != blink::kChromeUICrashURL) { return NoStatePrefetchContents::CheckURL(url); + } return true; } @@ -220,31 +223,36 @@ stopped_(false) {} TestPrerender::~TestPrerender() { - if (contents_) + if (contents_) { contents_->RemoveObserver(this); + } } FinalStatus TestPrerender::GetFinalStatus() const { - if (contents_) + if (contents_) { return contents_->final_status(); + } return final_status_; } void TestPrerender::WaitForCreate() { - if (contents_) + if (contents_) { return; + } create_loop_.Run(); } void TestPrerender::WaitForStart() { - if (started_) + if (started_) { return; + } start_loop_.Run(); } void TestPrerender::WaitForStop() { - if (stopped_) + if (stopped_) { return; + } stop_loop_.Run(); } @@ -276,8 +284,9 @@ void TestPrerender::OnPrefetchStopLoading(NoStatePrefetchContents* contents) { number_of_loads_++; - if (load_waiter_ && number_of_loads_ >= expected_number_of_loads_) + if (load_waiter_ && number_of_loads_ >= expected_number_of_loads_) { load_waiter_->Quit(); + } } void TestPrerender::OnPrefetchStop(NoStatePrefetchContents* contents) { @@ -288,8 +297,9 @@ stop_loop_.Quit(); // If there is a WaitForLoads call and it has yet to see the expected number // of loads, stop the loop so the test fails instead of timing out. - if (load_waiter_) + if (load_waiter_) { load_waiter_->Quit(); + } } // static @@ -309,13 +319,15 @@ void FirstContentfulPaintManagerWaiter::OnFirstContentfulPaint() { saw_fcp_ = true; - if (waiter_) + if (waiter_) { waiter_->Quit(); + } } void FirstContentfulPaintManagerWaiter::Wait() { - if (saw_fcp_) + if (saw_fcp_) { return; + } waiter_ = std::make_unique<base::RunLoop>(); waiter_->Run(); waiter_.reset(); @@ -358,8 +370,9 @@ TestNoStatePrefetchContents* contents = new TestNoStatePrefetchContents( no_state_prefetch_manager, browser_context, url, referrer, initiator_origin, origin, expected.final_status, expected.ignore); - if (expected.handle) + if (expected.handle) { expected.handle->OnPrefetchContentsCreated(contents); + } return contents; } @@ -399,8 +412,9 @@ content::SessionStorageNamespace* PrerenderInProcessBrowserTest::GetSessionStorageNamespace() const { content::WebContents* web_contents = GetActiveWebContents(); - if (!web_contents) + if (!web_contents) { return nullptr; + } return web_contents->GetController().GetDefaultSessionStorageNamespace(); } @@ -446,8 +460,9 @@ } net::EmbeddedTestServer* PrerenderInProcessBrowserTest::src_server() { - if (https_src_server_) + if (https_src_server_) { return https_src_server_.get(); + } return embedded_test_server(); } @@ -476,8 +491,9 @@ embedded_test_server()->RegisterRequestMonitor(base::BindRepeating( &PrerenderInProcessBrowserTest::MonitorResourceRequest, base::Unretained(this))); - if (autostart_test_server_) + if (autostart_test_server_) { CHECK(embedded_test_server()->Start()); + } ExternalProtocolHandler::SetDelegateForTesting( external_protocol_handler_delegate_.get()); @@ -505,8 +521,9 @@ } void PrerenderInProcessBrowserTest::UseHttpsSrcServer() { - if (https_src_server_) + if (https_src_server_) { return; + } https_src_server_ = std::make_unique<net::EmbeddedTestServer>( net::EmbeddedTestServer::TYPE_HTTPS); https_src_server_->ServeFilesFromSourceDirectory("chrome/test/data"); @@ -602,8 +619,9 @@ uint32_t PrerenderInProcessBrowserTest::GetRequestCount(const GURL& url) { base::AutoLock auto_lock(lock_); auto i = requests_.find(url); - if (i == requests_.end()) + if (i == requests_.end()) { return 0; + } return i->second; }
diff --git a/chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_unit_test_utils.cc b/chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_unit_test_utils.cc index df2a5f59..07ff77e 100644 --- a/chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_unit_test_utils.cc +++ b/chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_unit_test_utils.cc
@@ -58,16 +58,18 @@ UnitTestNoStatePrefetchManager::~UnitTestNoStatePrefetchManager() = default; void UnitTestNoStatePrefetchManager::Shutdown() { - if (next_no_state_prefetch_contents()) + if (next_no_state_prefetch_contents()) { next_no_state_prefetch_contents_->Destroy(FINAL_STATUS_PROFILE_DESTROYED); + } NoStatePrefetchManager::Shutdown(); } void UnitTestNoStatePrefetchManager::MoveEntryToPendingDelete( NoStatePrefetchContents* entry, FinalStatus final_status) { - if (entry == next_no_state_prefetch_contents_.get()) + if (entry == next_no_state_prefetch_contents_.get()) { return; + } NoStatePrefetchManager::MoveEntryToPendingDelete(entry, final_status); } @@ -83,8 +85,9 @@ UnitTestNoStatePrefetchManager::FindAndUseEntry(const GURL& url) { NoStatePrefetchData* no_state_prefetch_data = FindNoStatePrefetchData(url, nullptr); - if (!no_state_prefetch_data) + if (!no_state_prefetch_data) { return nullptr; + } auto to_erase = FindIteratorForNoStatePrefetchContents( no_state_prefetch_data->contents()); CHECK(to_erase != active_prefetches_.end()); @@ -128,8 +131,9 @@ this, url, ORIGIN_LINK_REL_PRERENDER_CROSSDOMAIN, url::Origin::Create(GURL("https://uniquedifferentorigin.com")), expected_final_status); - for (const GURL& alias : alias_urls) + for (const GURL& alias : alias_urls) { EXPECT_TRUE(no_state_prefetch_contents->AddAliasURL(alias)); + } return SetNextNoStatePrefetchContents(std::move(no_state_prefetch_contents)); }
diff --git a/chrome/browser/preloading/prefetch/no_state_prefetch/prerender_nostate_prefetch_browsertest.cc b/chrome/browser/preloading/prefetch/no_state_prefetch/prerender_nostate_prefetch_browsertest.cc index 9674081..92570fb 100644 --- a/chrome/browser/preloading/prefetch/no_state_prefetch/prerender_nostate_prefetch_browsertest.cc +++ b/chrome/browser/preloading/prefetch/no_state_prefetch/prerender_nostate_prefetch_browsertest.cc
@@ -208,11 +208,13 @@ // content::WebContentsObserver implementation: void DidStartLoading() override { did_start_loading_ = true; } void DidStopLoading() override { - if (!did_start_loading_) + if (!did_start_loading_) { return; + } number_of_loads_--; - if (number_of_loads_ == 0) + if (number_of_loads_ == 0) { loop_.Quit(); + } } // TabStripModelObserver implementation: @@ -220,12 +222,14 @@ TabStripModel* tab_strip_model, const TabStripModelChange& change, const TabStripSelectionChange& selection) override { - if (change.type() != TabStripModelChange::kReplaced) + if (change.type() != TabStripModelChange::kReplaced) { return; + } auto* replace = change.GetReplace(); - if (replace->old_contents != web_contents()) + if (replace->old_contents != web_contents()) { return; + } // Switch to observing the new WebContents. Observe(replace->new_contents); @@ -260,8 +264,9 @@ public: NewTabNavigationOrSwapObserver() { BrowserList::AddObserver(this); - for (const Browser* browser : *BrowserList::GetInstance()) + for (const Browser* browser : *BrowserList::GetInstance()) { browser->tab_strip_model()->AddObserver(this); + } } NewTabNavigationOrSwapObserver(const NewTabNavigationOrSwapObserver&) = @@ -283,8 +288,9 @@ TabStripModel* tab_strip_model, const TabStripModelChange& change, const TabStripSelectionChange& selection) override { - if (change.type() != TabStripModelChange::kInserted || swap_observer_) + if (change.type() != TabStripModelChange::kInserted || swap_observer_) { return; + } content::WebContents* new_tab = change.GetInsert()->contents[0].contents; swap_observer_ = @@ -1617,8 +1623,9 @@ content::RenderProcessHost::AllHostsIterator()); !iter.IsAtEnd(); iter.Advance()) { // Don't count spare RenderProcessHosts. - if (!iter.GetCurrentValue()->HostHasNotBeenUsed()) + if (!iter.GetCurrentValue()->HostHasNotBeenUsed()) { ++host_count; + } content::RenderProcessHostWatcher process_exit_observer( iter.GetCurrentValue(), @@ -1880,9 +1887,7 @@ class SpeculationNoStatePrefetchBrowserTest : public NoStatePrefetchBrowserTest { public: - void SetUp() override { - NoStatePrefetchBrowserTest::SetUp(); - } + void SetUp() override { NoStatePrefetchBrowserTest::SetUp(); } void InsertSpeculation(const GURL& prefetch_url, FinalStatus expected_final_status,
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 523fb40..f379cfb 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -1585,7 +1585,7 @@ #if BUILDFLAG(ENABLE_PLUGINS) void RenderViewContextMenu::HandleAuthorizeAllPlugins() { ChromePluginServiceFilter::GetInstance()->AuthorizeAllPlugins( - source_web_contents_, false, std::string()); + source_web_contents_->GetPrimaryMainFrame(), false, std::string()); } #endif
diff --git a/chrome/browser/resources/ash/settings/device_page/per_device_keyboard_subsection.ts b/chrome/browser/resources/ash/settings/device_page/per_device_keyboard_subsection.ts index 0e778e6..e575e9b 100644 --- a/chrome/browser/resources/ash/settings/device_page/per_device_keyboard_subsection.ts +++ b/chrome/browser/resources/ash/settings/device_page/per_device_keyboard_subsection.ts
@@ -263,11 +263,10 @@ (await this.inputDeviceSettingsProvider.hasAmbientLightSensor()) ?.hasAmbientLightSensor; - if (this.hasKeyboardBacklight) { - const crSlider = this.shadowRoot! - .querySelector<SettingsSliderElement>( - '#keyboardBrightnessSlider')!.shadowRoot! - .querySelector('cr-slider'); + if (this.hasKeyboardBacklight && this.isChromeOsKeyboard()) { + const crSlider = + this.shadowRoot!.querySelector('#keyboardBrightnessSlider') + ?.shadowRoot!.querySelector('cr-slider'); if (crSlider) { // Set key press increment value to be 10. crSlider.setAttribute('key-press-slider-increment', '10');
diff --git a/chrome/browser/resources/commerce/product_specifications/shared_vars.css b/chrome/browser/resources/commerce/product_specifications/shared_vars.css index 60c1f5e..3de0c2a0 100644 --- a/chrome/browser/resources/commerce/product_specifications/shared_vars.css +++ b/chrome/browser/resources/commerce/product_specifications/shared_vars.css
@@ -16,7 +16,7 @@ --header-height) + var(--header-margin-bottom) + var( --table-data-unavailable-min-height)); --column-hover-padding: 4px; - --comparison-table-list-width: 416px; + --comparison-table-list-width: 360px; --header-height: 38px; --header-margin-bottom: 24px; --summary-container-padding: 16px;
diff --git a/chrome/browser/resources/lens/overlay/lens_overlay_app.html b/chrome/browser/resources/lens/overlay/lens_overlay_app.html index 6e713ef2..a174d711 100644 --- a/chrome/browser/resources/lens/overlay/lens_overlay_app.html +++ b/chrome/browser/resources/lens/overlay/lens_overlay_app.html
@@ -28,12 +28,12 @@ display: flex; pointer-events: none; position: absolute; - z-index: 6; /* Keep aligned with cursor and context menu. */ } .button-container, #searchboxContainer { transition: opacity 150ms, visibility 150ms; + z-index: 6; /* Keep aligned with cursor and context menu. */ } #searchboxContainer { @@ -347,16 +347,14 @@ on-pointerleave="handlePointerLeaveSelectionOverlay"> </lens-selection-overlay> <initial-gradient id="initialGradient"></initial-gradient> - <div id="searchboxContainer"> + <div id="searchboxContainer" on-focusout="handleSearchboxBlurred"> <cr-searchbox id="searchbox" - on-focus="handleSearchboxFocused" - on-blur="handleSearchboxBlurred" + on-focusin="handleSearchboxFocused" searchbox-aria-description="[[getSearchboxAriaDescription(showErrorState, showGhostLoader)]]"> </cr-searchbox> - </cr-searchbox> - <cr-searchbox-ghost-loader id="searchboxGhostLoader" - show-error-state="{{showErrorState}}"> + <cr-searchbox-ghost-loader id="searchboxGhostLoader" tabindex="-1" + show-error-state="{{showErrorState}}"> </cr-searchbox-ghost-loader> </div> <div id="translateButtonContainer" class="button-container">
diff --git a/chrome/browser/resources/lens/overlay/lens_overlay_app.ts b/chrome/browser/resources/lens/overlay/lens_overlay_app.ts index 8938ea2..6b111de 100644 --- a/chrome/browser/resources/lens/overlay/lens_overlay_app.ts +++ b/chrome/browser/resources/lens/overlay/lens_overlay_app.ts
@@ -387,7 +387,16 @@ ShimmerControlRequester.SEARCHBOX); } - private handleSearchboxBlurred() { + private handleSearchboxBlurred(event: FocusEvent) { + // Ignore the blurred event if focus left one child element to enter another + // child element. + if (event.relatedTarget instanceof Node && + this.$.searchboxContainer.contains(event.relatedTarget)) { + // TODO(380467089): This workaround wouldn't be needed if the ghost loader + // was part of the searchbox element. Remove this workaround once they are + // combined. + return; + } this.isSearchboxFocused = false; this.autocompleteRequestStarted = false; this.showErrorState = false;
diff --git a/chrome/browser/resources/lens/overlay/metrics_utils.ts b/chrome/browser/resources/lens/overlay/metrics_utils.ts index 6caaf96..c04cad99 100644 --- a/chrome/browser/resources/lens/overlay/metrics_utils.ts +++ b/chrome/browser/resources/lens/overlay/metrics_utils.ts
@@ -6,6 +6,34 @@ import {UserAction} from './lens.mojom-webui.js'; import type {SemanticEvent} from './lens.mojom-webui.js'; + +// LINT.IfChange(ContextMenuOption) +// The possible context menu options that can appear in the Lens overlay. +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +export enum ContextMenuOption { + COPY_TEXT = 0, + TRANSLATE_TEXT = 1, + SELECT_TEXT_IN_REGION = 2, + TRANSLATE_TEXT_IN_REGION = 3, + COPY_AS_IMAGE = 4, + SAVE_AS_IMAGE = 5, + // Must be last. + COUNT = 6, +} +// LINT.ThenChange(//tools/metrics/histograms/metadata/lens/enums.xml:LensOverlayContextMenuOption) + +export function recordContextMenuOptionShown( + invocationSource: string, contextMenuOption: ContextMenuOption) { + chrome.metricsPrivate.recordEnumerationValue( + `Lens.Overlay.ContextMenuOption.Shown`, contextMenuOption, + ContextMenuOption.COUNT); + chrome.metricsPrivate.recordEnumerationValue( + `Lens.Overlay.ByInvocationSource.${ + invocationSource}.ContextMenuOption.Shown`, + contextMenuOption, ContextMenuOption.COUNT); +} + export function recordLensOverlayInteraction( invocationSource: string, interaction: UserAction) { chrome.metricsPrivate.recordEnumerationValue(
diff --git a/chrome/browser/resources/lens/overlay/selection_overlay.ts b/chrome/browser/resources/lens/overlay/selection_overlay.ts index a57f8f1..a30c8fc4 100644 --- a/chrome/browser/resources/lens/overlay/selection_overlay.ts +++ b/chrome/browser/resources/lens/overlay/selection_overlay.ts
@@ -24,7 +24,7 @@ import type {CenterRotatedBox} from './geometry.mojom-webui.js'; import {UserAction} from './lens.mojom-webui.js'; import {INVOCATION_SOURCE} from './lens_overlay_app.js'; -import {recordLensOverlayInteraction} from './metrics_utils.js'; +import {ContextMenuOption, recordContextMenuOptionShown, recordLensOverlayInteraction} from './metrics_utils.js'; import type {ObjectLayerElement} from './object_layer.js'; import type {OverlayShimmerCanvasElement} from './overlay_shimmer_canvas.js'; import type {PostSelectionRendererElement} from './post_selection_renderer.js'; @@ -333,20 +333,20 @@ this.eventTracker_.add( document, 'show-selected-text-context-menu', (e: CustomEvent<SelectedTextContextMenuData>) => { - this.showSelectedTextContextMenu = true; this.selectedTextContextMenuX = e.detail.left; this.selectedTextContextMenuY = e.detail.bottom; this.highlightedText = e.detail.text; this.contentLanguage = e.detail.contentLanguage; this.textSelectionStartIndex = e.detail.selectionStartIndex; this.textSelectionEndIndex = e.detail.selectionEndIndex; + this.setShowSelectedTextContextMenu(true); }); this.eventTracker_.add( document, 'restore-selected-text-context-menu', () => { // show-selected-text-context-menu or // update-selected-text-context-menu must be triggered first so that // instance variables are set. - this.showSelectedTextContextMenu = true; + this.setShowSelectedTextContextMenu(true); }); this.eventTracker_.add( document, 'update-selected-text-context-menu', @@ -359,7 +359,7 @@ this.textSelectionEndIndex = e.detail.selectionEndIndex; }); this.eventTracker_.add(document, 'hide-selected-text-context-menu', () => { - this.showSelectedTextContextMenu = false; + this.setShowSelectedTextContextMenu(false); this.textSelectionStartIndex = -1; this.textSelectionEndIndex = -1; }); @@ -376,10 +376,10 @@ this.showDetectedTextContextMenuOptions = this.detectedTextStartIndex !== -1 && this.detectedTextEndIndex !== -1; - this.showSelectedRegionContextMenu = + this.setShowSelectedRegionContextMenu( (!this.suppressCopyAndSaveAsImage && (this.enableCopyAsImage || this.enableSaveAsImage)) || - this.showDetectedTextContextMenuOptions; + this.showDetectedTextContextMenuOptions); }); this.eventTracker_.add( document, 'restore-selected-region-context-menu', () => { @@ -387,15 +387,15 @@ // we are still waiting for the text layer to receive text. Check for // this condition by checking if the box has been set. if (this.selectedRegionContextMenuBox !== undefined) { - this.showSelectedRegionContextMenu = + this.setShowSelectedRegionContextMenu( (!this.suppressCopyAndSaveAsImage && (this.enableCopyAsImage || this.enableSaveAsImage)) || - this.showDetectedTextContextMenuOptions; + this.showDetectedTextContextMenuOptions); } }); this.eventTracker_.add( document, 'hide-selected-region-context-menu', () => { - this.showSelectedRegionContextMenu = false; + this.setShowSelectedRegionContextMenu(false); this.detectedTextStartIndex = -1; this.detectedTextEndIndex = -1; }); @@ -957,7 +957,7 @@ bubbles: true, composed: true, })); - this.showSelectedTextContextMenu = false; + this.setShowSelectedTextContextMenu(false); } private handleSelectText() { @@ -976,14 +976,14 @@ BrowserProxyImpl.getInstance().handler.issueTranslateSelectionRequest( this.highlightedText.replaceAll('\r\n', ' '), this.contentLanguage, this.textSelectionStartIndex, this.textSelectionEndIndex); - this.showSelectedTextContextMenu = false; + this.setShowSelectedTextContextMenu(false); recordLensOverlayInteraction(INVOCATION_SOURCE, UserAction.kTranslateText); } private handleCopyAsImage() { BrowserProxyImpl.getInstance().handler.copyImage( this.selectedRegionContextMenuBox); - this.showSelectedRegionContextMenu = false; + this.setShowSelectedRegionContextMenu(false); recordLensOverlayInteraction(INVOCATION_SOURCE, UserAction.kCopyAsImage); this.dispatchEvent(new CustomEvent('copied-as-image', { bubbles: true, @@ -994,7 +994,7 @@ private handleSaveAsImage() { BrowserProxyImpl.getInstance().handler.saveAsImage( this.selectedRegionContextMenuBox); - this.showSelectedRegionContextMenu = false; + this.setShowSelectedRegionContextMenu(false); recordLensOverlayInteraction(INVOCATION_SOURCE, UserAction.kSaveAsImage); } @@ -1027,6 +1027,50 @@ })); } + // Sets the text context menu to be visible or not, and logs the shown + // context menu options. + private setShowSelectedTextContextMenu(shouldShow: boolean) { + if (shouldShow && !this.showSelectedTextContextMenu) { + // If the context menu was not being shown earlier, but will be now, log + // the shown context menu options. + recordContextMenuOptionShown( + INVOCATION_SOURCE, ContextMenuOption.COPY_TEXT); + if (this.showTranslateContextMenuItem) { + recordContextMenuOptionShown( + INVOCATION_SOURCE, ContextMenuOption.TRANSLATE_TEXT); + } + } + this.showSelectedTextContextMenu = shouldShow; + } + + // Sets the region context menu to be visible or not, and logs the shown + // context menu options. + private setShowSelectedRegionContextMenu(shouldShow: boolean) { + if (shouldShow && !this.showSelectedRegionContextMenu) { + // If the context menu was not being shown earlier, but will be now, log + // the shown context menu options. + if (this.showDetectedTextContextMenuOptions) { + recordContextMenuOptionShown( + INVOCATION_SOURCE, ContextMenuOption.SELECT_TEXT_IN_REGION); + if (this.showTranslateContextMenuItem) { + recordContextMenuOptionShown( + INVOCATION_SOURCE, ContextMenuOption.TRANSLATE_TEXT_IN_REGION); + } + } + if (!this.suppressCopyAndSaveAsImage) { + if (this.enableCopyAsImage) { + recordContextMenuOptionShown( + INVOCATION_SOURCE, ContextMenuOption.COPY_AS_IMAGE); + } + if (this.enableSaveAsImage) { + recordContextMenuOptionShown( + INVOCATION_SOURCE, ContextMenuOption.SAVE_AS_IMAGE); + } + } + } + this.showSelectedRegionContextMenu = shouldShow; + } + private onInitialFlashAnimationEnd() { if (this.hasInitialFlashAnimationEnded) { return;
diff --git a/chrome/browser/resources/lens/overlay/side_panel/side_panel_app.html b/chrome/browser/resources/lens/overlay/side_panel/side_panel_app.html index 63abe2a..d2df52f 100644 --- a/chrome/browser/resources/lens/overlay/side_panel/side_panel_app.html +++ b/chrome/browser/resources/lens/overlay/side_panel/side_panel_app.html
@@ -190,21 +190,25 @@ display: block; } </style> -<div id="searchboxContainer" on-escape-searchbox="handleEscapeSearchbox"> +<div id="searchboxContainer" + on-escape-searchbox="handleEscapeSearchbox" + on-focusout="onSearchboxFocusOut_"> <template is="dom-if" if="[[isBackArrowVisible]]"> <cr-icon-button id="backButton" class="action-icon icon-arrow-back" on-click="onBackArrowClick" aria-label="$i18n{backButton}"> </cr-icon-button> </template> - <cr-searchbox + <cr-searchbox id="searchbox" placeholder-text="{{placeholderText}}" searchbox-aria-description="[[getSearchboxAriaDescription(showErrorState, showGhostLoader)]]" - > + on-focusin="onSearchboxFocusIn_" + > </cr-searchbox> <cr-searchbox-ghost-loader id="searchboxGhostLoader" - show-error-state="{{showErrorState}}"> + show-error-state="{{showErrorState}}" + tabindex="-1"> </cr-searchbox-ghost-loader> </div>
diff --git a/chrome/browser/resources/lens/overlay/side_panel/side_panel_app.ts b/chrome/browser/resources/lens/overlay/side_panel/side_panel_app.ts index e8110af..62d14b5 100644 --- a/chrome/browser/resources/lens/overlay/side_panel/side_panel_app.ts +++ b/chrome/browser/resources/lens/overlay/side_panel/side_panel_app.ts
@@ -37,6 +37,7 @@ ghostLoader: SidePanelGhostLoaderElement, networkErrorPage: HTMLDivElement, searchbox: SearchboxElement, + searchboxContainer: HTMLElement, searchboxGhostLoader: SearchboxGhostLoaderElement, }; } @@ -188,13 +189,6 @@ this.browserProxy.callbackRouter.suppressGhostLoader.addListener( this.suppressGhostLoader_.bind(this)), ]; - - this.eventTracker_.add(this.$.searchbox, 'focusin', () => { - this.onSearchboxFocusIn_(); - }); - this.eventTracker_.add(this.$.searchbox, 'focusout', () => { - this.onSearchboxFocusOut_(); - }); this.eventTracker_.add(this.$.searchbox, 'mousedown', () => { this.suppressGhostLoader = false; this.showErrorState = false; @@ -276,7 +270,16 @@ 'kLensSidePanelSearchBoxFocusedEventId'); } - private onSearchboxFocusOut_() { + private onSearchboxFocusOut_(event: FocusEvent) { + // Ignore the blurred event if focus left one child element to enter another + // child element. + if (event.relatedTarget instanceof Node && + this.$.searchboxContainer.contains(event.relatedTarget)) { + // TODO(380467089): This workaround wouldn't be needed if the ghost loader + // was part of the searchbox element. Remove this workaround once they are + // combined. + return; + } this.isBackArrowVisible = this.wasBackArrowAvailable; this.isSearchboxFocused = false; this.autocompleteRequestStarted = false;
diff --git a/chrome/browser/resources/lens/shared/searchbox_ghost_loader.ts b/chrome/browser/resources/lens/shared/searchbox_ghost_loader.ts index babe573..e90c9f8f 100644 --- a/chrome/browser/resources/lens/shared/searchbox_ghost_loader.ts +++ b/chrome/browser/resources/lens/shared/searchbox_ghost_loader.ts
@@ -21,7 +21,9 @@ export class SearchboxGhostLoaderElement extends SearchboxGhostLoaderElementBase { static get is() { + // LINT.IfChange(GhostLoaderTagName) return 'cr-searchbox-ghost-loader'; + // LINT.ThenChange(/ui/webui/resources/cr_components/searchbox/searchbox.ts:GhostLoaderTagName) } static get template() {
diff --git a/chrome/browser/resources/privacy_sandbox/privacy_sandbox_notice_dialog.html b/chrome/browser/resources/privacy_sandbox/privacy_sandbox_notice_dialog.html index da5de11..da5f9fc91 100644 --- a/chrome/browser/resources/privacy_sandbox/privacy_sandbox_notice_dialog.html +++ b/chrome/browser/resources/privacy_sandbox/privacy_sandbox_notice_dialog.html
@@ -11,6 +11,9 @@ margin: 0; padding: 0; } + privacy-sandbox-notice-dialog-app { + display: flex; + } @media (prefers-color-scheme: dark) { body { background-color: var(--md-background-color);
diff --git a/chrome/browser/test_dummy/android/java/src/org/chromium/chrome/browser/test_dummy/TestDummy.java b/chrome/browser/test_dummy/android/java/src/org/chromium/chrome/browser/test_dummy/TestDummy.java index 2ebb8e3..8d9de49a 100644 --- a/chrome/browser/test_dummy/android/java/src/org/chromium/chrome/browser/test_dummy/TestDummy.java +++ b/chrome/browser/test_dummy/android/java/src/org/chromium/chrome/browser/test_dummy/TestDummy.java
@@ -7,7 +7,10 @@ import android.app.Activity; import android.content.Intent; +import org.chromium.build.annotations.NullMarked; + /** Runs scenarios to test dynamic feature module functionality. */ +@NullMarked public interface TestDummy { /** * Run the test scenario encoded in the given intent.
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index adf83290..c95f1f5 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -2503,6 +2503,7 @@ "//chromeos/ash/components/disks", "//chromeos/ash/components/drivefs", "//chromeos/ash/components/drivefs/mojom:mojom", + "//chromeos/ash/components/editor_menu/public/cpp", "//chromeos/ash/components/emoji", "//chromeos/ash/components/emoji:mojo_bindings", "//chromeos/ash/components/emoji:resources", @@ -2565,7 +2566,6 @@ "//chromeos/ash/services/multidevice_setup/public/cpp:url_provider", "//chromeos/ash/services/nearby/public/mojom", "//chromeos/ash/services/recording/public/mojom", - "//chromeos/components/editor_menu/public/cpp", "//chromeos/components/in_session_auth", "//chromeos/components/kiosk", "//chromeos/components/libsegmentation:buildflags", @@ -5343,12 +5343,11 @@ "web_applications/diagnostics/app_type_initialized_event.h", "web_applications/diagnostics/web_app_icon_health_checks.cc", "web_applications/diagnostics/web_app_icon_health_checks.h", - "web_applications/navigation_capturing_information_forwarder.cc", - "web_applications/navigation_capturing_information_forwarder.h", - "web_applications/navigation_capturing_navigation_handle_user_data.cc", - "web_applications/navigation_capturing_navigation_handle_user_data.h", + "web_applications/navigation_capturing_process.cc", + "web_applications/navigation_capturing_process.h", "web_applications/navigation_capturing_redirection_throttle.cc", "web_applications/navigation_capturing_redirection_throttle.h", + "web_applications/navigation_handle_user_data_forwarder.h", "web_applications/share_target_utils.cc", "web_applications/share_target_utils.h", "web_applications/sub_apps_install_dialog_controller.cc", @@ -5362,6 +5361,8 @@ "web_applications/web_app_dialog_utils.cc", "web_applications/web_app_dialog_utils.h", "web_applications/web_app_dialogs.h", + "web_applications/web_app_launch_navigation_handle_user_data.cc", + "web_applications/web_app_launch_navigation_handle_user_data.h", "web_applications/web_app_launch_process.cc", "web_applications/web_app_launch_process.h", "web_applications/web_app_launch_utils.cc",
diff --git a/chrome/browser/ui/ash/editor_menu/BUILD.gn b/chrome/browser/ui/ash/editor_menu/BUILD.gn index 4b40786..6a098131 100644 --- a/chrome/browser/ui/ash/editor_menu/BUILD.gn +++ b/chrome/browser/ui/ash/editor_menu/BUILD.gn
@@ -28,7 +28,7 @@ deps = [ "//base", "//chrome/browser:browser_process", - "//chromeos/components/editor_menu/public/cpp", + "//chromeos/ash/components/editor_menu/public/cpp", "//chromeos/crosapi/mojom", "//ui/aura", "//ui/display", @@ -62,7 +62,7 @@ "//chrome/browser/ash/lobster", "//chrome/browser/profiles:profile", "//chrome/browser/ui/ash/read_write_cards", - "//chromeos/components/editor_menu/public/cpp", + "//chromeos/ash/components/editor_menu/public/cpp", "//chromeos/components/magic_boost/public/cpp", "//chromeos/constants:constants", "//chromeos/crosapi/mojom", @@ -101,7 +101,7 @@ "//base", "//build:branding_buildflags", "//chrome/browser:browser_process", - "//chromeos/components/editor_menu/public/cpp", + "//chromeos/ash/components/editor_menu/public/cpp", "//chromeos/constants:constants", "//chromeos/strings:strings_grit", "//chromeos/ui/vector_icons",
diff --git a/chrome/browser/ui/ash/editor_menu/DIR_METADATA b/chrome/browser/ui/ash/editor_menu/DIR_METADATA index 9143772..afebe8d7 100644 --- a/chrome/browser/ui/ash/editor_menu/DIR_METADATA +++ b/chrome/browser/ui/ash/editor_menu/DIR_METADATA
@@ -1 +1 @@ -mixins: "//chromeos/components/editor_menu/COMMON_METADATA" +mixins: "//chromeos/ash/components/editor_menu/COMMON_METADATA"
diff --git a/chrome/browser/ui/ash/editor_menu/editor_manager_ash.cc b/chrome/browser/ui/ash/editor_menu/editor_manager_ash.cc index 097e34cb..bf01a0a 100644 --- a/chrome/browser/ui/ash/editor_menu/editor_manager_ash.cc +++ b/chrome/browser/ui/ash/editor_menu/editor_manager_ash.cc
@@ -9,7 +9,7 @@ #include "base/observer_list.h" #include "chrome/browser/ui/ash/editor_menu/utils/editor_types.h" #include "chrome/browser/ui/ash/editor_menu/utils/mojo.h" -#include "chromeos/components/editor_menu/public/cpp/preset_text_query.h" +#include "chromeos/ash/components/editor_menu/public/cpp/preset_text_query.h" #include "chromeos/crosapi/mojom/editor_panel.mojom.h" namespace chromeos::editor_menu {
diff --git a/chrome/browser/ui/ash/editor_menu/editor_menu_card_context.h b/chrome/browser/ui/ash/editor_menu/editor_menu_card_context.h index 68f83412..332a469 100644 --- a/chrome/browser/ui/ash/editor_menu/editor_menu_card_context.h +++ b/chrome/browser/ui/ash/editor_menu/editor_menu_card_context.h
@@ -7,7 +7,7 @@ #include "chrome/browser/ui/ash/editor_menu/utils/editor_types.h" #include "chrome/browser/ui/ash/editor_menu/utils/text_and_image_mode.h" -#include "chromeos/components/editor_menu/public/cpp/preset_text_query.h" +#include "chromeos/ash/components/editor_menu/public/cpp/preset_text_query.h" namespace chromeos::editor_menu {
diff --git a/chrome/browser/ui/ash/editor_menu/editor_menu_card_context_unittest.cc b/chrome/browser/ui/ash/editor_menu/editor_menu_card_context_unittest.cc index 3e1a708..016dd02f 100644 --- a/chrome/browser/ui/ash/editor_menu/editor_menu_card_context_unittest.cc +++ b/chrome/browser/ui/ash/editor_menu/editor_menu_card_context_unittest.cc
@@ -6,7 +6,7 @@ #include "chrome/browser/ui/ash/editor_menu/editor_menu_strings.h" #include "chrome/browser/ui/ash/editor_menu/utils/text_and_image_mode.h" -#include "chromeos/components/editor_menu/public/cpp/preset_text_query.h" +#include "chromeos/ash/components/editor_menu/public/cpp/preset_text_query.h" #include "testing/gmock/include/gmock/gmock-matchers.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/ui/ash/editor_menu/editor_menu_chip_view.cc b/chrome/browser/ui/ash/editor_menu/editor_menu_chip_view.cc index 5eab7f1..445c0d50 100644 --- a/chrome/browser/ui/ash/editor_menu/editor_menu_chip_view.cc +++ b/chrome/browser/ui/ash/editor_menu/editor_menu_chip_view.cc
@@ -5,8 +5,8 @@ #include "chrome/browser/ui/ash/editor_menu/editor_menu_chip_view.h" #include "chrome/browser/ui/ash/editor_menu/editor_menu_strings.h" -#include "chromeos/components/editor_menu/public/cpp/icon.h" -#include "chromeos/components/editor_menu/public/cpp/preset_text_query.h" +#include "chromeos/ash/components/editor_menu/public/cpp/icon.h" +#include "chromeos/ash/components/editor_menu/public/cpp/preset_text_query.h" #include "ui/base/metadata/metadata_impl_macros.h" #include "ui/base/models/image_model.h" #include "ui/color/color_id.h"
diff --git a/chrome/browser/ui/ash/editor_menu/editor_menu_controller_impl.cc b/chrome/browser/ui/ash/editor_menu/editor_menu_controller_impl.cc index 6652751..30abd78 100644 --- a/chrome/browser/ui/ash/editor_menu/editor_menu_controller_impl.cc +++ b/chrome/browser/ui/ash/editor_menu/editor_menu_controller_impl.cc
@@ -31,7 +31,7 @@ #include "chrome/browser/ui/ash/editor_menu/editor_menu_view.h" #include "chrome/browser/ui/ash/editor_menu/utils/editor_types.h" #include "chrome/browser/ui/ash/editor_menu/utils/text_and_image_mode.h" -#include "chromeos/components/editor_menu/public/cpp/preset_text_query.h" +#include "chromeos/ash/components/editor_menu/public/cpp/preset_text_query.h" #include "chromeos/components/magic_boost/public/cpp/magic_boost_state.h" #include "chromeos/constants/chromeos_features.h" #include "content/public/browser/browser_context.h"
diff --git a/chrome/browser/ui/ash/editor_menu/editor_menu_view.cc b/chrome/browser/ui/ash/editor_menu/editor_menu_view.cc index 7f299b4..3d7a0de 100644 --- a/chrome/browser/ui/ash/editor_menu/editor_menu_view.cc +++ b/chrome/browser/ui/ash/editor_menu/editor_menu_view.cc
@@ -21,8 +21,8 @@ #include "chrome/browser/ui/ash/editor_menu/utils/pre_target_handler.h" #include "chrome/browser/ui/ash/editor_menu/utils/pre_target_handler_view.h" #include "chrome/browser/ui/ash/editor_menu/utils/utils.h" -#include "chromeos/components/editor_menu/public/cpp/icon.h" -#include "chromeos/components/editor_menu/public/cpp/preset_text_query.h" +#include "chromeos/ash/components/editor_menu/public/cpp/icon.h" +#include "chromeos/ash/components/editor_menu/public/cpp/preset_text_query.h" #include "chromeos/strings/grit/chromeos_strings.h" #include "components/vector_icons/vector_icons.h" #include "ui/base/accelerators/accelerator.h"
diff --git a/chrome/browser/ui/ash/editor_menu/editor_menu_view.h b/chrome/browser/ui/ash/editor_menu/editor_menu_view.h index 0295a08..679ce5b6 100644 --- a/chrome/browser/ui/ash/editor_menu/editor_menu_view.h +++ b/chrome/browser/ui/ash/editor_menu/editor_menu_view.h
@@ -11,7 +11,7 @@ #include "base/memory/weak_ptr.h" #include "chrome/browser/ui/ash/editor_menu/utils/pre_target_handler_view.h" #include "chrome/browser/ui/ash/editor_menu/utils/text_and_image_mode.h" -#include "chromeos/components/editor_menu/public/cpp/preset_text_query.h" +#include "chromeos/ash/components/editor_menu/public/cpp/preset_text_query.h" #include "ui/base/metadata/metadata_header_macros.h" #include "ui/views/controls/tabbed_pane/tabbed_pane.h" #include "ui/views/controls/tabbed_pane/tabbed_pane_listener.h"
diff --git a/chrome/browser/ui/ash/editor_menu/editor_menu_view_unittest.cc b/chrome/browser/ui/ash/editor_menu/editor_menu_view_unittest.cc index 11cb96fd..20c06e6 100644 --- a/chrome/browser/ui/ash/editor_menu/editor_menu_view_unittest.cc +++ b/chrome/browser/ui/ash/editor_menu/editor_menu_view_unittest.cc
@@ -13,7 +13,7 @@ #include "chrome/browser/ui/ash/editor_menu/editor_menu_view.h" #include "chrome/browser/ui/ash/editor_menu/editor_menu_view_delegate.h" #include "chrome/test/views/chrome_views_test_base.h" -#include "chromeos/components/editor_menu/public/cpp/preset_text_query.h" +#include "chromeos/ash/components/editor_menu/public/cpp/preset_text_query.h" #include "chromeos/constants/chromeos_features.h" #include "testing/gmock/include/gmock/gmock-matchers.h" #include "testing/gmock/include/gmock/gmock.h"
diff --git a/chrome/browser/ui/ash/editor_menu/utils/editor_types.h b/chrome/browser/ui/ash/editor_menu/utils/editor_types.h index 9ed99b5..7d40c27 100644 --- a/chrome/browser/ui/ash/editor_menu/utils/editor_types.h +++ b/chrome/browser/ui/ash/editor_menu/utils/editor_types.h
@@ -5,7 +5,7 @@ #ifndef CHROME_BROWSER_UI_ASH_EDITOR_MENU_UTILS_EDITOR_TYPES_H_ #define CHROME_BROWSER_UI_ASH_EDITOR_MENU_UTILS_EDITOR_TYPES_H_ -#include "chromeos/components/editor_menu/public/cpp/preset_text_query.h" +#include "chromeos/ash/components/editor_menu/public/cpp/preset_text_query.h" namespace chromeos::editor_menu {
diff --git a/chrome/browser/ui/ash/login/simple_web_view_dialog.cc b/chrome/browser/ui/ash/login/simple_web_view_dialog.cc index d65743b..d7eaae2 100644 --- a/chrome/browser/ui/ash/login/simple_web_view_dialog.cc +++ b/chrome/browser/ui/ash/login/simple_web_view_dialog.cc
@@ -201,9 +201,18 @@ forward->SetID(VIEW_ID_FORWARD_BUTTON); forward_ = forward.get(); - // Location bar. + // Location bar. Passing in nullptr as there's no browser in this case. This + // may lead to crash, which was discussed in crbug.com/379534750 and was + // mitigated in crrev.com/c/6043176. So far simple_web_view_dialog, which is + // specifically for ChromeOS, is one of the only two classes that passes in + // nullptr as the browser argument, when initiating a location_bar_view in + // production code. The other known case is presentation_receiver_window_view. + // There is discussion to move simple_web_view_dialog away from using + // location_bar_view to avoid this unwanted nullptr situation. As for + // presentation_receiver_window_view, it is about to be sunsetted in a year or + // so. auto location_bar = std::make_unique<LocationBarView>( - nullptr, profile_, command_updater_.get(), this, true); + /*browser=*/nullptr, profile_, command_updater_.get(), this, true); location_bar_ = location_bar.get(); // Reload button.
diff --git a/chrome/browser/ui/ash/quick_insert/BUILD.gn b/chrome/browser/ui/ash/quick_insert/BUILD.gn index f72f84d..424f9f3 100644 --- a/chrome/browser/ui/ash/quick_insert/BUILD.gn +++ b/chrome/browser/ui/ash/quick_insert/BUILD.gn
@@ -40,7 +40,7 @@ "//chrome/common", "//chromeos/ash/components/browser_context_helper", "//chromeos/ash/components/drivefs/mojom", - "//chromeos/components/editor_menu/public/cpp", + "//chromeos/ash/components/editor_menu/public/cpp", "//chromeos/constants", "//components/favicon/core:core", "//components/optimization_guide/core",
diff --git a/chrome/browser/ui/ash/quick_insert/quick_insert_client_impl.cc b/chrome/browser/ui/ash/quick_insert/quick_insert_client_impl.cc index 122120b..c90fa94 100644 --- a/chrome/browser/ui/ash/quick_insert/quick_insert_client_impl.cc +++ b/chrome/browser/ui/ash/quick_insert/quick_insert_client_impl.cc
@@ -51,7 +51,7 @@ #include "chrome/browser/ui/ash/quick_insert/quick_insert_thumbnail_loader.h" #include "chromeos/ash/components/browser_context_helper/browser_context_helper.h" #include "chromeos/ash/components/drivefs/mojom/drivefs.mojom.h" -#include "chromeos/components/editor_menu/public/cpp/preset_text_query.h" +#include "chromeos/ash/components/editor_menu/public/cpp/preset_text_query.h" #include "chromeos/constants/chromeos_features.h" #include "components/user_manager/user.h" #include "components/user_manager/user_manager.h"
diff --git a/chrome/browser/ui/browser_actions.cc b/chrome/browser/ui/browser_actions.cc index 2f87bbe..14cde27 100644 --- a/chrome/browser/ui/browser_actions.cc +++ b/chrome/browser/ui/browser_actions.cc
@@ -27,6 +27,7 @@ #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/browser_window/public/browser_window_features.h" #include "chrome/browser/ui/lens/lens_overlay_controller.h" +#include "chrome/browser/ui/lens/lens_overlay_entry_point_controller.h" #include "chrome/browser/ui/passwords/manage_passwords_ui_controller.h" #include "chrome/browser/ui/passwords/passwords_model_delegate.h" #include "chrome/browser/ui/qrcode_generator/qrcode_generator_bubble_controller.h" @@ -214,19 +215,8 @@ if (!browser) { return; } - - LensOverlayController* controller = browser->GetActiveTabInterface() - ->GetTabFeatures() - ->lens_overlay_controller(); - - // Toggle the Lens overlay. There's no need to show or hide the side - // panel as the overlay controller will handle that. - if (controller->IsOverlayActive()) { - controller->CloseUIAsync( - lens::LensOverlayDismissalSource::kToolbar); - } else { - controller->ShowUI(lens::LensOverlayInvocationSource::kToolbar); - } + lens::LensOverlayEntryPointController::InvokeAction( + browser->GetActiveTabInterface(), context); }, browser->AsWeakPtr()); const gfx::VectorIcon& icon =
diff --git a/chrome/browser/ui/browser_navigator.cc b/chrome/browser/ui/browser_navigator.cc index 819c4484..4618057 100644 --- a/chrome/browser/ui/browser_navigator.cc +++ b/chrome/browser/ui/browser_navigator.cc
@@ -63,6 +63,7 @@ #include "url/url_constants.h" #if !BUILDFLAG(IS_ANDROID) +#include "chrome/browser/ui/web_applications/navigation_capturing_process.h" #include "chrome/browser/ui/web_applications/web_app_launch_utils.h" #endif // !BUILDFLAG(IS_ANDROID) @@ -744,11 +745,16 @@ int singleton_index; #if !BUILDFLAG(IS_ANDROID) - web_app::AppNavigationResult app_navigation_result = - web_app::MaybeHandleAppNavigation(*params); + std::unique_ptr<web_app::NavigationCapturingProcess> app_navigation = + web_app::NavigationCapturingProcess::MaybeHandleAppNavigation(*params); + std::optional<std::tuple<Browser*, int>> app_browser_tab_override; + if (app_navigation) { + app_browser_tab_override = + app_navigation->GetInitialBrowserAndTabOverrideForNavigation(*params); + } std::tie(params->browser, singleton_index) = - app_navigation_result.browser_tab_override().has_value() - ? *app_navigation_result.browser_tab_override() + app_browser_tab_override.has_value() + ? *app_browser_tab_override : GetBrowserAndTabForDisposition(*params); #else // !BUILDFLAG(IS_ANDROID) std::tie(params->browser, singleton_index) = @@ -1009,8 +1015,11 @@ // be non null, so perform tasks if the navigation has been captured by a web // app, like enqueueing launch params. #if !BUILDFLAG(IS_ANDROID) - web_app::OnWebAppNavigationAfterWebContentsCreation( - std::move(app_navigation_result), *params, navigation_handle); + if (app_navigation) { + web_app::NavigationCapturingProcess::AfterWebContentsCreation( + std::move(app_navigation), *params->navigated_or_inserted_contents, + navigation_handle.get()); + } #endif // !BUILDFLAG(IS_ANDROID) return navigation_handle; }
diff --git a/chrome/browser/ui/lens/lens_overlay_entry_point_controller.cc b/chrome/browser/ui/lens/lens_overlay_entry_point_controller.cc index d078cb49..fa5ebdf2 100644 --- a/chrome/browser/ui/lens/lens_overlay_entry_point_controller.cc +++ b/chrome/browser/ui/lens/lens_overlay_entry_point_controller.cc
@@ -150,6 +150,22 @@ return phys_mem_mb > lens::features::GetLensOverlayMinRamMb(); } +// static +void LensOverlayEntryPointController::InvokeAction( + tabs::TabInterface* active_tab, + const actions::ActionInvocationContext& context) { + LensOverlayController* controller = + active_tab->GetTabFeatures()->lens_overlay_controller(); + + // Toggle the Lens overlay. There's no need to show or hide the side + // panel as the overlay controller will handle that. + if (controller->IsOverlayActive()) { + controller->CloseUIAsync(lens::LensOverlayDismissalSource::kToolbar); + } else { + controller->ShowUI(lens::LensOverlayInvocationSource::kToolbar); + } +} + void LensOverlayEntryPointController::OnViewAddedToWidget(views::View* view) { CHECK(location_bar_); location_bar_->GetFocusManager()->AddFocusChangeListener(this);
diff --git a/chrome/browser/ui/lens/lens_overlay_entry_point_controller.h b/chrome/browser/ui/lens/lens_overlay_entry_point_controller.h index 7113ab2..dc4241b 100644 --- a/chrome/browser/ui/lens/lens_overlay_entry_point_controller.h +++ b/chrome/browser/ui/lens/lens_overlay_entry_point_controller.h
@@ -18,9 +18,13 @@ class BrowserWindowInterface; class CommandUpdater; +namespace tabs { +class TabInterface; +} // namespace tabs + namespace views { class View; -} +} // namespace views namespace lens { @@ -44,6 +48,10 @@ // Whether the entry points should be enabled. bool IsEnabled(); + // Invokes the entrypoint action. + static void InvokeAction(tabs::TabInterface* active_tab, + const actions::ActionInvocationContext& context); + private: // FullscreenObserver: void OnFullscreenStateChanged() override;
diff --git a/chrome/browser/ui/lens/lens_overlay_gen204_controller.cc b/chrome/browser/ui/lens/lens_overlay_gen204_controller.cc index 929e764d7..0c22cc8 100644 --- a/chrome/browser/ui/lens/lens_overlay_gen204_controller.cc +++ b/chrome/browser/ui/lens/lens_overlay_gen204_controller.cc
@@ -54,7 +54,7 @@ constexpr char kPageContentUploadLatencyId[] = "pcu"; constexpr char kPartialPageContentUploadLatencyId[] = "ppcu"; constexpr char kInteractionFetchLatencyId[] = "lif"; -constexpr char kFetchStickyClusterInfoLatencyId[] = "sct"; +constexpr char kFetchStickyClusterInfoLatencyId[] = "sctr"; constexpr char kInvocationToInitialClusterInfoRequestLatencyId[] = "cstcirs"; constexpr char kInvocationToInitialFullObjectsRequestLatencyId[] = "cstiors"; constexpr char kInvocationToInitialInteractionRequestLatencyId[] = "cstiirs";
diff --git a/chrome/browser/ui/lens/lens_overlay_gen204_controller_unittest.cc b/chrome/browser/ui/lens/lens_overlay_gen204_controller_unittest.cc index 80dfd3b..60e0ac98 100644 --- a/chrome/browser/ui/lens/lens_overlay_gen204_controller_unittest.cc +++ b/chrome/browser/ui/lens/lens_overlay_gen204_controller_unittest.cc
@@ -201,7 +201,7 @@ EXPECT_TRUE(net::GetValueForKeyInQuery(gen204_controller->last_url_sent_, kLatencyRequestTypeQueryParameter, &request_type_param)); - ASSERT_EQ(request_type_param, "fpof.100,sct.200"); + ASSERT_EQ(request_type_param, "fpof.100,sctr.200"); // Check that the visual input type param is present. EXPECT_TRUE(net::GetValueForKeyInQuery(gen204_controller->last_url_sent_,
diff --git a/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc b/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc index 5c304df6..0c3cfea 100644 --- a/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc +++ b/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc
@@ -1483,7 +1483,7 @@ } // Verifies that keyword search works when `SiteSearchSettings` policy is set. -IN_PROC_BROWSER_TEST_F(OmniboxViewTest, NonFeatured) { +IN_PROC_BROWSER_TEST_F(OmniboxViewTest, NonFeaturedPolicyKeyword) { policy::PolicyMap policies; policies.Set(policy::key::kSiteSearchSettings, policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD, @@ -1505,36 +1505,37 @@ // Trigger keyword hint mode. ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSiteSearchPolicyKeywordKeys)); - ASSERT_TRUE(omnibox_view->model()->is_keyword_hint()); - ASSERT_EQ(kSiteSearchPolicyKeyword, omnibox_view->model()->keyword()); + EXPECT_TRUE(omnibox_view->model()->is_keyword_hint()); + EXPECT_EQ(omnibox_view->model()->keyword(), kSiteSearchPolicyKeyword); // Trigger keyword mode. ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_TAB, 0)); - ASSERT_FALSE(omnibox_view->model()->is_keyword_hint()); - ASSERT_EQ(kSiteSearchPolicyKeyword, omnibox_view->model()->keyword()); + EXPECT_FALSE(omnibox_view->model()->is_keyword_hint()); + EXPECT_EQ(omnibox_view->model()->keyword(), kSiteSearchPolicyKeyword); // Input something as search text and perform a search. ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchTextKeys)); ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone()); - ASSERT_TRUE(omnibox_view->model()->PopupIsOpen()); + EXPECT_TRUE(omnibox_view->model()->PopupIsOpen()); - EXPECT_EQ(kSiteSearchPolicyTextURL, omnibox_view->controller() - ->autocomplete_controller() - ->result() - .default_match() - ->destination_url.spec()); + EXPECT_EQ(omnibox_view->controller() + ->autocomplete_controller() + ->result() + .default_match() + ->destination_url.spec(), + kSiteSearchPolicyTextURL); } // Verifies that keyword search works when `SiteSearchSettings` policy defines // a featured search engine. -IN_PROC_BROWSER_TEST_F(OmniboxViewTest, Featured) { +IN_PROC_BROWSER_TEST_F(OmniboxViewTest, FeaturedPolicyKeyword) { policy::PolicyMap policies; policies.Set(policy::key::kSiteSearchSettings, policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD, CreateSiteSearchPolicyValue(/*featured=*/true), nullptr); policy_provider()->UpdateChromePolicy(policies); - OmniboxView* omnibox_view = nullptr; + OmniboxView* omnibox_view; ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view)); // Check that new entries have been added to TemplateURLService. @@ -1547,34 +1548,34 @@ EXPECT_EQ(turl->url(), kSiteSearchPolicyURL); EXPECT_TRUE(turl->featured_by_policy()); - // Trigger keyword hint mode. + // Type the keyword. ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_2, ui::EF_SHIFT_DOWN)); ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSiteSearchPolicyKeywordKeys)); - ASSERT_TRUE(omnibox_view->model()->is_keyword_hint()); - ASSERT_EQ(kSiteSearchPolicyKeywordWithAtPrefix, - omnibox_view->model()->keyword()); + EXPECT_FALSE(omnibox_view->model()->is_keyword_hint()); + EXPECT_EQ(omnibox_view->model()->keyword(), u""); // Trigger keyword mode. ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_TAB, 0)); - ASSERT_FALSE(omnibox_view->model()->is_keyword_hint()); - ASSERT_EQ(kSiteSearchPolicyKeywordWithAtPrefix, - omnibox_view->model()->keyword()); + EXPECT_FALSE(omnibox_view->model()->is_keyword_hint()); + EXPECT_EQ(omnibox_view->model()->keyword(), + kSiteSearchPolicyKeywordWithAtPrefix); // Input something as search text and perform a search. - ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchTextKeys)); + ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchTextKeys)); // ABC ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone()); - ASSERT_TRUE(omnibox_view->model()->PopupIsOpen()); + EXPECT_TRUE(omnibox_view->model()->PopupIsOpen()); - EXPECT_EQ(kSiteSearchPolicyTextURL, omnibox_view->controller() - ->autocomplete_controller() - ->result() - .default_match() - ->destination_url.spec()); + EXPECT_EQ(omnibox_view->controller() + ->autocomplete_controller() + ->result() + .default_match() + ->destination_url.spec(), + kSiteSearchPolicyTextURL); // ...?q=ABC } // Verifies that featured search engine is shown with starter pack on "@" state // and that the underlying search works. -IN_PROC_BROWSER_TEST_F(OmniboxViewTest, FeaturedOnArrowDown) { +IN_PROC_BROWSER_TEST_F(OmniboxViewTest, FeaturedPolicyKeywordArrowDown) { policy::PolicyMap policies; policies.Set(policy::key::kSiteSearchSettings, policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD, @@ -1597,20 +1598,21 @@ // Trigger keyword mode. ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_2, ui::EF_SHIFT_DOWN)); ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_DOWN, /*modifiers=*/0)); - ASSERT_FALSE(omnibox_view->model()->is_keyword_hint()); - ASSERT_EQ(kSiteSearchPolicyKeywordWithAtPrefix, - omnibox_view->model()->keyword()); + EXPECT_FALSE(omnibox_view->model()->is_keyword_hint()); + EXPECT_EQ(omnibox_view->model()->keyword(), + kSiteSearchPolicyKeywordWithAtPrefix); // Input something as search text and perform a search. ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchTextKeys)); ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone()); - ASSERT_TRUE(omnibox_view->model()->PopupIsOpen()); + EXPECT_TRUE(omnibox_view->model()->PopupIsOpen()); - EXPECT_EQ(kSiteSearchPolicyTextURL, omnibox_view->controller() - ->autocomplete_controller() - ->result() - .default_match() - ->destination_url.spec()); + EXPECT_EQ(omnibox_view->controller() + ->autocomplete_controller() + ->result() + .default_match() + ->destination_url.spec(), + kSiteSearchPolicyTextURL); } class SearchAggregatorPolicyOmniboxViewTest : public OmniboxViewTest { @@ -1671,24 +1673,25 @@ // Trigger keyword hint mode. ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchAggregatorPolicyKeywordKeys)); - ASSERT_TRUE(omnibox_view->model()->is_keyword_hint()); - ASSERT_EQ(kSearchAggregatorPolicyKeyword, omnibox_view->model()->keyword()); + EXPECT_TRUE(omnibox_view->model()->is_keyword_hint()); + EXPECT_EQ(omnibox_view->model()->keyword(), kSearchAggregatorPolicyKeyword); // Trigger keyword mode. ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_TAB, 0)); - ASSERT_FALSE(omnibox_view->model()->is_keyword_hint()); - ASSERT_EQ(kSearchAggregatorPolicyKeyword, omnibox_view->model()->keyword()); + EXPECT_FALSE(omnibox_view->model()->is_keyword_hint()); + EXPECT_EQ(omnibox_view->model()->keyword(), kSearchAggregatorPolicyKeyword); // Input something as search text and perform a search. ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchTextKeys)); ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone()); - ASSERT_TRUE(omnibox_view->model()->PopupIsOpen()); + EXPECT_TRUE(omnibox_view->model()->PopupIsOpen()); - EXPECT_EQ(kSearchAggregatorPolicyTextURL, omnibox_view->controller() - ->autocomplete_controller() - ->result() - .default_match() - ->destination_url.spec()); + EXPECT_EQ(omnibox_view->controller() + ->autocomplete_controller() + ->result() + .default_match() + ->destination_url.spec(), + kSearchAggregatorPolicyTextURL); } // Verifies that featured search engine is shown when @@ -1721,29 +1724,29 @@ EXPECT_FALSE(turl->safe_for_autoreplace()); EXPECT_TRUE(turl->featured_by_policy()); - // Trigger keyword hint mode. + // Type the keyword. ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_2, ui::EF_SHIFT_DOWN)); ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchAggregatorPolicyKeywordKeys)); - ASSERT_TRUE(omnibox_view->model()->is_keyword_hint()); - ASSERT_EQ(kSearchAggregatorPolicyKeywordWithAtPrefix, - omnibox_view->model()->keyword()); + EXPECT_FALSE(omnibox_view->model()->is_keyword_hint()); + EXPECT_EQ(omnibox_view->model()->keyword(), u""); // Trigger keyword mode. ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_TAB, 0)); - ASSERT_FALSE(omnibox_view->model()->is_keyword_hint()); - ASSERT_EQ(kSearchAggregatorPolicyKeywordWithAtPrefix, - omnibox_view->model()->keyword()); + EXPECT_FALSE(omnibox_view->model()->is_keyword_hint()); + EXPECT_EQ(omnibox_view->model()->keyword(), + kSearchAggregatorPolicyKeywordWithAtPrefix); // Input something as search text and perform a search. ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchTextKeys)); ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone()); - ASSERT_TRUE(omnibox_view->model()->PopupIsOpen()); + EXPECT_TRUE(omnibox_view->model()->PopupIsOpen()); - EXPECT_EQ(kSearchAggregatorPolicyTextURL, omnibox_view->controller() - ->autocomplete_controller() - ->result() - .default_match() - ->destination_url.spec()); + EXPECT_EQ(omnibox_view->controller() + ->autocomplete_controller() + ->result() + .default_match() + ->destination_url.spec(), + kSearchAggregatorPolicyTextURL); } // Verifies that featured search engine is shown with starter pack on "@" @@ -1781,20 +1784,21 @@ // Trigger keyword mode. ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_2, ui::EF_SHIFT_DOWN)); ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_TAB, 0)); - ASSERT_FALSE(omnibox_view->model()->is_keyword_hint()); - ASSERT_EQ(kSearchAggregatorPolicyKeywordWithAtPrefix, - omnibox_view->model()->keyword()); + EXPECT_FALSE(omnibox_view->model()->is_keyword_hint()); + EXPECT_EQ(omnibox_view->model()->keyword(), + kSearchAggregatorPolicyKeywordWithAtPrefix); // Input something as search text and perform a search. ASSERT_NO_FATAL_FAILURE(SendKeySequence(kSearchTextKeys)); ASSERT_NO_FATAL_FAILURE(WaitForAutocompleteControllerDone()); - ASSERT_TRUE(omnibox_view->model()->PopupIsOpen()); + EXPECT_TRUE(omnibox_view->model()->PopupIsOpen()); - EXPECT_EQ(kSearchAggregatorPolicyTextURL, omnibox_view->controller() - ->autocomplete_controller() - ->result() - .default_match() - ->destination_url.spec()); + EXPECT_EQ(omnibox_view->controller() + ->autocomplete_controller() + ->result() + .default_match() + ->destination_url.spec(), + kSearchAggregatorPolicyTextURL); } // Tests for IDN hostnames that contain deviation characters. See
diff --git a/chrome/browser/ui/views/frame/tab_strip_region_view.cc b/chrome/browser/ui/views/frame/tab_strip_region_view.cc index 27394f18..d22e2f58 100644 --- a/chrome/browser/ui/views/frame/tab_strip_region_view.cc +++ b/chrome/browser/ui/views/frame/tab_strip_region_view.cc
@@ -382,8 +382,12 @@ TabSearchButton* TabStripRegionView::GetTabSearchButton() { if (features::IsTabstripComboButtonEnabled()) { return tab_strip_combo_button_->tab_search_button(); - } else { + } else if (tab_search_container_) { + // tab_search_container_ may be null if browser is not TYPE_NORMAL or + // ShouldShowNewTabButton(browser) otherwise returns false. return tab_search_container_->tab_search_button(); + } else { + return nullptr; } }
diff --git a/chrome/browser/ui/views/frame/toolbar_button_provider.h b/chrome/browser/ui/views/frame/toolbar_button_provider.h index 4e8af782..92983f86b 100644 --- a/chrome/browser/ui/views/frame/toolbar_button_provider.h +++ b/chrome/browser/ui/views/frame/toolbar_button_provider.h
@@ -24,6 +24,10 @@ class Size; } // namespace gfx +namespace page_actions { +class PageActionView; +} // namespace page_actions + namespace views { class AccessiblePaneView; class View; @@ -47,6 +51,12 @@ virtual PageActionIconView* GetPageActionIconView( PageActionIconType type) = 0; + // Page actions are currently undergoing a migration. The following method + // should be used for the new path, and will eventually replace + // `GetPageActionIconView`. + virtual page_actions::PageActionView* GetPageActionView( + actions::ActionId action_id) = 0; + // Gets the app menu button. virtual AppMenuButton* GetAppMenuButton() = 0;
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 5325919..ebf977fb 100644 --- a/chrome/browser/ui/views/location_bar/location_bar_view.cc +++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -288,7 +288,11 @@ MerchantTrustServiceFactory::GetForProfile(profile_)); } - // Initialize the Omnibox view. + // Initialize the Omnibox view. browser_ can be nullptr on ChromeOS in the + // case of simple_web_view_dialog. Or it can be nulltpr on ChromeOS and on + // other desktop platforms in the case of presentation_receiver_window_view. + // See crbug.com/379534750. In other cases, browser_ can be nullptr but is + // limited to test environment. auto omnibox_view = std::make_unique<OmniboxViewViews>( std::make_unique<ChromeOmniboxClient>( /*location_bar=*/this, browser_, profile_),
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 121723d..f60a77c 100644 --- a/chrome/browser/ui/views/location_bar/location_bar_view.h +++ b/chrome/browser/ui/views/location_bar/location_bar_view.h
@@ -150,6 +150,10 @@ return page_action_icon_controller_; } + page_actions::PageActionContainerView* page_action_container() { + return page_action_container_; + } + // Returns the screen coordinates of the omnibox (where the URL text appears, // not where the icons are shown). gfx::Point GetOmniboxViewOrigin() const; @@ -259,6 +263,14 @@ // |is_hovering| should be true when mouse is in omnibox; false when exited. void OnOmniboxHovered(bool is_hovering); + // `browser_` returned here may be nullptr. There are two known cases. + // + // 1. simple_web_view_dialog, which is used to show captive portal page on + // signin screen on ChromeOS, passes in nullptr while constructing its + // location_bar_view_. See crbug.com/379534750. + // + // 2. presentation_receiver_window_view is the other known case. However, + // presentation_receiver_window_view is about to be sunsetted in a year or so. Browser* browser() { return browser_; } Profile* profile() { return profile_; }
diff --git a/chrome/browser/ui/views/omnibox/omnibox_match_cell_view.cc b/chrome/browser/ui/views/omnibox/omnibox_match_cell_view.cc index c046374..45ccb22 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_match_cell_view.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_match_cell_view.cc
@@ -356,8 +356,7 @@ const bool is_journeys_suggestion_row = match.type == AutocompleteMatchType::HISTORY_CLUSTER; const bool is_instant_keyword_row = - match.type == AutocompleteMatchType::STARTER_PACK || - match.type == AutocompleteMatchType::FEATURED_ENTERPRISE_SEARCH; + AutocompleteMatch::IsFeaturedSearchType(match.type); if (is_pedal_suggestion_row || is_journeys_suggestion_row || is_instant_keyword_row) { // When a PEDAL suggestion has been split out to its own row, apply a square
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc index 81dbc6a..5d55b9c 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
@@ -178,8 +178,10 @@ SetFontList(font_list); set_force_text_directionality(true); - // Unit tests may use a mock location bar that has no browser, - // or use no location bar at all. + // Unit tests may use a mock location bar that has no browser, or use no + // location bar at all. In addition, location bar may has no browser in + // production environment when constructed by simple_web_view_dialog or by + // presentation_receiver_window_view. See crbug.com/379534750. if (location_bar_view_ && location_bar_view_->browser()) { pref_change_registrar_.Init( location_bar_view_->browser()->profile()->GetPrefs()); @@ -433,10 +435,14 @@ // actually receives focus, ImmersiveFocusWatcher will add another lock to // keep it revealed. |location_bar_view_| can be nullptr in unit tests. // - // Besides tests, location bar is also used in non-browser UI (e.g. - // SimpleWebViewDialog and PresentationReceiverWindowView). Null check to - // avoid crash before these UIs are migrated away. - // See http://crbug.com/379534750 + // Besides tests, location bar is also used in non-browser UI in production + // enviroment. There are only two known case so far, one is + // simple_web_view_dialog for ChromeOS to draw captive portal during OOBE + // signin. The other one is presentation_receiver_window_view which applies to + // both ChromeOS and other desktop platforms. Null check to avoid crash before + // these UIs are migrated away. See crbug.com/379534750 for a production crash + // example. There is an effort to move simple_web_view_dialog away from + // location_bar_view and from this nullptr situation. std::unique_ptr<ImmersiveRevealedLock> focus_reveal_lock; if (location_bar_view_ && location_bar_view_->browser()) { focus_reveal_lock = @@ -1925,9 +1931,12 @@ IDS_CONTEXT_MENU_SHOW_FULL_URLS); } - // Location bar is also used in non-browser UI (e.g. SimpleWebViewDialog and - // PresentationReceiverWindowView). Null check to avoid crash before these - // UIs are migrated away. See http://crbug.com/379534750 + // Location bar is also used in non-browser UI in production enviroment. + // The only known case so far is simple_web_view_dialog for ChromeOS to draw + // captive portal during OOBE signin. Null check to avoid crash before these + // UIs are migrated away. See crbug.com/379534750 for a production crash + // example. There is an effort to move simple_web_view_dialog away from + // location_bar_view and from this nullptr situation. if (lens::features::IsOmniboxEntryPointEnabled() && location_bar_view_->browser() && location_bar_view_->browser()
diff --git a/chrome/browser/ui/views/page_action/page_action_container_view.cc b/chrome/browser/ui/views/page_action/page_action_container_view.cc index b5b2800..7376f77 100644 --- a/chrome/browser/ui/views/page_action/page_action_container_view.cc +++ b/chrome/browser/ui/views/page_action/page_action_container_view.cc
@@ -13,14 +13,12 @@ #include "ui/actions/actions.h" #include "ui/base/metadata/metadata_impl_macros.h" #include "ui/gfx/geometry/insets.h" -#include "ui/views/actions/action_view_controller.h" namespace page_actions { PageActionContainerView::PageActionContainerView( const std::vector<actions::ActionItem*>& action_items, - IconLabelBubbleView::Delegate* icon_view_delegate) - : action_view_controller_(std::make_unique<views::ActionViewController>()) { + IconLabelBubbleView::Delegate* icon_view_delegate) { SetBetweenChildSpacing(kPageActionBetweenIconSpacing); // Right align to clip the leftmost items first when not enough space. @@ -35,9 +33,6 @@ view->AddVisibleChangedCallback(base::BindRepeating( &PageActionContainerView::SetContainerInsideBorderInsets, base::Unretained(this)))); - - action_view_controller_->CreateActionViewRelationship( - view, action_item->GetAsWeakPtr()); } SetContainerInsideBorderInsets();
diff --git a/chrome/browser/ui/views/page_action/page_action_container_view.h b/chrome/browser/ui/views/page_action/page_action_container_view.h index 05cb9a9..dcac53b 100644 --- a/chrome/browser/ui/views/page_action/page_action_container_view.h +++ b/chrome/browser/ui/views/page_action/page_action_container_view.h
@@ -11,10 +11,6 @@ #include "chrome/browser/ui/views/location_bar/icon_label_bubble_view.h" #include "ui/views/layout/box_layout_view.h" -namespace views { -class ActionViewController; -} // namespace views - namespace page_actions { class PageActionController; @@ -53,7 +49,6 @@ void SetContainerInsideBorderInsets(); std::map<actions::ActionId, raw_ptr<PageActionView>> page_action_views_; - std::unique_ptr<views::ActionViewController> action_view_controller_; std::list<base::CallbackListSubscription> page_action_views_visible_subscriptions_; };
diff --git a/chrome/browser/ui/views/page_action/page_action_view.cc b/chrome/browser/ui/views/page_action/page_action_view.cc index ed84280a..74865cd 100644 --- a/chrome/browser/ui/views/page_action/page_action_view.cc +++ b/chrome/browser/ui/views/page_action/page_action_view.cc
@@ -63,12 +63,6 @@ SetVisible(false); } -std::unique_ptr<views::ActionViewInterface> -PageActionView::GetActionViewInterface() { - return std::make_unique<PageActionViewInterface>(this, - observation_.GetSource()); -} - actions::ActionId PageActionView::GetActionId() const { return action_item_->GetActionId().value(); } @@ -166,29 +160,4 @@ BEGIN_METADATA(PageActionView) END_METADATA -PageActionViewInterface::PageActionViewInterface(PageActionView* action_view, - PageActionModel* model) - : views::LabelButtonActionViewInterface(action_view), - action_view_(action_view), - model_(model) {} - -PageActionViewInterface::~PageActionViewInterface() = default; - -void PageActionViewInterface::ActionItemChangedImpl( - actions::ActionItem* action_item) { - // This method does nothing, because all ActionItem state is plumbed through - // PageActionController and PageActionModel. Doing so saves having to deal - // with conflicts (eg. ActionItem sets visibility, but PageActionController - // overrides it). -} - -// These methods do nothing because `PageActionView` needs to add the -// button trigger source (i.e, mouse, keyboard, gesture) to the action's -// invocation context. The current action-view framework does not support this, -// so the behaviour is implemented by `PageActionView`. -void PageActionViewInterface::InvokeActionImpl( - actions::ActionItem* action_item) {} -void PageActionViewInterface::LinkActionInvocationToView( - base::RepeatingClosure trigger_action_callback) {} - } // namespace page_actions
diff --git a/chrome/browser/ui/views/page_action/page_action_view.h b/chrome/browser/ui/views/page_action/page_action_view.h index b008760..05c6bc3 100644 --- a/chrome/browser/ui/views/page_action/page_action_view.h +++ b/chrome/browser/ui/views/page_action/page_action_view.h
@@ -29,8 +29,6 @@ PageActionView& operator=(const PageActionView&) = delete; ~PageActionView() override; - std::unique_ptr<views::ActionViewInterface> GetActionViewInterface() override; - // Sets the controller for this view, and attaches this view in the // controller. void OnNewActiveController(PageActionController* controller); @@ -72,27 +70,6 @@ base::CallbackListSubscription action_item_controller_subscription_; }; -// TODO(crbug.com/376285151): This class is overriding all of the behaviour -// from its base classes with stub implementations. `PageActionView` can now -// be disconnected from the ActionItem-View framework altogether. -class PageActionViewInterface : public views::LabelButtonActionViewInterface { - public: - explicit PageActionViewInterface(PageActionView* action_view, - PageActionModel* model); - PageActionViewInterface(const PageActionViewInterface&) = delete; - PageActionViewInterface& operator=(const PageActionViewInterface&) = delete; - ~PageActionViewInterface() override; - - void ActionItemChangedImpl(actions::ActionItem* action_item) override; - void InvokeActionImpl(actions::ActionItem* action_item) override; - void LinkActionInvocationToView( - base::RepeatingClosure trigger_action_callback) override; - - private: - raw_ptr<PageActionView> action_view_; - raw_ptr<PageActionModel> model_; -}; - } // namespace page_actions #endif // CHROME_BROWSER_UI_VIEWS_PAGE_ACTION_PAGE_ACTION_VIEW_H_
diff --git a/chrome/browser/ui/views/toolbar/BUILD.gn b/chrome/browser/ui/views/toolbar/BUILD.gn index 9373a80..6452830e 100644 --- a/chrome/browser/ui/views/toolbar/BUILD.gn +++ b/chrome/browser/ui/views/toolbar/BUILD.gn
@@ -126,6 +126,7 @@ "//chrome/browser/ui/tabs:tab_strip", "//chrome/browser/ui/tabs:tab_strip_model_observer", "//chrome/browser/ui/views/download", + "//chrome/browser/ui/views/page_action:page_action", "//chrome/browser/ui/views/side_panel:side_panel_enums", "//chrome/common:buildflags", "//chrome/common:chrome_features",
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.cc b/chrome/browser/ui/views/toolbar/toolbar_view.cc index 548dcae..7b6a5909 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_view.cc +++ b/chrome/browser/ui/views/toolbar/toolbar_view.cc
@@ -62,6 +62,7 @@ #include "chrome/browser/ui/views/location_bar/intent_chip_button.h" #include "chrome/browser/ui/views/location_bar/star_view.h" #include "chrome/browser/ui/views/media_router/cast_toolbar_button.h" +#include "chrome/browser/ui/views/page_action/page_action_container_view.h" #include "chrome/browser/ui/views/page_action/page_action_icon_container.h" #include "chrome/browser/ui/views/page_action/page_action_icon_controller.h" #include "chrome/browser/ui/views/performance_controls/battery_saver_button.h" @@ -1148,6 +1149,11 @@ return location_bar()->page_action_icon_controller()->GetIconView(type); } +page_actions::PageActionView* ToolbarView::GetPageActionView( + actions::ActionId action_id) { + return location_bar()->page_action_container()->GetPageActionView(action_id); +} + AppMenuButton* ToolbarView::GetAppMenuButton() { if (app_menu_button_) { return app_menu_button_;
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.h b/chrome/browser/ui/views/toolbar/toolbar_view.h index 82f032c2..02b81d4 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_view.h +++ b/chrome/browser/ui/views/toolbar/toolbar_view.h
@@ -64,6 +64,10 @@ class CastToolbarButton; } +namespace page_actions { +class PageActionView; +} // namespace page_actions + namespace send_tab_to_self { class SendTabToSelfToolbarIconView; } @@ -249,6 +253,8 @@ gfx::Size GetToolbarButtonSize() const override; views::View* GetDefaultExtensionDialogAnchorView() override; PageActionIconView* GetPageActionIconView(PageActionIconType type) override; + page_actions::PageActionView* GetPageActionView( + actions::ActionId action_id) override; AppMenuButton* GetAppMenuButton() override; gfx::Rect GetFindBarBoundingBox(int contents_bottom) override; void FocusToolbar() override;
diff --git a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_view.cc b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_view.cc index 787c910..c578484 100644 --- a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_view.cc +++ b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_view.cc
@@ -208,6 +208,13 @@ return right_container_->page_action_icon_controller()->GetIconView(type); } +page_actions::PageActionView* WebAppFrameToolbarView::GetPageActionView( + actions::ActionId action_id) { + // TODO(crbug.com/386376455): Return the appropriate view once web apps + // support the new Page Actions framework. + return nullptr; +} + AppMenuButton* WebAppFrameToolbarView::GetAppMenuButton() { return right_container_->web_app_menu_button(); }
diff --git a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_view.h b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_view.h index 9234c23f..38649ba 100644 --- a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_view.h +++ b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_view.h
@@ -22,6 +22,10 @@ class LocationBarViewQuietNotificationInteractiveUITest; } // namespace +namespace page_actions { +class PageActionView; +} // namespace page_actions + namespace views { class View; class ViewTargeterDelegate; @@ -75,6 +79,8 @@ gfx::Size GetToolbarButtonSize() const override; views::View* GetDefaultExtensionDialogAnchorView() override; PageActionIconView* GetPageActionIconView(PageActionIconType type) override; + page_actions::PageActionView* GetPageActionView( + actions::ActionId action_id) override; AppMenuButton* GetAppMenuButton() override; gfx::Rect GetFindBarBoundingBox(int contents_bottom) override; void FocusToolbar() override;
diff --git a/chrome/browser/ui/web_applications/navigation_capturing_information_forwarder.cc b/chrome/browser/ui/web_applications/navigation_capturing_information_forwarder.cc deleted file mode 100644 index 969f851..0000000 --- a/chrome/browser/ui/web_applications/navigation_capturing_information_forwarder.cc +++ /dev/null
@@ -1,51 +0,0 @@ -// Copyright 2024 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/web_applications/navigation_capturing_information_forwarder.h" - -#include "chrome/browser/ui/web_applications/navigation_capturing_navigation_handle_user_data.h" -#include "content/public/browser/web_contents.h" -#include "content/public/browser/web_contents_observer.h" -#include "content/public/browser/web_contents_user_data.h" -#include "ui/base/window_open_disposition.h" - -namespace web_app { - -NavigationCapturingInformationForwarder:: - ~NavigationCapturingInformationForwarder() = default; - -NavigationCapturingInformationForwarder:: - NavigationCapturingInformationForwarder( - content::WebContents* contents, - NavigationCapturingRedirectionInfo redirection_info, - std::optional<webapps::AppId> launched_app_id, - bool force_iph_off) - : content::WebContentsObserver(contents), - content::WebContentsUserData<NavigationCapturingInformationForwarder>( - *contents), - redirection_info_(std::move(redirection_info)), - launched_app_id_(std::move(launched_app_id)), - force_iph_off_(force_iph_off) {} - -void NavigationCapturingInformationForwarder::SelfDestruct() { - GetWebContents().RemoveUserData(UserDataKey()); -} - -void NavigationCapturingInformationForwarder::DidStartNavigation( - content::NavigationHandle* navigation_handle) { - web_app::NavigationCapturingNavigationHandleUserData:: - CreateForNavigationHandle(*navigation_handle, - std::move(redirection_info_), - std::move(launched_app_id_), force_iph_off_); - SelfDestruct(); -} - -void NavigationCapturingInformationForwarder::DidFinishNavigation( - content::NavigationHandle* navigation_handle) { - SelfDestruct(); -} - -WEB_CONTENTS_USER_DATA_KEY_IMPL(NavigationCapturingInformationForwarder); - -} // namespace web_app
diff --git a/chrome/browser/ui/web_applications/navigation_capturing_information_forwarder.h b/chrome/browser/ui/web_applications/navigation_capturing_information_forwarder.h deleted file mode 100644 index 6d85b461..0000000 --- a/chrome/browser/ui/web_applications/navigation_capturing_information_forwarder.h +++ /dev/null
@@ -1,57 +0,0 @@ -// Copyright 2024 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_WEB_APPLICATIONS_NAVIGATION_CAPTURING_INFORMATION_FORWARDER_H_ -#define CHROME_BROWSER_UI_WEB_APPLICATIONS_NAVIGATION_CAPTURING_INFORMATION_FORWARDER_H_ - -#include "chrome/browser/ui/web_applications/navigation_capturing_navigation_handle_user_data.h" -#include "content/public/browser/web_contents.h" -#include "content/public/browser/web_contents_observer.h" -#include "content/public/browser/web_contents_user_data.h" - -namespace content { -class WebContents; -class NavigationHandle; -} // namespace content - -namespace web_app { - -// An utility that holds information in a WebContents instance until it can be -// passed on to a NavigationHandle via -// `NavigationCapturingNavigationHandleUserData` to be used for handling -// navigations to be captured after redirected navigations. -class NavigationCapturingInformationForwarder - : public content::WebContentsObserver, - public content::WebContentsUserData< - NavigationCapturingInformationForwarder> { - public: - ~NavigationCapturingInformationForwarder() override; - // Deletes the current instance of `NavigationCapturingInformationForwarder` - // in the associated `WebContents`. - void SelfDestruct(); - - // content::WebContents overrides: - void DidStartNavigation( - content::NavigationHandle* navigation_handle) override; - void DidFinishNavigation( - content::NavigationHandle* navigation_handle) override; - - private: - NavigationCapturingInformationForwarder( - content::WebContents* contents, - NavigationCapturingRedirectionInfo redirection_info, - std::optional<webapps::AppId> launched_app_id, - bool force_iph_off); - friend WebContentsUserData; - - NavigationCapturingRedirectionInfo redirection_info_; - std::optional<webapps::AppId> launched_app_id_; - bool force_iph_off_; - - WEB_CONTENTS_USER_DATA_KEY_DECL(); -}; - -} // namespace web_app - -#endif // CHROME_BROWSER_UI_WEB_APPLICATIONS_NAVIGATION_CAPTURING_INFORMATION_FORWARDER_H_
diff --git a/chrome/browser/ui/web_applications/navigation_capturing_navigation_handle_user_data.cc b/chrome/browser/ui/web_applications/navigation_capturing_navigation_handle_user_data.cc deleted file mode 100644 index ea0a1e0..0000000 --- a/chrome/browser/ui/web_applications/navigation_capturing_navigation_handle_user_data.cc +++ /dev/null
@@ -1,216 +0,0 @@ -// Copyright 2024 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/web_applications/navigation_capturing_navigation_handle_user_data.h" - -#include "base/strings/to_string.h" -#include "chrome/browser/ui/browser_finder.h" -#include "chrome/browser/ui/web_applications/web_app_launch_utils.h" -#include "chrome/browser/web_applications/navigation_capturing_log.h" -#include "chrome/browser/web_applications/web_app_launch_params.h" -#include "chrome/browser/web_applications/web_app_provider.h" -#include "chrome/browser/web_applications/web_app_tab_helper.h" -#include "components/services/app_service/public/cpp/app_launch_util.h" -#include "content/public/browser/navigation_handle.h" -#include "content/public/browser/navigation_handle_user_data.h" -#include "third_party/blink/public/mojom/manifest/display_mode.mojom-shared.h" -#include "ui/base/window_open_disposition.h" - -namespace web_app { - -// static -NavigationCapturingRedirectionInfo -NavigationCapturingRedirectionInfo::Disabled() { - return NavigationCapturingRedirectionInfo( - /*source_browser_app_id=*/std::nullopt, - /* source_tab_app_id= */ std::nullopt, - NavigationHandlingInitialResult::kNotHandledByNavigationHandling, - /*first_navigation_app_id=*/std::nullopt, WindowOpenDisposition::UNKNOWN, - /*navigation_params_browser=*/nullptr); -} - -// static -NavigationCapturingRedirectionInfo -NavigationCapturingRedirectionInfo::AuxiliaryContext( - const std::optional<webapps::AppId>& source_browser_app_id, - const std::optional<webapps::AppId>& source_tab_app_id, - WindowOpenDisposition disposition) { - return NavigationCapturingRedirectionInfo( - source_browser_app_id, source_tab_app_id, - NavigationHandlingInitialResult::kAuxContext, - /*first_navigation_app_id=*/std::nullopt, disposition, - /*navigation_params_browser=*/nullptr); -} - -// Created for user-modified or capturable navigations that don't have an -// initial controlling app of the first url. -// static -NavigationCapturingRedirectionInfo -NavigationCapturingRedirectionInfo::NoInitialActionRedirectionHandlingEligible( - const std::optional<webapps::AppId>& source_browser_app_id, - const std::optional<webapps::AppId>& source_tab_app_id, - WindowOpenDisposition disposition, - Browser* navigation_params_browser) { - return NavigationCapturingRedirectionInfo( - source_browser_app_id, source_tab_app_id, - NavigationHandlingInitialResult::kBrowserTab, - /*first_navigation_app_id=*/std::nullopt, disposition, - navigation_params_browser); -} - -// static -NavigationCapturingRedirectionInfo -NavigationCapturingRedirectionInfo::ForcedNewContext( - const std::optional<webapps::AppId>& source_browser_app_id, - const std::optional<webapps::AppId>& source_tab_app_id, - const webapps::AppId& capturing_app_id, - blink::mojom::DisplayMode capturing_display_mode, - WindowOpenDisposition disposition, - Browser* navigation_params_browser) { - return NavigationCapturingRedirectionInfo( - source_browser_app_id, source_tab_app_id, - capturing_display_mode == blink::mojom::DisplayMode::kBrowser - ? NavigationHandlingInitialResult::kForcedNewAppContextBrowserTab - : NavigationHandlingInitialResult::kForcedNewAppContextAppWindow, - capturing_app_id, disposition, navigation_params_browser); -} - -// static -NavigationCapturingRedirectionInfo -NavigationCapturingRedirectionInfo::CapturedNewContext( - const std::optional<webapps::AppId>& source_browser_app_id, - const std::optional<webapps::AppId>& source_tab_app_id, - const webapps::AppId& capturing_app_id, - blink::mojom::DisplayMode capturing_display_mode, - WindowOpenDisposition disposition, - Browser* navigation_params_browser) { - return NavigationCapturingRedirectionInfo( - source_browser_app_id, source_tab_app_id, - capturing_display_mode == blink::mojom::DisplayMode::kBrowser - ? NavigationHandlingInitialResult::kNavigateCapturedNewBrowserTab - : NavigationHandlingInitialResult::kNavigateCapturedNewAppWindow, - capturing_app_id, disposition, navigation_params_browser); -} - -// static -NavigationCapturingRedirectionInfo -NavigationCapturingRedirectionInfo::CapturedNavigateExisting( - const std::optional<webapps::AppId>& source_browser_app_id, - const std::optional<webapps::AppId>& source_tab_app_id, - const webapps::AppId& capturing_app_id, - WindowOpenDisposition disposition, - Browser* navigation_params_browser) { - return NavigationCapturingRedirectionInfo( - source_browser_app_id, source_tab_app_id, - NavigationHandlingInitialResult::kNavigateCapturingNavigateExisting, - capturing_app_id, disposition, navigation_params_browser); -} - -NavigationCapturingRedirectionInfo::~NavigationCapturingRedirectionInfo() = - default; -NavigationCapturingRedirectionInfo::NavigationCapturingRedirectionInfo( - const NavigationCapturingRedirectionInfo& navigation_info) = default; -NavigationCapturingRedirectionInfo& -NavigationCapturingRedirectionInfo::operator=( - const NavigationCapturingRedirectionInfo&) = default; - -base::Value NavigationCapturingRedirectionInfo::ToDebugData() const { - return base::Value( - base::Value::Dict() - .Set("initial_nav_handling_result", - base::ToString(initial_nav_handling_result())) - .Set("source_browser_app_id", - source_browser_app_id().value_or("<none>")) - .Set("source_tab_app_id", source_tab_app_id().value_or("<none>")) - .Set("first_navigation_app_id", - first_navigation_app_id().value_or("<none>")) - .Set("disposition", base::ToString(disposition()))); -} - -NavigationCapturingRedirectionInfo::NavigationCapturingRedirectionInfo( - const std::optional<webapps::AppId>& source_browser_app_id, - const std::optional<webapps::AppId>& source_tab_app_id, - NavigationHandlingInitialResult initial_nav_handling_result, - const std::optional<webapps::AppId>& first_navigation_app_id, - WindowOpenDisposition disposition, - Browser* navigation_params_browser) - : source_browser_app_id_(source_browser_app_id), - source_tab_app_id_(source_tab_app_id), - initial_nav_handling_result_(initial_nav_handling_result), - first_navigation_app_id_(first_navigation_app_id), - disposition_(disposition), - navigation_params_browser_(navigation_params_browser) {} - -NavigationCapturingNavigationHandleUserData:: - ~NavigationCapturingNavigationHandleUserData() = default; - -NavigationCapturingNavigationHandleUserData:: - NavigationCapturingNavigationHandleUserData( - content::NavigationHandle& navigation_handle, - std::optional<NavigationCapturingRedirectionInfo> redirection_info, - std::optional<webapps::AppId> launched_app, - bool force_iph_off) - : navigation_handle_(navigation_handle), - redirection_info_(std::move(redirection_info)), - launched_app_(std::move(launched_app)), - force_iph_off_(force_iph_off) {} - -void NavigationCapturingNavigationHandleUserData::SetLaunchedAppState( - std::optional<webapps::AppId> launched_app, - bool force_iph_off) { - launched_app_ = launched_app; - force_iph_off_ = force_iph_off; -} - -void NavigationCapturingNavigationHandleUserData:: - MaybePerformAppHandlingTasksInWebContents() { - if (!launched_app_.has_value()) { - return; - } - - const webapps::AppId& app_id = *launched_app_; - content::WebContents* web_contents = navigation_handle_->GetWebContents(); - - EnqueueLaunchParams( - web_contents, app_id, navigation_handle_->GetURL(), - /*wait_for_navigation_to_complete=*/!navigation_handle_->HasCommitted()); - - WebAppTabHelper* tab_helper = WebAppTabHelper::FromWebContents(web_contents); - CHECK(tab_helper); - - apps::LaunchContainer container = - tab_helper->is_in_app_window() - ? apps::LaunchContainer::kLaunchContainerWindow - : apps::LaunchContainer::kLaunchContainerTab; - RecordLaunchMetrics(app_id, container, - apps::LaunchSource::kFromNavigationCapturing, - navigation_handle_->GetURL(), web_contents); - - WebAppProvider::GetForWebContents(web_contents) - ->navigation_capturing_log() - .StoreNavigationCapturedDebugData(ToDebugData()); - - if (!force_iph_off_) { - // TODO(crbug.com/371237535): Avoid reliance on FindBrowserWithTab and - // instead pass in the Browser instance earlier. - Browser* browser = chrome::FindBrowserWithTab(web_contents); - MaybeShowNavigationCaptureIph(app_id, browser->profile(), browser); - } -} - -base::Value NavigationCapturingNavigationHandleUserData::ToDebugData() const { - return base::Value( - base::Value::Dict() - .Set("launched_app", launched_app_.value_or("<none>")) - .Set("force_iph_off", force_iph_off_) - .Set("handle", - base::Value::Dict().Set( - "url", - navigation_handle_->GetURL().possibly_invalid_spec()))); -} - -NAVIGATION_HANDLE_USER_DATA_KEY_IMPL( - NavigationCapturingNavigationHandleUserData); - -} // namespace web_app
diff --git a/chrome/browser/ui/web_applications/navigation_capturing_navigation_handle_user_data.h b/chrome/browser/ui/web_applications/navigation_capturing_navigation_handle_user_data.h deleted file mode 100644 index 163095b..0000000 --- a/chrome/browser/ui/web_applications/navigation_capturing_navigation_handle_user_data.h +++ /dev/null
@@ -1,225 +0,0 @@ -// Copyright 2024 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_WEB_APPLICATIONS_NAVIGATION_CAPTURING_NAVIGATION_HANDLE_USER_DATA_H_ -#define CHROME_BROWSER_UI_WEB_APPLICATIONS_NAVIGATION_CAPTURING_NAVIGATION_HANDLE_USER_DATA_H_ - -#include <optional> - -#include "base/memory/raw_ptr.h" -#include "components/webapps/common/web_app_id.h" -#include "content/public/browser/navigation_handle_user_data.h" -#include "third_party/blink/public/mojom/manifest/display_mode.mojom-shared.h" -#include "ui/base/window_open_disposition.h" - -namespace base { -class Value; -} - -namespace content { -class NavigationHandle; -} // namespace content - -class Browser; - -namespace web_app { - -// TODO(crbug.com/336371044): Support web apps that open in a new tab. -// The initial result of navigation handling, stored as an enum to prevent -// transferring a `Browser` instance everywhere. -// Note: Apps can be configured to open in a browser tab or open in a standalone -// window. -enum class NavigationHandlingInitialResult { - // A browser tab was opened that wasn't the result of web app navigation - // capturing, but due to redirection the final behavior could change. - // Note: New context & capturable behavior for open-in-browser-tab apps apply - // to the cases below, and are not part of this category. - kBrowserTab = 0, - // The navigation was captured by an app and it resulted in the creation of a - // new app window for the navigation. This can only occur when the app opens - // in a standalone window. - kNavigateCapturedNewAppWindow = 1, - // The navigation was captured and it resulted in the creation of a new - // browser tab for the navigation. This can only occur when the app opens in a - // browser tab. - kNavigateCapturedNewBrowserTab = 2, - // The navigation was captured and it resulted in a existing web contents - // (either in an app window or browser tab) to be navigated. - kNavigateCapturingNavigateExisting = 3, - // The capturing logic forced this to launch the app in a new app window - // context, with the same behavior of `navigate-new`. This is used when it was - // a user-modified navigation, triggered by a shift or middle click. Launch - // parameters are enqueued. - kForcedNewAppContextAppWindow = 4, - // Same as above but for an app that opens in a browser tab. - kForcedNewAppContextBrowserTab = 5, - // The navigation open an auxiliary context, and thus the 'window container' - // (app or browser) needs to stay the same. - kAuxContext = 6, - // This navigation should be excluded from redirection handling. - kNotHandledByNavigationHandling = 7, - kMaxValue = kNotHandledByNavigationHandling -}; - -// Information that will be used to make decisions regarding redirection. -class NavigationCapturingRedirectionInfo { - public: - NavigationCapturingRedirectionInfo(const NavigationCapturingRedirectionInfo&); - NavigationCapturingRedirectionInfo& operator=( - const NavigationCapturingRedirectionInfo&); - - static NavigationCapturingRedirectionInfo Disabled(); - - static NavigationCapturingRedirectionInfo AuxiliaryContext( - const std::optional<webapps::AppId>& source_browser_app_id, - const std::optional<webapps::AppId>& source_tab_app_id, - WindowOpenDisposition disposition); - - // Created for user-modified or capturable navigations that don't have an - // initial controlling app of the first url. - static NavigationCapturingRedirectionInfo - NoInitialActionRedirectionHandlingEligible( - const std::optional<webapps::AppId>& source_browser_app_id, - const std::optional<webapps::AppId>& source_tab_app_id, - WindowOpenDisposition disposition, - Browser* navigation_params_browser); - - // Created for non-user modified navigations that usually launch a new app - // window. - static NavigationCapturingRedirectionInfo ForcedNewContext( - const std::optional<webapps::AppId>& source_browser_app_id, - const std::optional<webapps::AppId>& source_tab_app_id, - const webapps::AppId& capturing_app_id, - blink::mojom::DisplayMode capturing_display_mode, - WindowOpenDisposition disposition, - Browser* navigation_params_browser); - - // Created for non user modified navigations that result in a capturable - // navigation launching a new app container (window or tab). - static NavigationCapturingRedirectionInfo CapturedNewContext( - const std::optional<webapps::AppId>& source_browser_app_id, - const std::optional<webapps::AppId>& source_tab_app_id, - const webapps::AppId& capturing_app_id, - blink::mojom::DisplayMode capturing_display_mode, - WindowOpenDisposition disposition, - Browser* navigation_params_browser); - - // Created for non user modified navigations that result in a capturable - // navigation opening an existing app container (window or tab). This is - // triggered if there is a guarantee that an existing app container was - // already open for the controlling app. - static NavigationCapturingRedirectionInfo CapturedNavigateExisting( - const std::optional<webapps::AppId>& source_browser_app_id, - const std::optional<webapps::AppId>& source_tab_app_id, - const webapps::AppId& capturing_app_id, - WindowOpenDisposition disposition, - Browser* navigation_params_browser); - - ~NavigationCapturingRedirectionInfo(); - - // The initial result of navigation capturing on this navigation, on the - // initial url. - NavigationHandlingInitialResult initial_nav_handling_result() const { - return initial_nav_handling_result_; - } - - // If the navigation occurred in a standalone PWA window, then this is the - // app_id of that PWA. Otherwise this is `std::nullopt`. Note that this will - // be `std::nullopt` if the navigation came from a browser tab of an - // open-in-browser-tab app. - const std::optional<webapps::AppId>& source_browser_app_id() const { - return source_browser_app_id_; - } - - const std::optional<webapps::AppId>& source_tab_app_id() const { - return source_tab_app_id_; - } - - // The id of the capturing app_id of the first navigation, if this was - // captured or a forced new window. - // Note: This is currently not populated for aux context navigations, as it's - // not needed. - const std::optional<webapps::AppId>& first_navigation_app_id() const { - return first_navigation_app_id_; - } - - // The `WindowOpenDisposition` of the first navigation. - WindowOpenDisposition disposition() const { return disposition_; } - - Browser* navigation_params_browser() const { - return navigation_params_browser_; - } - - base::Value ToDebugData() const; - - private: - NavigationCapturingRedirectionInfo( - const std::optional<webapps::AppId>& source_browser_app_id, - const std::optional<webapps::AppId>& source_tab_app_id, - NavigationHandlingInitialResult initial_nav_handling_result, - const std::optional<webapps::AppId>& first_navigation_app_id, - WindowOpenDisposition disposition, - Browser* navigation_params_browser); - - std::optional<webapps::AppId> source_browser_app_id_; - std::optional<webapps::AppId> source_tab_app_id_; - NavigationHandlingInitialResult initial_nav_handling_result_ = - NavigationHandlingInitialResult::kBrowserTab; - std::optional<webapps::AppId> first_navigation_app_id_; - WindowOpenDisposition disposition_ = WindowOpenDisposition::UNKNOWN; - raw_ptr<Browser> navigation_params_browser_ = nullptr; -}; - -// Data that is tied to the NavigationHandle. Used in the -// `NavigationCapturingRedirectionThrottle` to make final decisions on what the -// outcome of navigation capturing on a redirected navigation should be. -class NavigationCapturingNavigationHandleUserData - : public content::NavigationHandleUserData< - NavigationCapturingNavigationHandleUserData> { - public: - ~NavigationCapturingNavigationHandleUserData() override; - - // Information necessary to perform different actions based on multiple - // redirects. - const std::optional<NavigationCapturingRedirectionInfo>& redirection_info() { - return redirection_info_; - } - - std::optional<webapps::AppId> launched_app() const { return launched_app_; } - - // Sets the `launched_app` as the id of the app that was/will be launched as a - // result of this navigation. Setting `force_iph_off` to `true` will prevent - // in-product-help from being displayed when it otherwise would. This is used - // by `MaybePerformAppHandlingTasksInWebContents` to decide if launch params, - // launch metrics and possible navigation capturing IPH need to be triggered. - void SetLaunchedAppState(std::optional<webapps::AppId> launched_app, - bool force_iph_off); - - // If this navigation triggered a web app launch, this method will queue - // launch params, record launch metrics and maybe show a navigation capturing - // IPH. Should be called when it is known that this navigation will commit. - void MaybePerformAppHandlingTasksInWebContents(); - - private: - NavigationCapturingNavigationHandleUserData( - content::NavigationHandle& navigation_handle, - std::optional<NavigationCapturingRedirectionInfo> redirection_info, - std::optional<webapps::AppId> launched_app, - bool force_iph_off); - - friend NavigationHandleUserData; - - base::Value ToDebugData() const; - - raw_ref<content::NavigationHandle> navigation_handle_; - std::optional<NavigationCapturingRedirectionInfo> redirection_info_; - std::optional<webapps::AppId> launched_app_; - bool force_iph_off_; - - NAVIGATION_HANDLE_USER_DATA_KEY_DECL(); -}; - -} // namespace web_app - -#endif // CHROME_BROWSER_UI_WEB_APPLICATIONS_NAVIGATION_CAPTURING_NAVIGATION_HANDLE_USER_DATA_H_
diff --git a/chrome/browser/ui/web_applications/navigation_capturing_process.cc b/chrome/browser/ui/web_applications/navigation_capturing_process.cc new file mode 100644 index 0000000..064f663 --- /dev/null +++ b/chrome/browser/ui/web_applications/navigation_capturing_process.cc
@@ -0,0 +1,1217 @@ +// Copyright 2025 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/web_applications/navigation_capturing_process.h" + +#include "base/feature_list.h" +#include "base/strings/string_split.h" +#include "base/types/optional_util.h" +#include "chrome/browser/apps/link_capturing/link_capturing_features.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_finder.h" +#include "chrome/browser/ui/browser_navigator_params.h" +#include "chrome/browser/ui/web_applications/app_browser_controller.h" +#include "chrome/browser/ui/web_applications/navigation_handle_user_data_forwarder.h" +#include "chrome/browser/ui/web_applications/web_app_browser_controller.h" +#include "chrome/browser/ui/web_applications/web_app_launch_navigation_handle_user_data.h" +#include "chrome/browser/ui/web_applications/web_app_launch_utils.h" +#include "chrome/browser/web_applications/navigation_capturing_log.h" +#include "chrome/browser/web_applications/web_app_helpers.h" +#include "chrome/browser/web_applications/web_app_provider.h" +#include "chrome/browser/web_applications/web_app_registrar.h" +#include "chrome/browser/web_applications/web_app_tab_helper.h" +#include "chrome/browser/web_applications/web_app_utils.h" +#include "content/public/common/content_features.h" + +#if BUILDFLAG(IS_CHROMEOS) +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/apps/app_service/launch_utils.h" +#include "chrome/browser/web_applications/chromeos_web_app_experiments.h" +#endif + +namespace web_app { + +using BrowserAndTabOverride = NavigationCapturingProcess::BrowserAndTabOverride; + +namespace { + +// Causes all new auxiliary browser contexts to share the same window container +// type as where they were created from. For example, if an aux context was +// created from standalone PWA, then the new context will be created in a new +// window of the same PWA. +// If this is off, then all auxiliary contexts will be created as browser tabs. +const base::FeatureParam<bool> kEnableAuxContextKeepSameContainer{ + &features::kPwaNavigationCapturing, "aux_context_keep_same_container", + /*default_value=*/false}; + +// Keeping auxiliary contexts in an 'app' container was causing problems on +// initial Canary testing, see https://crbug.com/379181271 for more information. +// Either this will be rolled out separately or removed. +bool ShouldDisableAuxiliaryBrowsingContextHandling( + const std::optional<webapps::AppId>& source_browser_app_id, + const GURL& url) { + // This is however needed on ChromeOS to support the ChromeOsWebAppExperiments + // code, see ChromeOsWebAppExperimentsNavigationBrowserTest for tests with + // this on. +#if BUILDFLAG(IS_CHROMEOS) + if (source_browser_app_id.has_value() && + ::web_app::ChromeOsWebAppExperiments:: + IsNavigationCapturingReimplEnabledForSourceApp(*source_browser_app_id, + url)) { + return true; + } +#endif + return apps::features::IsNavigationCapturingReimplEnabled() && + kEnableAuxContextKeepSameContainer.Get(); +} + +std::optional<webapps::AppId> GetWebAppControllingUrl( + Profile& profile, + const WebAppProvider* provider, + const GURL& url) { +#if BUILDFLAG(IS_CHROMEOS) + if (!apps::AppServiceProxyFactory::IsAppServiceAvailableForProfile( + &profile)) { + return std::nullopt; + } + return apps::FindAppIdsToLaunchForUrl( + apps::AppServiceProxyFactory::GetForProfile(&profile), url) + .preferred; +#else + return provider->registrar_unsafe().FindAppThatCapturesLinksInScope(url); +#endif +} + +bool IsDispositionValidForNavigationCapturing( + WindowOpenDisposition disposition) { + switch (disposition) { + case WindowOpenDisposition::NEW_FOREGROUND_TAB: + case WindowOpenDisposition::NEW_BACKGROUND_TAB: + case WindowOpenDisposition::NEW_WINDOW: + return true; + case WindowOpenDisposition::UNKNOWN: + // Note: App popups are handled in browser_navigator.cc + case WindowOpenDisposition::NEW_POPUP: + case WindowOpenDisposition::CURRENT_TAB: + case WindowOpenDisposition::SINGLETON_TAB: + case WindowOpenDisposition::SAVE_TO_DISK: + case WindowOpenDisposition::OFF_THE_RECORD: + case WindowOpenDisposition::IGNORE_ACTION: + case WindowOpenDisposition::SWITCH_TO_TAB: + case WindowOpenDisposition::NEW_PICTURE_IN_PICTURE: + return false; + } +} + +bool IsPageTransitionValidForNavigationCapturing( + ui::PageTransition transition) { + switch (ui::PageTransitionStripQualifier(transition)) { + case ui::PAGE_TRANSITION_TYPED: + case ui::PAGE_TRANSITION_AUTO_TOPLEVEL: + case ui::PAGE_TRANSITION_AUTO_BOOKMARK: + case ui::PAGE_TRANSITION_AUTO_SUBFRAME: + case ui::PAGE_TRANSITION_MANUAL_SUBFRAME: + case ui::PAGE_TRANSITION_GENERATED: + case ui::PAGE_TRANSITION_RELOAD: + case ui::PAGE_TRANSITION_KEYWORD: + case ui::PAGE_TRANSITION_KEYWORD_GENERATED: + return false; + case ui::PAGE_TRANSITION_LINK: + case ui::PAGE_TRANSITION_FORM_SUBMIT: + break; + default: + NOTREACHED(base::NotFatalUntil::M135); + } + if (base::to_underlying(ui::PageTransitionGetQualifier(transition)) != 0) { + // Qualifiers indicate that this navigation was the result of a click on a + // forward/back button, typing in the URL bar, or client-side redirections. + // Don't handle any of those types of navigations. + return false; + } + return true; +} + +bool IsServiceWorkerClientOpenNavigation(const NavigateParams& params) { + return params.open_pwa_window_if_possible && + ui::PageTransitionCoreTypeIs(params.transition, + ui::PAGE_TRANSITION_AUTO_TOPLEVEL) && + params.disposition == WindowOpenDisposition::NEW_FOREGROUND_TAB; +} + +// Returns true if an auxiliary browsing context is getting created, so +// navigation should be done in the same container that it was triggered in. +bool IsAuxiliaryBrowsingContext(const NavigateParams& nav_params) { + if ((nav_params.contents_to_insert && + nav_params.contents_to_insert->HasOpener()) || + nav_params.opener) { + return true; + } + return false; +} + +Browser* CreateWebAppWindowFromNavigationParams( + const webapps::AppId& app_id, + const NavigateParams& navigate_params, + bool should_create_app_popup = false) { + Browser::CreateParams app_browser_params = CreateParamsForApp( + app_id, should_create_app_popup, navigate_params.trusted_source, + navigate_params.window_features.bounds, + navigate_params.initiating_profile, navigate_params.user_gesture); + Browser* created_browser = + CreateWebAppWindowMaybeWithHomeTab(app_id, app_browser_params); + return created_browser; +} + +// TODO(crbug.com/371237535): Move to TabInterface once there is support for +// getting the browser interface for web contents that are in an app window. +// For all use-cases where a reparenting to an app window happens, launch params +// need to be enqueued so as to mimic the pre redirection behavior. See +// https://bit.ly/pwa-navigation-capturing?tab=t.0#bookmark=id.60x2trlfg6iq for +// more information. +void ReparentToAppBrowser(content::WebContents* old_web_contents, + const webapps::AppId& app_id, + const GURL& target_url) { + Browser* main_browser = chrome::FindBrowserWithTab(old_web_contents); + Browser* target_browser = CreateWebAppWindowMaybeWithHomeTab( + app_id, CreateParamsForApp( + app_id, /*is_popup=*/false, /*trusted_source=*/true, + gfx::Rect(), main_browser->profile(), /*user_gesture=*/true)); + CHECK(target_browser->app_controller()); + ReparentWebContentsIntoBrowserImpl( + main_browser, old_web_contents, target_browser, + target_browser->app_controller()->IsUrlInHomeTabScope(target_url)); + CHECK(old_web_contents); +} + +// TODO(crbug.com/371237535): Move to TabInterface once there is support for +// getting the browser interface for web contents that are in an app window. +void ReparentWebContentsToTabbedBrowser(content::WebContents* old_web_contents, + WindowOpenDisposition disposition, + Browser* navigate_params_browser) { + Browser* source_browser = chrome::FindBrowserWithTab(old_web_contents); + Browser* existing_browser_window = + navigate_params_browser && + !AppBrowserController::IsWebApp(navigate_params_browser) + ? navigate_params_browser + : chrome::FindTabbedBrowser(source_browser->profile(), + /*match_original_profiles=*/false); + + // Create a new browser window if the navigation was triggered via a + // shift-click, or if there are no open tabbed browser windows at the moment. + Browser* target_browser_window = + (disposition == WindowOpenDisposition::NEW_WINDOW || + !existing_browser_window) + ? Browser::Create(Browser::CreateParams(source_browser->profile(), + /*user_gesture=*/true)) + : existing_browser_window; + + ReparentWebContentsIntoBrowserImpl(source_browser, old_web_contents, + target_browser_window); +} + +} // namespace + +// static +std::unique_ptr<NavigationCapturingProcess> +NavigationCapturingProcess::MaybeHandleAppNavigation( + const NavigateParams& params) { + Profile* profile = params.initiating_profile; + if (!AreWebAppsUserInstallable(profile) || + Browser::GetCreationStatusForProfile(profile) != + Browser::CreationStatus::kOk || + !params.url.is_valid()) { + return nullptr; + } + + web_app::WebAppProvider* provider = + web_app::WebAppProvider::GetForWebApps(profile); + if (!provider) { + return nullptr; + } + + auto result = base::WrapUnique(new NavigationCapturingProcess(params)); + // The `open_pwa_window_if_possible` flag is implemented in navigation + // capturing logic, even if otherwise the reimpl experiment isn't enabled. + if (!result->IsNavigationCapturingReimplExperimentEnabled() && + !params.open_pwa_window_if_possible) { + // Don't record debug information for ALL navigations unless expensive + // DCHECKs are enabled. +#if !EXPENSIVE_DCHECKS_ARE_ON() + result->debug_data_.clear(); +#endif + return nullptr; + } + return result; +} + +NavigationCapturingProcess::NavigationCapturingProcess( + const NavigateParams& params) + : profile_(raw_ref<Profile>::from_ptr(params.initiating_profile)), + source_browser_app_id_( + params.browser && + web_app::AppBrowserController::IsWebApp(params.browser) + ? std::optional(params.browser->app_controller()->app_id()) + : std::nullopt), + source_tab_app_id_(params.source_contents + ? base::OptionalFromPtr(WebAppTabHelper::GetAppId( + params.source_contents)) + : std::nullopt), + navigation_params_url_(params.url), + disposition_(params.disposition), + navigation_params_browser_(params.browser.get()) { + CHECK(AreWebAppsUserInstallable(&*profile_)); + CHECK(params.url.is_valid()); + + WebAppProvider* provider = WebAppProvider::GetForWebApps(&*profile_); + CHECK(provider); + web_app::WebAppRegistrar& registrar = provider->registrar_unsafe(); + + debug_data_.Set("referrer.url", params.referrer.url.possibly_invalid_spec()); + debug_data_.Set("source_contents.url", + params.source_contents + ? params.source_contents->GetLastCommittedURL() + .possibly_invalid_spec() + : "<nullptr>"); + debug_data_.Set("source_contents.app_id", + source_tab_app_id_.value_or("<none>")); + debug_data_.Set("params.browser", base::ToString(params.browser.get())); + + debug_data_.Set("params.url", params.url.possibly_invalid_spec()); + debug_data_.Set("params.disposition", base::ToString(params.disposition)); + debug_data_.Set("params.opener", params.opener != nullptr); + debug_data_.Set("params.contents_to_insert", + base::ToString(params.contents_to_insert.get())); + debug_data_.Set("source_browser_app_id", + source_browser_app_id_.value_or("<none>")); + debug_data_.Set("params.transition", + ui::PageTransitionGetCoreTransitionString( + ui::PageTransitionStripQualifier(params.transition))); + debug_data_.Set( + "params.transition.qualifiers", + static_cast<int>(ui::PageTransitionGetQualifier(params.transition))); + debug_data_.Set("is_user_modified_click", is_user_modified_click()); + + first_navigation_app_id_ = + GetWebAppControllingUrl(profile_.get(), provider, params.url); + debug_data_.Set("controlling_app_id", + first_navigation_app_id_.value_or("<none>")); + if (first_navigation_app_id_) { + first_navigation_app_display_mode_ = + registrar.GetAppEffectiveDisplayMode(*first_navigation_app_id_); + debug_data_.Set("controlling_app_display_mode", + base::ToString(*first_navigation_app_display_mode_)); + } +} + +NavigationCapturingProcess::~NavigationCapturingProcess() { + if (!debug_data_.empty()) { + WebAppProvider* provider = WebAppProvider::GetForWebApps(&*profile_); + provider->navigation_capturing_log().StoreNavigationCapturedDebugData( + base::Value(std::move(debug_data_))); + } +} + +// static +void NavigationCapturingProcess::AttachToNavigationHandle( + content::NavigationHandle& navigation_handle, + std::unique_ptr<NavigationCapturingProcess> user_data) { + if (user_data->initial_nav_handling_result_ == + InitialResult::kNotHandledByNavigationHandling) { + return; + } + CHECK(!user_data->navigation_handle_); + user_data->navigation_handle_ = &navigation_handle; + CHECK(user_data->state_ == PipelineState::kInitialOverrideCalculated || + user_data->state_ == PipelineState::kAttachedToWebContents); + user_data->state_ = PipelineState::kAttachedToNavigationHandle; + user_data->OnAttachedToNavigationHandle(); + navigation_handle.SetUserData(UserDataKey(), std::move(user_data)); +} + +// static +void NavigationCapturingProcess::AttachToNextNavigationInWebContents( + content::WebContents& web_contents, + std::unique_ptr<NavigationCapturingProcess> user_data) { + if (user_data->initial_nav_handling_result_ == + InitialResult::kNotHandledByNavigationHandling) { + return; + } + CHECK_EQ(user_data->state_, PipelineState::kInitialOverrideCalculated); + user_data->state_ = PipelineState::kAttachedToWebContents; + // If there already is a user data with the same user data key attached to the + // web contents, we want to overwrite that user data to make sure the newest + // process gets attached to the next navigation. As such we don't check for + // existing user data. + web_contents.SetUserData( + UserDataKey(), + std::make_unique< + NavigationHandleUserDataForwarder<NavigationCapturingProcess>>( + web_contents, std::move(user_data))); +} + +BrowserAndTabOverride +NavigationCapturingProcess::GetInitialBrowserAndTabOverrideForNavigation( + const NavigateParams& params) { + CHECK(AreWebAppsUserInstallable(&*profile_)); + CHECK(params.url.is_valid()); + CHECK_EQ(state_, PipelineState::kCreated); + + WebAppProvider* provider = WebAppProvider::GetForWebApps(&*profile_); + CHECK(provider); + web_app::WebAppRegistrar& registrar = provider->registrar_unsafe(); + + // Only proceed as below if the navigation capturing is enabled. The flag in + // the redirection info has to store the result of this check, so that the + // logic in `OnWebAppNavigationAfterWebContentsCreation()` is skipped when not + // needed. + bool navigation_capturing_enabled = + IsNavigationCapturingReimplExperimentEnabled(); + bool is_service_worker_clients_open_window = + IsServiceWorkerClientOpenNavigation(params); + + // TODO(https://crbug.com/382542907): Remove `open_pwa_window_if_possible` or + // make it IWA-specific. + bool is_service_worker_clients_open_window_with_nav_capturing = + is_service_worker_clients_open_window && navigation_capturing_enabled; + if (params.open_pwa_window_if_possible && + (!is_service_worker_clients_open_window_with_nav_capturing || + params.force_open_pwa_window)) { + std::optional<webapps::AppId> app_id = + web_app::FindInstalledAppWithUrlInScope(&*profile_, params.url, + /*window_only=*/true); + if (!app_id && params.force_open_pwa_window) { + // In theory |force_open_pwa_window| should only be set if we know a + // matching PWA is installed. However, we can reach here if + // `WebAppRegistrar` hasn't finished starting yet, which can happen if + // Chrome is launched with the URL of an isolated app as an argument. + // This isn't a supported way to launch isolated apps, so we can cancel + // the navigation, but if we want to support it in the future we'll need + // to block until `WebAppRegistrar` is loaded. + return CancelInitialNavigation(); + } + if (app_id) { + // Reuse the existing browser for in-app same window navigations. + bool navigating_same_app = + params.browser && + web_app::AppBrowserController::IsForWebApp(params.browser, *app_id); + if (navigating_same_app) { + if (disposition_ == WindowOpenDisposition::CURRENT_TAB) { + return NoCapturingOverrideBrowser(params.browser); + } + + // If the browser window does not yet have any tabs, and we are + // attempting to add the first tab to it, allow for it to be reused. + bool navigating_new_tab = + disposition_ == WindowOpenDisposition::NEW_FOREGROUND_TAB || + disposition_ == WindowOpenDisposition::NEW_BACKGROUND_TAB; + bool browser_has_no_tabs = + params.browser && params.browser->tab_strip_model()->empty(); + if (navigating_new_tab && browser_has_no_tabs) { + return NoCapturingOverrideBrowser(params.browser); + } + } + + auto GetOriginSpecified = [](const NavigateParams& params) { + return params.window_features.has_x && params.window_features.has_y + ? Browser::ValueSpecified::kSpecified + : Browser::ValueSpecified::kUnspecified; + }; + + // App popups are handled in the switch statement in + // `GetBrowserAndTabForDisposition()`. + if (disposition_ == WindowOpenDisposition::NEW_POPUP) { + return CapturingDisabled(); + } + std::string app_name = web_app::GenerateApplicationNameFromAppId(*app_id); + // Installed PWAs are considered trusted. + Browser::CreateParams browser_params = + Browser::CreateParams::CreateForApp(app_name, /*trusted_source=*/true, + params.window_features.bounds, + &*profile_, params.user_gesture); + browser_params.initial_origin_specified = GetOriginSpecified(params); + Browser* browser = Browser::Create(browser_params); + return NoCapturingOverrideBrowser(browser); + } + } + + // Below here handles the states outlined in + // https://bit.ly/pwa-navigation-capturing + if (!navigation_capturing_enabled) { + return CapturingDisabled(); + } + if (params.started_from_context_menu || + params.pwa_navigation_capturing_force_off || + params.tabstrip_index != -1) { + return CapturingDisabled(); + } + if (!IsDispositionValidForNavigationCapturing(disposition_)) { + return CapturingDisabled(); + } + + // The service worker clients API currently uses + // PAGE_TRANSITION_AUTO_TOPLEVEL, which is normally considered invalid for + // navigation capturing. Explicitly allow that. + if (!is_service_worker_clients_open_window && + !IsPageTransitionValidForNavigationCapturing(params.transition)) { + return CapturingDisabled(); + } + bool is_for_new_browser = + params.browser && params.browser->tab_strip_model()->count() == 0 && + (disposition_ == WindowOpenDisposition::NEW_FOREGROUND_TAB || + disposition_ == WindowOpenDisposition::NEW_BACKGROUND_TAB); + if (is_for_new_browser) { + // Some calls to `Navigate` populate a newly created browser in + // `params.browser`, with no tabs. Callers can assume that browser is used, + // so enabling capturing cause the user to see a browser with no tabs. We + // cannot simply close it, as sometimes callers then use/reference that + // browser. While that is likely a bug (callers should use the + // `params.browser` to be compatible with other logic that changes the + // browser), disable capturing in this case for now. + return CapturingDisabled(); + } + + // Ensure that we proceed for a `first_navigation_app_display_mode_` to be + // navigation captured only for the use-cases that are supported. + if (first_navigation_app_display_mode_) { + CHECK(WebAppRegistrar::IsSupportedDisplayModeForNavigationCapture( + *first_navigation_app_display_mode_)); + } + + std::optional<ClientModeAndBrowser> client_mode_and_browser; + if (first_navigation_app_id_) { + client_mode_and_browser = GetEffectiveClientModeAndBrowserForCapturing( + *profile_, *first_navigation_app_id_, source_tab_app_id_, + /*ignore_browser_tabs_for_standalone_apps=*/false, + /*navigate_params_requested_browser=*/params.browser); + debug_data_.Set( + "effective_client_mode", + base::ToString(client_mode_and_browser->effective_client_mode)); + CHECK(client_mode_and_browser->effective_client_mode != + LaunchHandler::ClientMode::kAuto); + debug_data_.Set("controlling_app_host_browser", + client_mode_and_browser->browser + ? base::ToString(client_mode_and_browser->browser) + : "<none>"); + debug_data_.Set("controlling_app_host_tab", + client_mode_and_browser->tab_index.has_value() + ? base::ToString(*client_mode_and_browser->tab_index) + : "<none>"); + } + + // Case: Any click (user modified or non-modified) with auxiliary browsing + // context. Only needs to be handled if it is triggered in the context of an + // app browser. + if (IsAuxiliaryBrowsingContext(params)) { + debug_data_.Set("is_auxiliary_browsing_context", true); + if (!ShouldDisableAuxiliaryBrowsingContextHandling(source_browser_app_id_, + params.url)) { + return CapturingDisabled(); + } + if (source_browser_app_id_.has_value()) { + Browser* app_window = CreateWebAppWindowFromNavigationParams( + *source_browser_app_id_, params, + disposition_ == WindowOpenDisposition::NEW_POPUP); + + return AuxiliaryContextInAppWindow(app_window); + } + return AuxiliaryContext(); + } + debug_data_.Set("is_auxiliary_browsing_context", false); + + // If no app controls the the target url, then there cannot be any further + // capturing logic unless a redirect occurs. + if (!first_navigation_app_id_) { + return NoInitialActionRedirectionHandlingEligible(); + } + CHECK(first_navigation_app_display_mode_); + CHECK(client_mode_and_browser); + const webapps::AppId& app_id = *first_navigation_app_id_; + blink::mojom::DisplayMode app_display_mode = + *first_navigation_app_display_mode_; + LaunchHandler::ClientMode client_mode = + client_mode_and_browser->effective_client_mode; + + // Case: User-modified clicks. + if (is_user_modified_click()) { + // The default behavior is only modified if the source is an app browser or + // the controlling app's display mode is 'browser'. + if (!source_browser_app_id_.has_value() && + app_display_mode != DisplayMode::kBrowser) { + return NoInitialActionRedirectionHandlingEligible(); + } + // Case: Shift-clicks with a new top level browsing context. + if (disposition_ == WindowOpenDisposition::NEW_WINDOW) { + Browser* app_host_window; + if (app_display_mode == DisplayMode::kBrowser) { + app_host_window = Browser::Create( + Browser::CreateParams(&*profile_, params.user_gesture)); + } else { + app_host_window = + CreateWebAppWindowFromNavigationParams(app_id, params); + } + return ForcedNewAppContext(app_display_mode, app_host_window); + } + + bool is_in_source_app_with_url_in_scope = + source_browser_app_id_ + ? registrar.IsUrlInAppScope(params.url, *source_browser_app_id_) + : false; + + // Case: Middle clicks with a new top level browsing context. + if (disposition_ == WindowOpenDisposition::NEW_BACKGROUND_TAB && + (app_display_mode == DisplayMode::kBrowser || + (app_id == source_browser_app_id_ && + is_in_source_app_with_url_in_scope))) { + if (source_browser_app_id_.has_value() && + !params.browser->app_controller()->ShouldHideNewTabButton()) { + // Apps that support tabbed mode can open a new tab in the current app + // browser itself. + return ForcedNewAppContext(app_display_mode, params.browser); + } + Browser* app_host_window; + if (app_display_mode == DisplayMode::kBrowser) { + // For a 'new tab' with the 'browser' requested display mode, prefer + // using an existing browser window. + app_host_window = client_mode_and_browser->browser + ? client_mode_and_browser->browser.get() + : Browser::Create(Browser::CreateParams( + &*profile_, params.user_gesture)); + } else { + app_host_window = + CreateWebAppWindowFromNavigationParams(app_id, params); + } + return ForcedNewAppContext(app_display_mode, app_host_window); + } + return NoInitialActionRedirectionHandlingEligible(); + } + + if (disposition_ != WindowOpenDisposition::NEW_FOREGROUND_TAB) { + return CapturingDisabled(); + } + + // Case: Left click, non-user-modified. Capturable. + + // Opening in non-browser-tab requires OS integration. Since os integration + // cannot be triggered synchronously, treat this as opening in browser. + if (registrar.GetInstallState(app_id) == + proto::INSTALLED_WITHOUT_OS_INTEGRATION) { + app_display_mode = blink::mojom::DisplayMode::kBrowser; + } + + // Prevent-close requires only focusing the existing tab, and never + // navigating. + if (registrar.IsPreventCloseEnabled(app_id) && + !registrar.IsTabbedWindowModeEnabled(app_id)) { + client_mode = LaunchHandler::ClientMode::kFocusExisting; + } + debug_data_.Set("client_mode", base::ToString(client_mode)); + + // Focus existing. + if (client_mode == LaunchHandler::ClientMode::kFocusExisting) { + CHECK(client_mode_and_browser->browser); + CHECK(client_mode_and_browser->tab_index.has_value()); + CHECK_NE(*client_mode_and_browser->tab_index, -1); + content::WebContents* contents = + client_mode_and_browser->browser->tab_strip_model()->GetWebContentsAt( + *client_mode_and_browser->tab_index); + CHECK(contents); + FocusAppContainer(client_mode_and_browser->browser, + *client_mode_and_browser->tab_index); + + // Abort the navigation by returning a `nullptr`. Because this means + // `OnWebAppNavigationAfterWebContentsCreation` won't be called, enqueue + // the launch params instantly and record the debug data. + EnqueueLaunchParams(contents, app_id, params.url, + /*wait_for_navigation_to_complete=*/false); + + MaybeShowNavigationCaptureIph(app_id, &*profile_, + client_mode_and_browser->browser); + + // TODO(crbug.com/336371044): Update RecordLaunchMetrics() to also work + // with apps that open in a new browser tab. + RecordLaunchMetrics(app_id, apps::LaunchContainer::kLaunchContainerWindow, + apps::LaunchSource::kFromNavigationCapturing, + params.url, contents); + return CancelInitialNavigation(); + } + + // Navigate existing. + if (client_mode == LaunchHandler::ClientMode::kNavigateExisting) { + CHECK(client_mode_and_browser->browser); + CHECK(client_mode_and_browser->tab_index.has_value()); + return CapturedNavigateExisting(client_mode_and_browser->browser, + *client_mode_and_browser->tab_index); + } + + // Navigate new. + CHECK(client_mode == LaunchHandler::ClientMode::kNavigateNew); + + Browser* host_window = nullptr; + switch (app_display_mode) { + case blink::mojom::DisplayMode::kBrowser: + if (client_mode_and_browser->browser) { + host_window = client_mode_and_browser->browser; + } else { + host_window = Browser::Create( + Browser::CreateParams(&*profile_, params.user_gesture)); + } + break; + case blink::mojom::DisplayMode::kMinimalUi: + case blink::mojom::DisplayMode::kStandalone: + case blink::mojom::DisplayMode::kWindowControlsOverlay: + case blink::mojom::DisplayMode::kBorderless: + host_window = CreateWebAppWindowFromNavigationParams(app_id, params); + break; + case blink::mojom::DisplayMode::kTabbed: + if (client_mode_and_browser->browser) { + host_window = client_mode_and_browser->browser; + } else { + host_window = CreateWebAppWindowFromNavigationParams(app_id, params); + } + break; + case blink::mojom::DisplayMode::kUndefined: + case blink::mojom::DisplayMode::kPictureInPicture: + case blink::mojom::DisplayMode::kFullscreen: + NOTREACHED(); + } + + return CapturedNewClient(app_display_mode, host_window); +} + +// static +void NavigationCapturingProcess::AfterWebContentsCreation( + std::unique_ptr<NavigationCapturingProcess> process, + content::WebContents& web_contents, + content::NavigationHandle* navigation_handle) { + if (navigation_handle) { + AttachToNavigationHandle(*navigation_handle, std::move(process)); + } else { + AttachToNextNavigationInWebContents(web_contents, std::move(process)); + } +} + +NavigationCapturingProcess::ThrottleCheckResult +NavigationCapturingProcess::HandleRedirect() { + CHECK(navigation_handle()); + CHECK_EQ(state_, PipelineState::kAttachedToNavigationHandle); + state_ = PipelineState::kFinished; + + // See https://bit.ly/pwa-navigation-capturing and + // https://bit.ly/pwa-navigation-handling-dd for more context. + // Exit early if: + // 1. If there were no redirects, then the only url in the redirect chain + // should be the last url to go to. + // 2. This is not a server side redirect. + // 3. The navigation was started from the context menu. + if (navigation_handle()->GetRedirectChain().size() == 1 || + !navigation_handle()->WasServerRedirect() || + (navigation_handle()->WasStartedFromContextMenu())) { + return content::NavigationThrottle::PROCEED; + } + const GURL& final_url = navigation_handle()->GetURL(); + if (!final_url.is_valid()) { + return content::NavigationThrottle::PROCEED; + } + + // Do not handle redirections for navigations that create an auxiliary + // browsing context, or if the app window that opened is not a part of the + // navigation handling flow. + if (initial_nav_handling_result_ == + InitialResult::kNotHandledByNavigationHandling || + initial_nav_handling_result_ == InitialResult::kAuxContext) { + return content::NavigationThrottle::PROCEED; + } + + content::WebContents* const web_contents_for_navigation = + navigation_handle()->GetWebContents(); + + WebAppProvider* provider = + WebAppProvider::GetForWebContents(web_contents_for_navigation); + WebAppRegistrar& registrar = provider->registrar_unsafe(); + std::optional<webapps::AppId> target_app_id = + GetWebAppControllingUrl(profile_.get(), provider, final_url); + + // "Same first navigation state" case: + // First, we can exit early if the first navigation app id matches the target + // app id (which includes if they are both std::nullopt), as this means we + // already did the 'correct' navigation capturing behavior on the first + // navigation. + if (first_navigation_app_id_ == target_app_id) { + return content::NavigationThrottle::PROCEED; + } + + // Clear out the "launch app id" field. This way we ensure that in any branch + // where the redirect does not result in an app being launched we don't + // accidentally (try to) treat it as a launch. Any branch where an app launch + // does happen will re-set the field to the correct value. + SetLaunchedAppId({}); + + // After this point: + // - The browsing context is a top-level browsing context. + // - The initial navigation capturing app_id does not match the final + // target_app_id (and either can be std::nullopt, but not both). + // - Navigation is only triggered as part of left, middle or shift clicks. + + bool is_source_app_matching_final_target = + target_app_id == source_browser_app_id_; + + // First, handle cases where the final url is not in scope of any app. These + // can mostly proceed as is, except for two cases where the initial navigation + // ended up in an app window but should now be in a browser tab. + if (!target_app_id.has_value()) { + if (initial_nav_handling_result_ == + InitialResult::kForcedNewAppContextAppWindow || + initial_nav_handling_result_ == + InitialResult::kNavigateCapturedNewAppWindow) { + ReparentWebContentsToTabbedBrowser(web_contents_for_navigation, + disposition_, + navigation_params_browser_); + } + return content::NavigationThrottle::PROCEED; + } + + blink::mojom::DisplayMode target_display_mode = + registrar.GetAppEffectiveDisplayMode(*target_app_id); + CHECK(WebAppRegistrar::IsSupportedDisplayModeForNavigationCapture( + target_display_mode)); + + // For the remaining cases we know that the navigation ended up in scope of a + // target application. + + // First, handle the case where a new app container (app or browser) was + // force-created for an app for user modified clicks. This refers to the + // use-cases here: + // https://bit.ly/pwa-navigation-capturing?tab=t.0#bookmark=id.ugh0e993wsl8, + // where a new app container is made. + if (initial_nav_handling_result_ == + InitialResult::kForcedNewAppContextAppWindow) { + CHECK(source_browser_app_id_.has_value()); + CHECK(first_navigation_app_id_.has_value()); + // standalone-app -> browser-tab-app. + if (target_display_mode == blink::mojom::DisplayMode::kBrowser) { + SetLaunchedAppId(*target_app_id, /*force_iph_off=*/true); + ReparentWebContentsToTabbedBrowser(web_contents_for_navigation, + disposition_, + navigation_params_browser_); + return content::NavigationThrottle::PROCEED; + } + // standalone-app -> standalone-app. + SetLaunchedAppId(*target_app_id); + CHECK(target_display_mode != blink::mojom::DisplayMode::kBrowser); + ReparentToAppBrowser(web_contents_for_navigation, *target_app_id, + final_url); + return content::NavigationThrottle::PROCEED; + } + if (initial_nav_handling_result_ == + InitialResult::kForcedNewAppContextBrowserTab) { + // browser-tab-app -> browser-tab-app. + if (target_display_mode == blink::mojom::DisplayMode::kBrowser) { + return content::NavigationThrottle::PROCEED; + } + // browser-tab-app -> standalone-app. This must have a source app id to + // ensure that we cannot have a user-modified click go from a regular + // browser tab to an app window. + CHECK(target_display_mode != blink::mojom::DisplayMode::kBrowser); + if (source_browser_app_id_.has_value()) { + SetLaunchedAppId(*target_app_id); + ReparentToAppBrowser(web_contents_for_navigation, *target_app_id, + final_url); + return content::NavigationThrottle::PROCEED; + } + } + + // Handle the last user-modified correction, where a user-modified click from + // an app went to the browser, but needs to be reparented back into an app. + // See + // https://bit.ly/pwa-navigation-capturing?tab=t.0#bookmark=id.ugh0e993wsl8 + // for more information. + if (initial_nav_handling_result_ == InitialResult::kBrowserTab && + is_user_modified_click() && source_browser_app_id_.has_value()) { + // As per the UX direction in the doc, NEW_BACKGROUND_TAB only creates a + // new app window for an app when coming from the same app window. + // Otherwise, only NEW_WINDOW can create a new app window when coming from + // an app. + if ((disposition_ == WindowOpenDisposition::NEW_BACKGROUND_TAB && + is_source_app_matching_final_target) || + (disposition_ == WindowOpenDisposition::NEW_WINDOW)) { + // browser-tab -> browser-tab-app. + if (target_display_mode == blink::mojom::DisplayMode::kBrowser) { + SetLaunchedAppId(*target_app_id, /*force_iph_off=*/true); + return content::NavigationThrottle::PROCEED; + } + // browser-tab -> standalone app + SetLaunchedAppId(*target_app_id); + ReparentToAppBrowser(web_contents_for_navigation, *target_app_id, + final_url); + return content::NavigationThrottle::PROCEED; + } + } + + // All other user-modified cases should do the default thing and navigate the + // existing container. + if (is_user_modified_click()) { + return content::NavigationThrottle::PROCEED; + } + + ClientModeAndBrowser client_mode_and_browser = + GetEffectiveClientModeAndBrowserForCapturing( + *profile_, *target_app_id, source_tab_app_id_, + /*ignore_browser_tabs_for_standalone_apps=*/false, + /*navigate_params_requested_browser=*/navigation_params_browser_); + + // After this point: + // - The navigation is non-user-modified. + // - This is a top-level browsing context. + // - The first navigation app_id doesn't match the target app_id (as per "Same + // first navigation state" case above). + + // Handle all cases where the initial navigation was captured, and that now + // needs to be corrected. See the table at + // bit.ly/pwa-navigation-handling-dd?tab=t.0#bookmark=id.hnvzj4iwiviz + + // First, address the 'navigate-new' or 'browser' initial capture, where the + // final state is also an effective 'navigate-new'. + if (client_mode_and_browser.effective_client_mode == + LaunchHandler::ClientMode::kNavigateNew && + (initial_nav_handling_result_ == InitialResult::kBrowserTab || + initial_nav_handling_result_ == + InitialResult::kNavigateCapturedNewAppWindow || + initial_nav_handling_result_ == + InitialResult::kNavigateCapturedNewBrowserTab)) { + // Handle all cases that result in a standalone app. + // (browser tab, browser-tab-app, or standalone-app -> standalone-app) + if (target_display_mode != blink::mojom::DisplayMode::kBrowser) { + SetLaunchedAppId(*target_app_id); + ReparentToAppBrowser(web_contents_for_navigation, *target_app_id, + final_url); + return content::NavigationThrottle::PROCEED; + } + // Handle all cases that result in a browser-tab-app. + // (browser tab, browser-tab-app, or standalone-app -> browser-tab-app) + CHECK(target_display_mode == blink::mojom::DisplayMode::kBrowser); + SetLaunchedAppId(*target_app_id, /*force_iph_off=*/true); + if (initial_nav_handling_result_ == + InitialResult::kNavigateCapturedNewAppWindow) { + ReparentWebContentsToTabbedBrowser(web_contents_for_navigation, + disposition_, + navigation_params_browser_); + } + return content::NavigationThrottle::PROCEED; + } + + // Only proceed from now on if the final app can be capturable depending on + // the result of the initial navigation handling. This involves only 2 + // use-cases, where the intermediary result is either a browser tab, or an app + // window that opened as a result of a capturable navigation. + // TODO(crbug.com/375619465): Implement open-in-browser-tab app support for + // redirection. + bool final_navigation_can_be_capturable = + InitialResultWasCaptured() || + initial_nav_handling_result_ == InitialResult::kBrowserTab; + if (!final_navigation_can_be_capturable) { + return content::NavigationThrottle::PROCEED; + } + + // Handle the use-case where the target_app_id has a launch handling mode of + // kFocusExisting or kNavigateExisting. In both cases this navigation gets + // aborted, and in some cases the web contents being navigated gets closed. + if (client_mode_and_browser.effective_client_mode == + LaunchHandler::ClientMode::kFocusExisting || + client_mode_and_browser.effective_client_mode == + LaunchHandler::ClientMode::kNavigateExisting) { + CHECK(client_mode_and_browser.browser); + CHECK(client_mode_and_browser.tab_index.has_value()); + CHECK_NE(*client_mode_and_browser.tab_index, -1); + + FocusAppContainer(client_mode_and_browser.browser, + *client_mode_and_browser.tab_index); + + content::WebContents* pre_existing_contents = + client_mode_and_browser.browser->tab_strip_model()->GetWebContentsAt( + *client_mode_and_browser.tab_index); + CHECK(pre_existing_contents); + CHECK_NE(pre_existing_contents, web_contents_for_navigation); + + if (client_mode_and_browser.effective_client_mode == + LaunchHandler::ClientMode::kNavigateExisting) { + content::OpenURLParams params = + content::OpenURLParams::FromNavigationHandle(navigation_handle()); + + // Reset the frame_tree_node_id to make sure we're navigating the main + // frame in the target web contents. + params.frame_tree_node_id = {}; + + pre_existing_contents->OpenURL( + params, + base::BindOnce( + [](const webapps::AppId& target_app_id, + content::NavigationHandle& navigation_handle) { + WebAppLaunchNavigationHandleUserData::CreateForNavigationHandle( + navigation_handle, target_app_id, /*force_iph_off=*/false); + }, + *target_app_id)); + + } else { + // Perform post navigation operations, like recording app launch metrics, + // or showing the navigation capturing IPH. + EnqueueLaunchParams(pre_existing_contents, *target_app_id, final_url, + /*wait_for_navigation_to_complete=*/false); + MaybeShowNavigationCaptureIph(*target_app_id, &*profile_, + client_mode_and_browser.browser); + RecordLaunchMetrics(*target_app_id, + apps::LaunchContainer::kLaunchContainerWindow, + apps::LaunchSource::kFromNavigationCapturing, + final_url, pre_existing_contents); + } + + // Close the old tab or app window, if it was created as part of the current + // navigation to mimic the behavior where the redirected url matches an + // outcome without redirection. Any residual app windows or tabs that were + // there before the current navigation started shouldn't be closed. + if (initial_nav_handling_result_ == + InitialResult::kNavigateCapturedNewAppWindow || + initial_nav_handling_result_ == + InitialResult::kNavigateCapturedNewBrowserTab || + initial_nav_handling_result_ == InitialResult::kBrowserTab) { + web_contents_for_navigation->ClosePage(); + } + return content::NavigationThrottle::CANCEL; + } + return content::NavigationThrottle::PROCEED; +} + +void NavigationCapturingProcess::OnAttachedToNavigationHandle() { + CHECK(navigation_handle()); + CHECK_NE(initial_nav_handling_result_, + InitialResult::kNotHandledByNavigationHandling); + if (!launched_app_id_) { + return; + } + + web_app::WebAppLaunchNavigationHandleUserData::CreateForNavigationHandle( + *navigation_handle(), *launched_app_id_, force_iph_off_); +} + +bool NavigationCapturingProcess:: + IsNavigationCapturingReimplExperimentEnabled() { + if (first_navigation_app_display_mode_ && + !WebAppRegistrar::IsSupportedDisplayModeForNavigationCapture( + *first_navigation_app_display_mode_)) { + return false; + } + // Enabling the generic flag turns it on for all navigations. + if (apps::features::IsNavigationCapturingReimplEnabled()) { + if (!features::kForcedOffCapturingAppsOnFirstNavigation.Get().empty() && + first_navigation_app_id_.has_value()) { + std::vector<std::string> forced_capturing_off_app_ids = base::SplitString( + features::kForcedOffCapturingAppsOnFirstNavigation.Get(), ",", + base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); + for (const std::string& forced_capturing_off_app_id : + forced_capturing_off_app_ids) { + if (first_navigation_app_id_ == forced_capturing_off_app_id) { + return false; + } + } + } + return true; + } + +#if BUILDFLAG(IS_CHROMEOS) + // Check application-specific flags. + if (first_navigation_app_id_.has_value() && + ::web_app::ChromeOsWebAppExperiments:: + IsNavigationCapturingReimplEnabledForTargetApp( + *first_navigation_app_id_)) { + return true; + } + if (source_browser_app_id_.has_value() && + ::web_app::ChromeOsWebAppExperiments:: + IsNavigationCapturingReimplEnabledForSourceApp( + *source_browser_app_id_, navigation_params_url_)) { + return true; + } +#endif + + return false; +} + +BrowserAndTabOverride NavigationCapturingProcess::CapturingDisabled() { + // Don't record debug information for ALL navigations unless expensive DCHECKs + // are enabled. +#if EXPENSIVE_DCHECKS_ARE_ON() + debug_data_.Set("result", "capturing disabled"); +#else + debug_data_.clear(); +#endif + CHECK_EQ(state_, PipelineState::kCreated); + state_ = PipelineState::kInitialOverrideCalculated; + return std::nullopt; +} + +BrowserAndTabOverride NavigationCapturingProcess::CancelInitialNavigation() { + debug_data_.Set("result", "cancel navigation"); + CHECK_EQ(state_, PipelineState::kCreated); + state_ = PipelineState::kInitialOverrideCalculated; + return {{nullptr, -1}}; +} + +BrowserAndTabOverride NavigationCapturingProcess::NoCapturingOverrideBrowser( + Browser* browser) { + debug_data_.Set("result", "no capturing, override browser"); + CHECK_EQ(state_, PipelineState::kCreated); + state_ = PipelineState::kInitialOverrideCalculated; + return {{browser, -1}}; +} + +BrowserAndTabOverride NavigationCapturingProcess::AuxiliaryContext() { + initial_nav_handling_result_ = InitialResult::kAuxContext; + // Don't record debug information for ALL navigations unless expensive DCHECKs + // are enabled. +#if EXPENSIVE_DCHECKS_ARE_ON() + debug_data_.Set("result", "auxiliary context"); +#else + debug_data_.clear(); +#endif + CHECK_EQ(state_, PipelineState::kCreated); + state_ = PipelineState::kInitialOverrideCalculated; + return std::nullopt; +} + +BrowserAndTabOverride NavigationCapturingProcess::AuxiliaryContextInAppWindow( + Browser* app_browser) { + CHECK(app_browser->app_controller()); + initial_nav_handling_result_ = InitialResult::kAuxContext; + if (first_navigation_app_id_.has_value()) { + SetLaunchedAppId(*first_navigation_app_id_); + } + debug_data_.Set("result", "auxiliary context in app window"); + CHECK_EQ(state_, PipelineState::kCreated); + state_ = PipelineState::kInitialOverrideCalculated; + return {{app_browser, -1}}; +} + +BrowserAndTabOverride +NavigationCapturingProcess::NoInitialActionRedirectionHandlingEligible() { + initial_nav_handling_result_ = InitialResult::kBrowserTab; + // Don't record debug information for ALL navigations unless expensive DCHECKs + // are enabled. + // TODO(https://crbug.com/351775835): Consider not erasing debug data until we + // know the redirect wasn't navigation captured either. +#if EXPENSIVE_DCHECKS_ARE_ON() + debug_data_.Set("result", "no initial action, redirection handling eligible"); +#else + debug_data_.clear(); +#endif + CHECK_EQ(state_, PipelineState::kCreated); + state_ = PipelineState::kInitialOverrideCalculated; + return std::nullopt; +} + +BrowserAndTabOverride NavigationCapturingProcess::ForcedNewAppContext( + blink::mojom::DisplayMode app_display_mode, + Browser* host_browser) { + CHECK(first_navigation_app_id_.has_value()); + CHECK(WebAppRegistrar::IsSupportedDisplayModeForNavigationCapture( + app_display_mode)); + CHECK((app_display_mode != blink::mojom::DisplayMode::kBrowser) == + (!!host_browser->app_controller())); + CHECK(disposition_ == WindowOpenDisposition::NEW_BACKGROUND_TAB || + disposition_ == WindowOpenDisposition::NEW_WINDOW); + CHECK(is_user_modified_click()); + initial_nav_handling_result_ = + app_display_mode == DisplayMode::kBrowser + ? InitialResult::kForcedNewAppContextBrowserTab + : InitialResult::kForcedNewAppContextAppWindow; + // Do not show iph when opening browser-tab-apps in a new browser tab, as + // this matches what is 'normal' - clicking on a link opens a new browser + // tab. + SetLaunchedAppId(*first_navigation_app_id_, + /*force_iph_off=*/app_display_mode == DisplayMode::kBrowser); + debug_data_.Set("result", "forced new app context"); + CHECK_EQ(state_, PipelineState::kCreated); + state_ = PipelineState::kInitialOverrideCalculated; + return {{host_browser, -1}}; +} + +BrowserAndTabOverride NavigationCapturingProcess::CapturedNewClient( + blink::mojom::DisplayMode app_display_mode, + Browser* host_browser) { + CHECK(first_navigation_app_id_.has_value()); + CHECK(WebAppRegistrar::IsSupportedDisplayModeForNavigationCapture( + app_display_mode)); + CHECK((app_display_mode != blink::mojom::DisplayMode::kBrowser) == + (!!host_browser->app_controller())); + CHECK(disposition_ == WindowOpenDisposition::NEW_FOREGROUND_TAB); + initial_nav_handling_result_ = + app_display_mode == DisplayMode::kBrowser + ? InitialResult::kNavigateCapturedNewBrowserTab + : InitialResult::kNavigateCapturedNewAppWindow; + // Do not show iph when opening browser-tab-apps in a new browser tab, as + // this matches what is 'normal' - clicking on a link opens a new browser + // tab. + SetLaunchedAppId(*first_navigation_app_id_, + /*force_iph_off=*/app_display_mode == DisplayMode::kBrowser); + debug_data_.Set("result", "captured new client"); + CHECK_EQ(state_, PipelineState::kCreated); + state_ = PipelineState::kInitialOverrideCalculated; + return {{host_browser, -1}}; +} + +BrowserAndTabOverride NavigationCapturingProcess::CapturedNavigateExisting( + Browser* app_browser, + int browser_tab) { + CHECK(first_navigation_app_id_.has_value()); + CHECK(disposition_ == WindowOpenDisposition::NEW_FOREGROUND_TAB); + CHECK(browser_tab != -1); + initial_nav_handling_result_ = + InitialResult::kNavigateCapturingNavigateExisting; + SetLaunchedAppId(*first_navigation_app_id_); + debug_data_.Set("result", "captured navigate existing"); + CHECK_EQ(state_, PipelineState::kCreated); + state_ = PipelineState::kInitialOverrideCalculated; + return {{app_browser, browser_tab}}; +} + +void NavigationCapturingProcess::SetLaunchedAppId(const webapps::AppId& app_id, + bool force_iph_off) { + CHECK_NE(initial_nav_handling_result_, + InitialResult::kNotHandledByNavigationHandling); + launched_app_id_ = app_id.empty() ? std::nullopt : std::optional(app_id); + force_iph_off_ = force_iph_off; + debug_data_.Set("result.launched_app_id", app_id); + debug_data_.Set("result.force_iph_off", force_iph_off); + if (!navigation_handle()) { + return; + } + + // Always delete the existing user data before optionally recreating new user + // data. + if (WebAppLaunchNavigationHandleUserData::GetForNavigationHandle( + *navigation_handle())) { + WebAppLaunchNavigationHandleUserData::DeleteForNavigationHandle( + *navigation_handle()); + } + if (launched_app_id_.has_value()) { + OnAttachedToNavigationHandle(); + } +} + +bool NavigationCapturingProcess::InitialResultWasCaptured() const { + switch (initial_nav_handling_result_) { + case InitialResult::kBrowserTab: + case InitialResult::kForcedNewAppContextAppWindow: + case InitialResult::kForcedNewAppContextBrowserTab: + case InitialResult::kNotHandledByNavigationHandling: + case InitialResult::kAuxContext: + return false; + case InitialResult::kNavigateCapturedNewAppWindow: + case InitialResult::kNavigateCapturedNewBrowserTab: + case InitialResult::kNavigateCapturingNavigateExisting: + return true; + } +} + +NAVIGATION_HANDLE_USER_DATA_KEY_IMPL(NavigationCapturingProcess); + +} // namespace web_app
diff --git a/chrome/browser/ui/web_applications/navigation_capturing_process.h b/chrome/browser/ui/web_applications/navigation_capturing_process.h new file mode 100644 index 0000000..ea8f7807 --- /dev/null +++ b/chrome/browser/ui/web_applications/navigation_capturing_process.h
@@ -0,0 +1,230 @@ +// Copyright 2025 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_WEB_APPLICATIONS_NAVIGATION_CAPTURING_PROCESS_H_ +#define CHROME_BROWSER_UI_WEB_APPLICATIONS_NAVIGATION_CAPTURING_PROCESS_H_ + +#include <memory> +#include <optional> +#include <tuple> + +#include "base/memory/raw_ptr.h" +#include "base/values.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/web_applications/web_app_launch_navigation_handle_user_data.h" +#include "chrome/browser/web_applications/web_app_constants.h" +#include "components/webapps/common/web_app_id.h" +#include "ui/base/window_open_disposition.h" + +class Browser; +struct NavigateParams; + +namespace web_app { + +// This class encompasses all of the logic for navigations in the browser to be +// captured into installed web app launches. +// +// Instances are created by `::Navigate()` in `browser_navigator.cc`, which +// also calls into this class to possibly capture the initial navigation. The +// instance is then eventually attached to the `NavigationHandle` for the +// navigation that was started. Later when all redirects for the navigation +// has been resolved, `NavigationCapturingRedirectThrottle()` again calls into +// this class to handle the result of the redirects, possible changing what app +// captures the navigation (or not capturing a previously captured navigation +// any longer). +// +// This class is also responsible for populating +// WebAppLaunchNavigationHandleUserData, which is used to gather launch metrics, +// populate the launch queue, and possibly trigger IPH. +class NavigationCapturingProcess + : public content::NavigationHandleUserData<NavigationCapturingProcess> { + public: + // Returns null if navigation capturing is disabled for this navigation. This + // returning non-null however does not mean that navigation capturing will + // definitely happen for this navigation; the logic in + // `GetInitialBrowserAndTabOverrideForNavigation()` can still decide that no + // capturing should apply to this navigation. + static std::unique_ptr<NavigationCapturingProcess> MaybeHandleAppNavigation( + const NavigateParams& navigate_params); + + ~NavigationCapturingProcess() override; + + // The first step of the navigation capturing process. This is called by + // `browser_navigator.cc` to check if the navigation capturing process wants + // to override the browser and or tab to use. A return value of `nullopt` + // means that no overriding should happen (but the navigation could still be + // captured on later redirects). A null `Browser*` means that the navigation + // should be aborted. + using BrowserAndTabOverride = std::optional<std::tuple<Browser*, int>>; + BrowserAndTabOverride GetInitialBrowserAndTabOverrideForNavigation( + const NavigateParams& params); + + // Called by `browesr_navigator.cc` after the WebContents and optionally + // NavigationHandle are known for the navigation it handled. Will CHECK-fail + // if called before `GetInitialBrowserAndTabOverrideForNavigation()`. + static void AfterWebContentsCreation( + std::unique_ptr<NavigationCapturingProcess> process, + content::WebContents& web_contents, + content::NavigationHandle* navigation_handle); + + // Attaches this NavigationCapturing process to a specific navigation. Will + // CHECK-fail if called before + // `GetInitialBrowserAndTabOverrideForNavigation()` is called. If that method + // decided no navigation capturing should apply to this navigation, this will + // destroy `user_data` rather than attach it. + static void AttachToNavigationHandle( + content::NavigationHandle& navigation_handle, + std::unique_ptr<NavigationCapturingProcess> user_data); + // Similar to `AttachToNavigationHandle()`, but instead attaches to the next + // navigation to start in the given `web_contents`. + static void AttachToNextNavigationInWebContents( + content::WebContents& web_contents, + std::unique_ptr<NavigationCapturingProcess> user_data); + + // The second step of the navigation capturing process. Called by + // `NavigationCapturingRedirectionThrottle` when the final URL is known after + // any possible redirects have happened. Will only be called after this class + // has been attached to a NavigationHandle, and will CHECK-fail otherwise. + using ThrottleCheckResult = content::NavigationThrottle::ThrottleCheckResult; + ThrottleCheckResult HandleRedirect(); + + content::NavigationHandle* navigation_handle() const { + return navigation_handle_; + } + + private: + friend NavigationHandleUserData; + + // To ensure the (public) methods of this class get called in the correct + // order, this enum is used to verify what state of the pipeline we're + // currently in. + enum class PipelineState { + kCreated, + kInitialOverrideCalculated, + kAttachedToWebContents, + kAttachedToNavigationHandle, + kFinished + }; + + // TODO(crbug.com/336371044): Support web apps that open in a new tab. + // The initial result of navigation handling, stored as an enum to prevent + // transferring a `Browser` instance everywhere. + // Note: Apps can be configured to open in a browser tab or open in a + // standalone window. + enum class InitialResult { + // A browser tab was opened that wasn't the result of web app navigation + // capturing, but due to redirection the final behavior could change. + // Note: New context & capturable behavior for open-in-browser-tab apps + // apply to the cases below, and are not part of this category. + kBrowserTab = 0, + // The navigation was captured by an app and it resulted in the creation of + // a new app window for the navigation. This can only occur when the app + // opens in a standalone window. + kNavigateCapturedNewAppWindow = 1, + // The navigation was captured and it resulted in the creation of a new + // browser tab for the navigation. This can only occur when the app opens in + // a browser tab. + kNavigateCapturedNewBrowserTab = 2, + // The navigation was captured and it resulted in a existing web contents + // (either in an app window or browser tab) to be navigated. + kNavigateCapturingNavigateExisting = 3, + // The capturing logic forced this to launch the app in a new app window + // context, with the same behavior of `navigate-new`. This is used when it + // was a user-modified navigation, triggered by a shift or middle click. + // Launch parameters are enqueued. + kForcedNewAppContextAppWindow = 4, + // Same as above but for an app that opens in a browser tab. + kForcedNewAppContextBrowserTab = 5, + // The navigation open an auxiliary context, and thus the 'window container' + // (app or browser) needs to stay the same. + kAuxContext = 6, + // This navigation should be excluded from redirection handling. The + // NavigationCapturingProcess instance will not be attached to the + // NavigationHandle. + kNotHandledByNavigationHandling = 7, + kMaxValue = kNotHandledByNavigationHandling + }; + + explicit NavigationCapturingProcess(const NavigateParams& params); + + // Returns true if based on the NavigateParams this instance was created with + // the navigation capturing reimpl experiment is enabled. + bool IsNavigationCapturingReimplExperimentEnabled(); + + // Called when this process is attached to a NavigationHandle. + void OnAttachedToNavigationHandle(); + + // Helper methods for `GetInitialBrowserAndTabOverrideForNavigation()` that + // return the correct return value and update internal state of this class + // with the corresponding outcome. + BrowserAndTabOverride CapturingDisabled(); + BrowserAndTabOverride CancelInitialNavigation(); + BrowserAndTabOverride NoCapturingOverrideBrowser(Browser* browser); + BrowserAndTabOverride AuxiliaryContext(); + BrowserAndTabOverride AuxiliaryContextInAppWindow(Browser* app_browser); + BrowserAndTabOverride NoInitialActionRedirectionHandlingEligible(); + BrowserAndTabOverride ForcedNewAppContext( + blink::mojom::DisplayMode app_display_mode, + Browser* host_browser); + BrowserAndTabOverride CapturedNewClient( + blink::mojom::DisplayMode app_display_mode, + Browser* host_browser); + BrowserAndTabOverride CapturedNavigateExisting(Browser* app_browser, + int browser_tab); + + // Updates the `launched_app_id_` field, and if this process as already been + // attached to a `NavigationHandle`, also creates or updates the + // `WebAppLaunchNavigationHandleUserData` for that handle. An empty `app_id` + // will cause the launch data to be cleared. + void SetLaunchedAppId(const webapps::AppId& app_id, + bool force_iph_off = false); + + // Returns true if `initial_nav_handling_result_` is one of the values where + // the navigation was captured by an app. + bool InitialResultWasCaptured() const; + + bool is_user_modified_click() const { + return disposition_ == WindowOpenDisposition::NEW_WINDOW || + disposition_ == WindowOpenDisposition::NEW_BACKGROUND_TAB; + } + + PipelineState state_ = PipelineState::kCreated; + + // These fields are copied or derived from the NavigateParams of the original + // navigation. + const raw_ref<Profile> profile_; + const std::optional<webapps::AppId> source_browser_app_id_; + const std::optional<webapps::AppId> source_tab_app_id_; + const GURL navigation_params_url_; + const WindowOpenDisposition disposition_; + const raw_ptr<Browser> navigation_params_browser_; + std::optional<webapps::AppId> first_navigation_app_id_; + std::optional<blink::mojom::DisplayMode> first_navigation_app_display_mode_; + + // This field records the outcome of handling the initial navigation,before + // any redirects might have happened. + InitialResult initial_nav_handling_result_ = + InitialResult::kNotHandledByNavigationHandling; + + // The app that ended up being launched as a result of the navigation being + // captured. This is initially set by + // `GetInitialBrowserAndTabOverrideForNavigation()` and can be cleared or + // reset by `HandleRedirect()` if the redirect results in a different app + // handling the launch. + bool force_iph_off_ = false; + std::optional<webapps::AppId> launched_app_id_; + + // Set to the NavigationHandle this process is owned by, once it is attached + // to one. + raw_ptr<content::NavigationHandle> navigation_handle_ = nullptr; + + // Debug information persisted to chrome://web-app-internals on destruction of + // this class. + base::Value::Dict debug_data_; + + NAVIGATION_HANDLE_USER_DATA_KEY_DECL(); +}; +} // namespace web_app + +#endif // CHROME_BROWSER_UI_WEB_APPLICATIONS_NAVIGATION_CAPTURING_PROCESS_H_
diff --git a/chrome/browser/ui/web_applications/navigation_capturing_redirection_throttle.cc b/chrome/browser/ui/web_applications/navigation_capturing_redirection_throttle.cc index ed5a6bb4..6d5dc5e 100644 --- a/chrome/browser/ui/web_applications/navigation_capturing_redirection_throttle.cc +++ b/chrome/browser/ui/web_applications/navigation_capturing_redirection_throttle.cc
@@ -7,118 +7,17 @@ #include <memory> #include <optional> -#include "chrome/browser/apps/link_capturing/link_capturing_features.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/browser_commands.h" -#include "chrome/browser/ui/browser_finder.h" -#include "chrome/browser/ui/web_applications/app_browser_controller.h" -#include "chrome/browser/ui/web_applications/navigation_capturing_information_forwarder.h" -#include "chrome/browser/ui/web_applications/navigation_capturing_navigation_handle_user_data.h" -#include "chrome/browser/ui/web_applications/web_app_launch_utils.h" -#include "chrome/browser/web_applications/mojom/user_display_mode.mojom-shared.h" -#include "chrome/browser/web_applications/web_app_constants.h" -#include "chrome/browser/web_applications/web_app_helpers.h" -#include "chrome/browser/web_applications/web_app_provider.h" -#include "chrome/browser/web_applications/web_app_registrar.h" -#include "components/services/app_service/public/cpp/app_launch_util.h" -#include "components/webapps/common/web_app_id.h" +#include "chrome/browser/ui/web_applications/navigation_capturing_process.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/navigation_throttle.h" -#include "third_party/blink/public/mojom/manifest/display_mode.mojom-shared.h" -#include "ui/base/window_open_disposition.h" -#include "ui/gfx/geometry/rect.h" -#include "url/gurl.h" - -#if BUILDFLAG(IS_CHROMEOS) -#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" -#include "chrome/browser/apps/app_service/launch_utils.h" -#endif // BUILDFLAG(IS_CHROMEOS) namespace web_app { namespace { -bool WasCaptured(NavigationHandlingInitialResult result) { - switch (result) { - case NavigationHandlingInitialResult::kBrowserTab: - case NavigationHandlingInitialResult::kForcedNewAppContextAppWindow: - case NavigationHandlingInitialResult::kForcedNewAppContextBrowserTab: - case NavigationHandlingInitialResult::kNotHandledByNavigationHandling: - case NavigationHandlingInitialResult::kAuxContext: - return false; - case NavigationHandlingInitialResult::kNavigateCapturedNewAppWindow: - case NavigationHandlingInitialResult::kNavigateCapturedNewBrowserTab: - case NavigationHandlingInitialResult::kNavigateCapturingNavigateExisting: - return true; - } -} using ThrottleCheckResult = content::NavigationThrottle::ThrottleCheckResult; -// TODO(crbug.com/371237535): Move to TabInterface once there is support for -// getting the browser interface for web contents that are in an app window. -// For all use-cases where a reparenting to an app window happens, launch params -// need to be enqueued so as to mimic the pre redirection behavior. See -// https://bit.ly/pwa-navigation-capturing?tab=t.0#bookmark=id.60x2trlfg6iq for -// more information. -void ReparentToAppBrowser(content::WebContents* old_web_contents, - const webapps::AppId& app_id, - const GURL& target_url) { - Browser* main_browser = chrome::FindBrowserWithTab(old_web_contents); - Browser* target_browser = CreateWebAppWindowMaybeWithHomeTab( - app_id, CreateParamsForApp( - app_id, /*is_popup=*/false, /*trusted_source=*/true, - gfx::Rect(), main_browser->profile(), /*user_gesture=*/true)); - CHECK(target_browser->app_controller()); - ReparentWebContentsIntoBrowserImpl( - main_browser, old_web_contents, target_browser, - target_browser->app_controller()->IsUrlInHomeTabScope(target_url)); - CHECK(old_web_contents); -} - -// TODO(crbug.com/371237535): Move to TabInterface once there is support for -// getting the browser interface for web contents that are in an app window. -void ReparentWebContentsToTabbedBrowser(content::WebContents* old_web_contents, - WindowOpenDisposition disposition, - Browser* navigate_params_browser) { - Browser* source_browser = chrome::FindBrowserWithTab(old_web_contents); - Browser* existing_browser_window = - navigate_params_browser && - !AppBrowserController::IsWebApp(navigate_params_browser) - ? navigate_params_browser - : chrome::FindTabbedBrowser(source_browser->profile(), - /*match_original_profiles=*/false); - - // Create a new browser window if the navigation was triggered via a - // shift-click, or if there are no open tabbed browser windows at the moment. - Browser* target_browser_window = - (disposition == WindowOpenDisposition::NEW_WINDOW || - !existing_browser_window) - ? Browser::Create(Browser::CreateParams(source_browser->profile(), - /*user_gesture=*/true)) - : existing_browser_window; - - ReparentWebContentsIntoBrowserImpl(source_browser, old_web_contents, - target_browser_window); -} - -std::optional<webapps::AppId> GetWebAppControllingUrl( - Profile* profile, - const WebAppProvider* provider, - const GURL& url) { -#if BUILDFLAG(IS_CHROMEOS) - if (!apps::AppServiceProxyFactory::IsAppServiceAvailableForProfile(profile)) { - return std::nullopt; - } - return apps::FindAppIdsToLaunchForUrl( - apps::AppServiceProxyFactory::GetForProfile(profile), url) - .preferred; -#else - return provider->registrar_unsafe().FindAppThatCapturesLinksInScope(url); -#endif -} - } // namespace // static @@ -138,7 +37,12 @@ ThrottleCheckResult NavigationCapturingRedirectionThrottle::WillProcessResponse() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - ThrottleCheckResult result = HandleResponse(); + ThrottleCheckResult result = content::NavigationThrottle::PROCEED; + NavigationCapturingProcess* process = + NavigationCapturingProcess::GetForNavigationHandle(*navigation_handle()); + if (process) { + result = process->HandleRedirect(); + } // If the navigation is not cancelled, this is the time to enqueue launch // params, record launch metrics and maybe show a navigation capturing IPH. @@ -146,8 +50,8 @@ // will cancel this navigation, so ideally we would wait until the navigation // actually commits, but this is an easier place to hook into. if (result.action() != content::NavigationThrottle::CANCEL) { - NavigationCapturingNavigationHandleUserData* handle_user_data = - NavigationCapturingNavigationHandleUserData::GetForNavigationHandle( + WebAppLaunchNavigationHandleUserData* handle_user_data = + WebAppLaunchNavigationHandleUserData::GetForNavigationHandle( *navigation_handle()); if (handle_user_data) { handle_user_data->MaybePerformAppHandlingTasksInWebContents(); @@ -157,336 +61,8 @@ return result; } -ThrottleCheckResult NavigationCapturingRedirectionThrottle::HandleResponse() { - // Bail out if there's no Navigation Capturing data attached. Note: this - // cannot be checked in `MaybeCreate()` since the data might get attached - // after it's executed. - NavigationCapturingNavigationHandleUserData* handle_user_data = - NavigationCapturingNavigationHandleUserData::GetForNavigationHandle( - *navigation_handle()); - if (!handle_user_data || !handle_user_data->redirection_info().has_value()) { - return content::NavigationThrottle::PROCEED; - } - - // See https://bit.ly/pwa-navigation-capturing and - // https://bit.ly/pwa-navigation-handling-dd for more context. - // Exit early if: - // 1. If there were no redirects, then the only url in the redirect chain - // should be the last url to go to. - // 2. This is not a server side redirect. - // 3. The navigation was started from the context menu. - if (navigation_handle()->GetRedirectChain().size() == 1 || - !navigation_handle()->WasServerRedirect() || - (navigation_handle()->WasStartedFromContextMenu())) { - return content::NavigationThrottle::PROCEED; - } - const GURL& final_url = navigation_handle()->GetURL(); - if (!final_url.is_valid()) { - return content::NavigationThrottle::PROCEED; - } - - NavigationCapturingRedirectionInfo redirection_info = - *handle_user_data->redirection_info(); - WindowOpenDisposition link_click_disposition = redirection_info.disposition(); - NavigationHandlingInitialResult initial_nav_handling_result = - redirection_info.initial_nav_handling_result(); - std::optional<webapps::AppId> source_browser_app_id = - redirection_info.source_browser_app_id(); - std::optional<webapps::AppId> source_tab_app_id = - redirection_info.source_tab_app_id(); - std::optional<webapps::AppId> navigation_handling_first_stage_app = - redirection_info.first_navigation_app_id(); - Browser* navigation_params_browser = - redirection_info.navigation_params_browser(); - - // Do not handle redirections for navigations that create an auxiliary - // browsing context, or if the app window that opened is not a part of the - // navigation handling flow. - if (initial_nav_handling_result == - NavigationHandlingInitialResult::kNotHandledByNavigationHandling || - initial_nav_handling_result == - NavigationHandlingInitialResult::kAuxContext) { - return content::NavigationThrottle::PROCEED; - } - - content::WebContents* const web_contents_for_navigation = - navigation_handle()->GetWebContents(); - - WebAppProvider* provider = - WebAppProvider::GetForWebContents(web_contents_for_navigation); - WebAppRegistrar& registrar = provider->registrar_unsafe(); - std::optional<webapps::AppId> target_app_id = - GetWebAppControllingUrl(&profile_.get(), provider, final_url); - - // "Same first navigation state" case: - // First, we can exit early if the first navigation app id matches the target - // app id (which includes if they are both std::nullopt), as this means we - // already did the 'correct' navigation capturing behavior on the first - // navigation. - if (navigation_handling_first_stage_app == target_app_id) { - return content::NavigationThrottle::PROCEED; - } - - // Clear out the "launch app id" field. This way we ensure that in any branch - // where the redirect does not result in an app being launched we don't - // accidentally (try to) treat it as a launch. Any branch where an app launch - // does happen will re-set the field to the correct value. - handle_user_data->SetLaunchedAppState(std::nullopt, /*force_iph_off=*/false); - - // After this point: - // - The browsing context is a top-level browsing context. - // - The initial navigation capturing app_id does not match the final - // target_app_id (and either can be std::nullopt, but not both). - // - Navigation is only triggered as part of left, middle or shift clicks. - - bool is_source_app_matching_final_target = - target_app_id == source_browser_app_id; - - // First, handle cases where the final url is not in scope of any app. These - // can mostly proceed as is, except for two cases where the initial navigation - // ended up in an app window but should now be in a browser tab. - if (!target_app_id.has_value()) { - if (initial_nav_handling_result == - NavigationHandlingInitialResult::kForcedNewAppContextAppWindow || - initial_nav_handling_result == - NavigationHandlingInitialResult::kNavigateCapturedNewAppWindow) { - ReparentWebContentsToTabbedBrowser(web_contents_for_navigation, - link_click_disposition, - navigation_params_browser); - } - return content::NavigationThrottle::PROCEED; - } - - blink::mojom::DisplayMode target_display_mode = - registrar.GetAppEffectiveDisplayMode(*target_app_id); - CHECK(WebAppRegistrar::IsSupportedDisplayModeForNavigationCapture( - target_display_mode)); - - // For the remaining cases we know that the navigation ended up in scope of a - // target application. - - // First, handle the case where a new app container (app or browser) was - // force-created for an app for user modified clicks. This refers to the - // use-cases here: - // https://bit.ly/pwa-navigation-capturing?tab=t.0#bookmark=id.ugh0e993wsl8, - // where a new app container is made. - if (initial_nav_handling_result == - NavigationHandlingInitialResult::kForcedNewAppContextAppWindow) { - CHECK(redirection_info.source_browser_app_id().has_value()); - CHECK(navigation_handling_first_stage_app); - // standalone-app -> browser-tab-app. - if (target_display_mode == blink::mojom::DisplayMode::kBrowser) { - handle_user_data->SetLaunchedAppState(*target_app_id, - /*force_iph_off=*/true); - ReparentWebContentsToTabbedBrowser(web_contents_for_navigation, - link_click_disposition, - navigation_params_browser); - return content::NavigationThrottle::PROCEED; - } - // standalone-app -> standalone-app. - handle_user_data->SetLaunchedAppState(*target_app_id, - /*force_iph_off=*/false); - CHECK(target_display_mode != blink::mojom::DisplayMode::kBrowser); - ReparentToAppBrowser(web_contents_for_navigation, *target_app_id, - final_url); - return content::NavigationThrottle::PROCEED; - } - if (initial_nav_handling_result == - NavigationHandlingInitialResult::kForcedNewAppContextBrowserTab) { - // browser-tab-app -> browser-tab-app. - if (target_display_mode == blink::mojom::DisplayMode::kBrowser) { - return content::NavigationThrottle::PROCEED; - } - // browser-tab-app -> standalone-app. This must have a source app id to - // ensure that we cannot have a user-modified click go from a regular - // browser tab to an app window. - CHECK(target_display_mode != blink::mojom::DisplayMode::kBrowser); - if (source_browser_app_id.has_value()) { - handle_user_data->SetLaunchedAppState(*target_app_id, - /*force_iph_off=*/false); - ReparentToAppBrowser(web_contents_for_navigation, *target_app_id, - final_url); - return content::NavigationThrottle::PROCEED; - } - } - - // Handle the last user-modified correction, where a user-modified click from - // an app went to the browser, but needs to be reparented back into an app. - // See - // https://bit.ly/pwa-navigation-capturing?tab=t.0#bookmark=id.ugh0e993wsl8 - // for more information. - bool is_user_modified = - (link_click_disposition == WindowOpenDisposition::NEW_BACKGROUND_TAB) || - (link_click_disposition == WindowOpenDisposition::NEW_WINDOW); - if (initial_nav_handling_result == - NavigationHandlingInitialResult::kBrowserTab && - is_user_modified && source_browser_app_id.has_value()) { - // As per the UX direction in the doc, NEW_BACKGROUND_TAB only creates a - // new app window for an app when coming from the same app window. - // Otherwise, only NEW_WINDOW can create a new app window when coming from - // an app. - if ((link_click_disposition == WindowOpenDisposition::NEW_BACKGROUND_TAB && - is_source_app_matching_final_target) || - (link_click_disposition == WindowOpenDisposition::NEW_WINDOW)) { - // browser-tab -> browser-tab-app. - if (target_display_mode == blink::mojom::DisplayMode::kBrowser) { - handle_user_data->SetLaunchedAppState(*target_app_id, - /*force_iph_off=*/true); - return content::NavigationThrottle::PROCEED; - } - // browser-tab -> standalone app - handle_user_data->SetLaunchedAppState(*target_app_id, - /*force_iph_off=*/false); - ReparentToAppBrowser(web_contents_for_navigation, *target_app_id, - final_url); - return content::NavigationThrottle::PROCEED; - } - } - - // All other user-modified cases should do the default thing and navigate the - // existing container. - if (is_user_modified) { - return content::NavigationThrottle::PROCEED; - } - - ClientModeAndBrowser client_mode_and_browser = - GetEffectiveClientModeAndBrowserForCapturing( - *profile_, *target_app_id, source_tab_app_id, - /*ignore_browser_tabs_for_standalone_apps=*/false, - /*navigate_params_requested_browser=*/navigation_params_browser); - - // After this point: - // - The navigation is non-user-modified. - // - This is a top-level browsing context. - // - The first navigation app_id doesn't match the target app_id (as per "Same - // first navigation state" case above). - - // Handle all cases where the initial navigation was captured, and that now - // needs to be corrected. See the table at - // bit.ly/pwa-navigation-handling-dd?tab=t.0#bookmark=id.hnvzj4iwiviz - - // First, address the 'navigate-new' or 'browser' initial capture, where the - // final state is also an effective 'navigate-new'. - if (client_mode_and_browser.effective_client_mode == - LaunchHandler::ClientMode::kNavigateNew && - (initial_nav_handling_result == - NavigationHandlingInitialResult::kBrowserTab || - initial_nav_handling_result == - NavigationHandlingInitialResult::kNavigateCapturedNewAppWindow || - initial_nav_handling_result == - NavigationHandlingInitialResult::kNavigateCapturedNewBrowserTab)) { - // Handle all cases that result in a standalone app. - // (browser tab, browser-tab-app, or standalone-app -> standalone-app) - if (target_display_mode != blink::mojom::DisplayMode::kBrowser) { - handle_user_data->SetLaunchedAppState(*target_app_id, - /*force_iph_off=*/false); - ReparentToAppBrowser(web_contents_for_navigation, *target_app_id, - final_url); - return content::NavigationThrottle::PROCEED; - } - // Handle all cases that result in a browser-tab-app. - // (browser tab, browser-tab-app, or standalone-app -> browser-tab-app) - CHECK(target_display_mode == blink::mojom::DisplayMode::kBrowser); - handle_user_data->SetLaunchedAppState(*target_app_id, - /*force_iph_off=*/true); - if (initial_nav_handling_result == - NavigationHandlingInitialResult::kNavigateCapturedNewAppWindow) { - ReparentWebContentsToTabbedBrowser(web_contents_for_navigation, - link_click_disposition, - navigation_params_browser); - } - return content::NavigationThrottle::PROCEED; - } - - // Only proceed from now on if the final app can be capturable depending on - // the result of the initial navigation handling. This involves only 2 - // use-cases, where the intermediary result is either a browser tab, or an app - // window that opened as a result of a capturable navigation. - // TODO(crbug.com/375619465): Implement open-in-browser-tab app support for - // redirection. - bool final_navigation_can_be_capturable = - WasCaptured(initial_nav_handling_result) || - initial_nav_handling_result == - NavigationHandlingInitialResult::kBrowserTab; - if (!final_navigation_can_be_capturable) { - return content::NavigationThrottle::PROCEED; - } - - // Handle the use-case where the target_app_id has a launch handling mode of - // kFocusExisting or kNavigateExisting. In both cases this navigation gets - // aborted, and in some cases the web contents being navigated gets closed. - if (client_mode_and_browser.effective_client_mode == - LaunchHandler::ClientMode::kFocusExisting || - client_mode_and_browser.effective_client_mode == - LaunchHandler::ClientMode::kNavigateExisting) { - CHECK(client_mode_and_browser.browser); - CHECK(client_mode_and_browser.tab_index.has_value()); - CHECK_NE(*client_mode_and_browser.tab_index, -1); - - FocusAppContainer(client_mode_and_browser.browser, - *client_mode_and_browser.tab_index); - - content::WebContents* pre_existing_contents = - client_mode_and_browser.browser->tab_strip_model()->GetWebContentsAt( - *client_mode_and_browser.tab_index); - CHECK(pre_existing_contents); - CHECK_NE(pre_existing_contents, web_contents_for_navigation); - - if (client_mode_and_browser.effective_client_mode == - LaunchHandler::ClientMode::kNavigateExisting) { - content::OpenURLParams params = - content::OpenURLParams::FromNavigationHandle(navigation_handle()); - - // Reset the frame_tree_node_id to make sure we're navigating the main - // frame in the target web contents. - params.frame_tree_node_id = {}; - - pre_existing_contents->OpenURL( - params, base::BindOnce( - [](const webapps::AppId& target_app_id, - content::NavigationHandle& navigation_handle) { - NavigationCapturingNavigationHandleUserData:: - CreateForNavigationHandle( - navigation_handle, - /*redirection_info=*/std::nullopt, - target_app_id, /*force_iph_off=*/false); - }, - *target_app_id)); - - } else { - // Perform post navigation operations, like recording app launch metrics, - // or showing the navigation capturing IPH. - EnqueueLaunchParams(pre_existing_contents, *target_app_id, final_url, - /*wait_for_navigation_to_complete=*/false); - MaybeShowNavigationCaptureIph(*target_app_id, &profile_.get(), - client_mode_and_browser.browser); - RecordLaunchMetrics(*target_app_id, - apps::LaunchContainer::kLaunchContainerWindow, - apps::LaunchSource::kFromNavigationCapturing, - final_url, pre_existing_contents); - } - - // Close the old tab or app window, if it was created as part of the current - // navigation to mimic the behavior where the redirected url matches an - // outcome without redirection. Any residual app windows or tabs that were - // there before the current navigation started shouldn't be closed. - if (initial_nav_handling_result == - NavigationHandlingInitialResult::kNavigateCapturedNewAppWindow || - initial_nav_handling_result == - NavigationHandlingInitialResult::kNavigateCapturedNewBrowserTab || - initial_nav_handling_result == - NavigationHandlingInitialResult::kBrowserTab) { - web_contents_for_navigation->ClosePage(); - } - return content::NavigationThrottle::CANCEL; - } - return content::NavigationThrottle::PROCEED; -} - NavigationCapturingRedirectionThrottle::NavigationCapturingRedirectionThrottle( content::NavigationHandle* navigation_handle) - : content::NavigationThrottle(navigation_handle), - profile_(*Profile::FromBrowserContext( - navigation_handle->GetWebContents()->GetBrowserContext())) {} + : content::NavigationThrottle(navigation_handle) {} } // namespace web_app
diff --git a/chrome/browser/ui/web_applications/navigation_capturing_redirection_throttle.h b/chrome/browser/ui/web_applications/navigation_capturing_redirection_throttle.h index bdce5c2..da3f472 100644 --- a/chrome/browser/ui/web_applications/navigation_capturing_redirection_throttle.h +++ b/chrome/browser/ui/web_applications/navigation_capturing_redirection_throttle.h
@@ -10,8 +10,6 @@ #include "content/public/browser/navigation_throttle.h" #include "ui/base/window_open_disposition.h" -class Profile; - namespace web_app { // This handler is executed after a redirection chain, and attempts to 'correct' @@ -39,12 +37,8 @@ ThrottleCheckResult WillProcessResponse() override; private: - ThrottleCheckResult HandleResponse(); - explicit NavigationCapturingRedirectionThrottle( content::NavigationHandle* navigation_handle); - - raw_ref<Profile> profile_; }; } // namespace web_app
diff --git a/chrome/browser/ui/web_applications/navigation_handle_user_data_forwarder.h b/chrome/browser/ui/web_applications/navigation_handle_user_data_forwarder.h new file mode 100644 index 0000000..ed290a5 --- /dev/null +++ b/chrome/browser/ui/web_applications/navigation_handle_user_data_forwarder.h
@@ -0,0 +1,60 @@ +// Copyright 2024 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_WEB_APPLICATIONS_NAVIGATION_HANDLE_USER_DATA_FORWARDER_H_ +#define CHROME_BROWSER_UI_WEB_APPLICATIONS_NAVIGATION_HANDLE_USER_DATA_FORWARDER_H_ + +#include "base/supports_user_data.h" +#include "content/public/browser/navigation_handle.h" +#include "content/public/browser/navigation_handle_user_data.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_contents_observer.h" +#include "content/public/browser/web_contents_user_data.h" + +namespace web_app { + +// Helper class that takes a NavigationHandleUserData and attaches it to the +// first navigation that is started in the given WebContents. The user data +// needs to implement a `AttachToNavigationHandle` method to do the actual +// attaching. +// This is a plain `base::SupportsUserData::Data` rather than a +// `WebContentsUserData` to make it easier to re-use the same user data key +// as what is used by the underlying `NavigationHandleUserData`. +template <typename UserDataType> +class NavigationHandleUserDataForwarder : public content::WebContentsObserver, + public base::SupportsUserData::Data { + public: + NavigationHandleUserDataForwarder(content::WebContents& contents, + std::unique_ptr<UserDataType> data) + : content::WebContentsObserver(&contents), data_(std::move(data)) {} + ~NavigationHandleUserDataForwarder() override = default; + + // Deletes the current instance of `NavigationHandleUserDataForwarder` + // in the associated `WebContents`. + void SelfDestruct() { + CHECK_EQ(web_contents()->GetUserData(UserDataKey()), this); + web_contents()->RemoveUserData(UserDataKey()); + } + + // content::WebContentsObserver overrides: + void DidStartNavigation( + content::NavigationHandle* navigation_handle) override { + UserDataType::AttachToNavigationHandle(*navigation_handle, + std::move(data_)); + SelfDestruct(); + } + void DidFinishNavigation( + content::NavigationHandle* navigation_handle) override { + SelfDestruct(); + } + + static const void* UserDataKey() { return UserDataType::UserDataKey(); } + + private: + std::unique_ptr<UserDataType> data_; +}; + +} // namespace web_app + +#endif // CHROME_BROWSER_UI_WEB_APPLICATIONS_NAVIGATION_HANDLE_USER_DATA_FORWARDER_H_
diff --git a/chrome/browser/ui/web_applications/web_app_launch_navigation_handle_user_data.cc b/chrome/browser/ui/web_applications/web_app_launch_navigation_handle_user_data.cc new file mode 100644 index 0000000..b63e643 --- /dev/null +++ b/chrome/browser/ui/web_applications/web_app_launch_navigation_handle_user_data.cc
@@ -0,0 +1,60 @@ +// Copyright 2024 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/web_applications/web_app_launch_navigation_handle_user_data.h" + +#include "chrome/browser/ui/browser_finder.h" +#include "chrome/browser/ui/web_applications/web_app_launch_utils.h" +#include "chrome/browser/web_applications/web_app_launch_params.h" +#include "chrome/browser/web_applications/web_app_provider.h" +#include "chrome/browser/web_applications/web_app_tab_helper.h" +#include "components/services/app_service/public/cpp/app_launch_util.h" +#include "content/public/browser/navigation_handle.h" +#include "content/public/browser/navigation_handle_user_data.h" +#include "third_party/blink/public/mojom/manifest/display_mode.mojom-shared.h" + +namespace web_app { + +WebAppLaunchNavigationHandleUserData::~WebAppLaunchNavigationHandleUserData() = + default; + +WebAppLaunchNavigationHandleUserData::WebAppLaunchNavigationHandleUserData( + content::NavigationHandle& navigation_handle, + webapps::AppId launched_app, + bool force_iph_off) + : navigation_handle_(navigation_handle), + launched_app_(std::move(launched_app)), + force_iph_off_(force_iph_off) {} + +void WebAppLaunchNavigationHandleUserData:: + MaybePerformAppHandlingTasksInWebContents() { + const webapps::AppId& app_id = launched_app_; + content::WebContents* web_contents = navigation_handle_->GetWebContents(); + + EnqueueLaunchParams( + web_contents, app_id, navigation_handle_->GetURL(), + /*wait_for_navigation_to_complete=*/!navigation_handle_->HasCommitted()); + + WebAppTabHelper* tab_helper = WebAppTabHelper::FromWebContents(web_contents); + CHECK(tab_helper); + + apps::LaunchContainer container = + tab_helper->is_in_app_window() + ? apps::LaunchContainer::kLaunchContainerWindow + : apps::LaunchContainer::kLaunchContainerTab; + RecordLaunchMetrics(app_id, container, + apps::LaunchSource::kFromNavigationCapturing, + navigation_handle_->GetURL(), web_contents); + + if (!force_iph_off_) { + // TODO(crbug.com/371237535): Avoid reliance on FindBrowserWithTab and + // instead pass in the Browser instance earlier. + Browser* browser = chrome::FindBrowserWithTab(web_contents); + MaybeShowNavigationCaptureIph(app_id, browser->profile(), browser); + } +} + +NAVIGATION_HANDLE_USER_DATA_KEY_IMPL(WebAppLaunchNavigationHandleUserData); + +} // namespace web_app
diff --git a/chrome/browser/ui/web_applications/web_app_launch_navigation_handle_user_data.h b/chrome/browser/ui/web_applications/web_app_launch_navigation_handle_user_data.h new file mode 100644 index 0000000..b29ab0e --- /dev/null +++ b/chrome/browser/ui/web_applications/web_app_launch_navigation_handle_user_data.h
@@ -0,0 +1,54 @@ +// Copyright 2024 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_WEB_APPLICATIONS_WEB_APP_LAUNCH_NAVIGATION_HANDLE_USER_DATA_H_ +#define CHROME_BROWSER_UI_WEB_APPLICATIONS_WEB_APP_LAUNCH_NAVIGATION_HANDLE_USER_DATA_H_ + +#include <optional> + +#include "base/memory/raw_ref.h" +#include "components/webapps/common/web_app_id.h" +#include "content/public/browser/navigation_handle_user_data.h" + +namespace content { +class NavigationHandle; +} // namespace content + +namespace web_app { + +// Data that is attached to a NavigationHandle which describes what app (if any) +// was launched as part of the navigation. When the navigation completes this is +// used to queue launch params, record launch metrics, and maybe show +// navigation capturing IPH. +class WebAppLaunchNavigationHandleUserData + : public content::NavigationHandleUserData< + WebAppLaunchNavigationHandleUserData> { + public: + ~WebAppLaunchNavigationHandleUserData() override; + + const webapps::AppId& launched_app() const { return launched_app_; } + + // This method will queue launch params, record launch metrics and maybe show + // a navigation capturing IPH. Should be called when it is known that this + // navigation will commit. + void MaybePerformAppHandlingTasksInWebContents(); + + private: + WebAppLaunchNavigationHandleUserData( + content::NavigationHandle& navigation_handle, + webapps::AppId launched_app, + bool force_iph_off); + + friend NavigationHandleUserData; + + raw_ref<content::NavigationHandle> navigation_handle_; + webapps::AppId launched_app_; + bool force_iph_off_; + + NAVIGATION_HANDLE_USER_DATA_KEY_DECL(); +}; + +} // namespace web_app + +#endif // CHROME_BROWSER_UI_WEB_APPLICATIONS_WEB_APP_LAUNCH_NAVIGATION_HANDLE_USER_DATA_H_
diff --git a/chrome/browser/ui/web_applications/web_app_launch_utils.cc b/chrome/browser/ui/web_applications/web_app_launch_utils.cc index 6c16b75..8035751 100644 --- a/chrome/browser/ui/web_applications/web_app_launch_utils.cc +++ b/chrome/browser/ui/web_applications/web_app_launch_utils.cc
@@ -56,8 +56,6 @@ #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/web_applications/app_browser_controller.h" -#include "chrome/browser/ui/web_applications/navigation_capturing_information_forwarder.h" -#include "chrome/browser/ui/web_applications/navigation_capturing_navigation_handle_user_data.h" #include "chrome/browser/ui/web_applications/web_app_browser_controller.h" #include "chrome/browser/ui/web_applications/web_app_launch_process.h" #include "chrome/browser/ui/web_applications/web_app_launch_utils.h" @@ -119,15 +117,6 @@ namespace web_app { namespace { -// Causes all new auxiliary browser contexts to share the same window container -// type as where they were created from. For example, if an aux context was -// created from standalone PWA, then the new context will be created in a new -// window of the same PWA. -// If this is off, then all auxiliary contexts will be created as browser tabs. -const base::FeatureParam<bool> kEnableAuxContextKeepSameContainer{ - &features::kPwaNavigationCapturing, "aux_context_keep_same_container", - /*default_value=*/false}; - Browser* ReparentWebContentsIntoAppBrowser(content::WebContents* contents, Browser* target_browser, const webapps::AppId& app_id, @@ -254,88 +243,6 @@ return value; } -// Returns true if an auxiliary browsing context is getting created, so -// navigation should be done in the same container that it was triggered in. -bool IsAuxiliaryBrowsingContext(const NavigateParams& nav_params) { - if ((nav_params.contents_to_insert && - nav_params.contents_to_insert->HasOpener()) || - nav_params.opener) { - return true; - } - return false; -} - -bool ShouldEnqueueNavigationHandlingInfoForRedirects( - const NavigationHandlingInitialResult initial_result) { - switch (initial_result) { - case NavigationHandlingInitialResult::kBrowserTab: - case NavigationHandlingInitialResult::kForcedNewAppContextBrowserTab: - case NavigationHandlingInitialResult::kForcedNewAppContextAppWindow: - case NavigationHandlingInitialResult::kNavigateCapturedNewBrowserTab: - case NavigationHandlingInitialResult::kNavigateCapturingNavigateExisting: - case NavigationHandlingInitialResult::kNavigateCapturedNewAppWindow: - // To prevent the 'v1' throttle from enabling, still attach the navigation - // handling info for aux contexts. - case NavigationHandlingInitialResult::kAuxContext: - return true; - case NavigationHandlingInitialResult::kNotHandledByNavigationHandling: - return false; - } -} - -// Populate navigation handling information for redirects based on the initial -// result of navigation handling by the web apps system. -void MaybePopulateNavigationHandlingInfoForRedirects( - base::WeakPtr<content::NavigationHandle> navigation_handle, - content::WebContents* web_contents, - const web_app::NavigationCapturingRedirectionInfo& redirection_info, - std::optional<webapps::AppId> launched_app_id, - bool is_launching_in_app_window) { - CHECK(web_contents); - if (!ShouldEnqueueNavigationHandlingInfoForRedirects( - redirection_info.initial_nav_handling_result())) { - return; - } - - // Do not show iph when opening browser-tab-apps in a new browser tab, as this - // matches what is 'normal' - clicking on a link opens a new browser tab. - bool force_iph_off = - !is_launching_in_app_window && - redirection_info.initial_nav_handling_result() != - NavigationHandlingInitialResult::kNavigateCapturingNavigateExisting; - if (navigation_handle) { - web_app::NavigationCapturingNavigationHandleUserData:: - CreateForNavigationHandle(*navigation_handle, redirection_info, - std::move(launched_app_id), - /*force_iph_off=*/force_iph_off); - } else { - web_app::NavigationCapturingInformationForwarder::CreateForWebContents( - web_contents, redirection_info, std::move(launched_app_id), - /*force_iph_off=*/force_iph_off); - } -} - -// Keeping auxiliary contexts in an 'app' container was causing problems on -// initial Canary testing, see https://crbug.com/379181271 for more information. -// Either this will be rolled out separately or removed. -bool ShouldDisableAuxiliaryBrowsingContextHandling( - const std::optional<webapps::AppId>& source_browser_app_id, - const GURL& url) { - // This is however needed on ChromeOS to support the ChromeOsWebAppExperiments - // code, see ChromeOsWebAppExperimentsNavigationBrowserTest for tests with - // this on. -#if BUILDFLAG(IS_CHROMEOS) - if (source_browser_app_id.has_value() && - ::web_app::ChromeOsWebAppExperiments:: - IsNavigationCapturingReimplEnabledForSourceApp(*source_browser_app_id, - url)) { - return true; - } -#endif - return apps::features::IsNavigationCapturingReimplEnabled() && - kEnableAuxContextKeepSameContainer.Get(); -} - bool IsNavigationCapturingReimplExperimentEnabled( const std::optional<webapps::AppId>& current_browser_app_id, const GURL& url, @@ -491,78 +398,6 @@ } } -std::optional<webapps::AppId> GetWebAppControllingUrl( - Profile* profile, - const WebAppProvider* provider, - const GURL& url) { -#if BUILDFLAG(IS_CHROMEOS) - if (!apps::AppServiceProxyFactory::IsAppServiceAvailableForProfile(profile)) { - return std::nullopt; - } - return apps::FindAppIdsToLaunchForUrl( - apps::AppServiceProxyFactory::GetForProfile(profile), url) - .preferred; -#else - return provider->registrar_unsafe().FindAppThatCapturesLinksInScope(url); -#endif -} - -bool IsDispositionValidForNavigationCapturing( - WindowOpenDisposition disposition) { - switch (disposition) { - case WindowOpenDisposition::NEW_FOREGROUND_TAB: - case WindowOpenDisposition::NEW_BACKGROUND_TAB: - case WindowOpenDisposition::NEW_WINDOW: - return true; - case WindowOpenDisposition::UNKNOWN: - // Note: App popups are handled in browser_navigator.cc - case WindowOpenDisposition::NEW_POPUP: - case WindowOpenDisposition::CURRENT_TAB: - case WindowOpenDisposition::SINGLETON_TAB: - case WindowOpenDisposition::SAVE_TO_DISK: - case WindowOpenDisposition::OFF_THE_RECORD: - case WindowOpenDisposition::IGNORE_ACTION: - case WindowOpenDisposition::SWITCH_TO_TAB: - case WindowOpenDisposition::NEW_PICTURE_IN_PICTURE: - return false; - } -} - -bool IsPageTransitionValidForNavigationCapturing( - ui::PageTransition transition) { - switch (ui::PageTransitionStripQualifier(transition)) { - case ui::PAGE_TRANSITION_TYPED: - case ui::PAGE_TRANSITION_AUTO_TOPLEVEL: - case ui::PAGE_TRANSITION_AUTO_BOOKMARK: - case ui::PAGE_TRANSITION_AUTO_SUBFRAME: - case ui::PAGE_TRANSITION_MANUAL_SUBFRAME: - case ui::PAGE_TRANSITION_GENERATED: - case ui::PAGE_TRANSITION_RELOAD: - case ui::PAGE_TRANSITION_KEYWORD: - case ui::PAGE_TRANSITION_KEYWORD_GENERATED: - return false; - case ui::PAGE_TRANSITION_LINK: - case ui::PAGE_TRANSITION_FORM_SUBMIT: - break; - default: - NOTREACHED(base::NotFatalUntil::M135); - } - if (base::to_underlying(ui::PageTransitionGetQualifier(transition)) != 0) { - // Qualifiers indicate that this navigation was the result of a click on a - // forward/back button, typing in the URL bar, or client-side redirections. - // Don't handle any of those types of navigations. - return false; - } - return true; -} - -bool IsServiceWorkerClientOpenNavigation(const NavigateParams& params) { - return params.open_pwa_window_if_possible && - ui::PageTransitionCoreTypeIs(params.transition, - ui::PAGE_TRANSITION_AUTO_TOPLEVEL) && - params.disposition == WindowOpenDisposition::NEW_FOREGROUND_TAB; -} - void RecordDiyOrCraftedAppLaunch(const WebApp& web_app) { base::UmaHistogramEnumeration( "Launch.WebApp.DiyOrCrafted", @@ -571,193 +406,6 @@ } // namespace -// static -AppNavigationResult AppNavigationResult::CapturingDisabled() { - return AppNavigationResult( - /*capturing_feature_enabled=*/false, std::nullopt, - /*perform_app_handling_tasks_in_web_contents=*/false, - NavigationCapturingRedirectionInfo::Disabled(), base::Value::Dict()); -} - -// static -AppNavigationResult AppNavigationResult::CancelNavigation() { - return AppNavigationResult( - /*capturing_feature_enabled=*/false, - /*browser_tab_override=*/{{nullptr, -1}}, - /*perform_app_handling_tasks_in_web_contents=*/false, - NavigationCapturingRedirectionInfo::Disabled(), base::Value::Dict()); -} - -// static -AppNavigationResult AppNavigationResult::NoCapturingOverrideBrowser( - Browser* browser) { - return AppNavigationResult( - /*capturing_feature_enabled=*/false, - /*browser_tab_override=*/{{browser, -1}}, - /*perform_app_handling_tasks_in_web_contents=*/false, - NavigationCapturingRedirectionInfo::Disabled(), base::Value::Dict()); -} - -// static -AppNavigationResult AppNavigationResult::AuxiliaryContext( - WindowOpenDisposition disposition, - base::Value::Dict debug_data) { - return AppNavigationResult( - /*capturing_feature_enabled=*/true, /*browser_tab_override=*/std::nullopt, - /*perform_app_handling_tasks_in_web_contents=*/false, - NavigationCapturingRedirectionInfo::AuxiliaryContext( - /*source_browser_app_id=*/std::nullopt, - /*source_tab_app_id=*/std::nullopt, disposition), - std::move(debug_data)); -} - -// static -AppNavigationResult AppNavigationResult::AuxiliaryContextInAppWindow( - const webapps::AppId& source_browser_app_id, - std::optional<webapps::AppId> source_tab_app_id, - WindowOpenDisposition disposition, - Browser* app_browser, - base::Value::Dict debug_data) { - CHECK(app_browser->app_controller()); - return AppNavigationResult( - /*capturing_feature_enabled=*/true, - /*browser_tab_override=*/{{app_browser, -1}}, - /*perform_app_handling_tasks_in_web_contents=*/false, - NavigationCapturingRedirectionInfo::AuxiliaryContext( - source_browser_app_id, source_tab_app_id, disposition), - std::move(debug_data)); -} - -// static -AppNavigationResult -AppNavigationResult::NoInitialActionRedirectionHandlingEligible( - std::optional<webapps::AppId> source_browser_app_id, - std::optional<webapps::AppId> source_tab_app_id, - WindowOpenDisposition disposition, - Browser* navigation_params_browser, - base::Value::Dict debug_data) { - return AppNavigationResult( - /*capturing_feature_enabled=*/true, - /*browser_tab_override=*/std::nullopt, - /*perform_app_handling_tasks_in_web_contents=*/false, - NavigationCapturingRedirectionInfo:: - NoInitialActionRedirectionHandlingEligible( - source_browser_app_id, source_tab_app_id, disposition, - navigation_params_browser), - std::move(debug_data)); -} - -// static -AppNavigationResult AppNavigationResult::ForcedNewAppContext( - std::optional<webapps::AppId> source_browser_app_id, - std::optional<webapps::AppId> source_tab_app_id, - const webapps::AppId capturing_app_id, - blink::mojom::DisplayMode new_client_display_mode, - Browser* host_browser, - WindowOpenDisposition disposition, - Browser* navigation_params_browser, - base::Value::Dict debug_data) { - CHECK(WebAppRegistrar::IsSupportedDisplayModeForNavigationCapture( - new_client_display_mode)); - CHECK((new_client_display_mode != blink::mojom::DisplayMode::kBrowser) == - (!!host_browser->app_controller())); - CHECK(disposition == WindowOpenDisposition::NEW_BACKGROUND_TAB || - disposition == WindowOpenDisposition::NEW_WINDOW); - return AppNavigationResult( - /*capturing_feature_enabled=*/true, - /*browser_tab_override=*/{{host_browser, -1}}, - /*perform_app_handling_tasks_in_web_contents=*/true, - NavigationCapturingRedirectionInfo::ForcedNewContext( - source_browser_app_id, source_tab_app_id, capturing_app_id, - new_client_display_mode, disposition, navigation_params_browser), - std::move(debug_data)); -} - -// static -AppNavigationResult AppNavigationResult::CapturedNewClient( - std::optional<webapps::AppId> source_browser_app_id, - std::optional<webapps::AppId> source_tab_app_id, - const webapps::AppId capturing_app_id, - blink::mojom::DisplayMode new_client_display_mode, - Browser* host_browser, - WindowOpenDisposition disposition, - Browser* navigation_params_browser, - base::Value::Dict debug_data) { - CHECK(WebAppRegistrar::IsSupportedDisplayModeForNavigationCapture( - new_client_display_mode)); - CHECK((new_client_display_mode != blink::mojom::DisplayMode::kBrowser) == - (!!host_browser->app_controller())); - CHECK(disposition == WindowOpenDisposition::NEW_FOREGROUND_TAB); - return AppNavigationResult( - /*capturing_feature_enabled=*/true, - /*browser_tab_override=*/{{host_browser, -1}}, - /*perform_app_handling_tasks_in_web_contents=*/true, - NavigationCapturingRedirectionInfo::CapturedNewContext( - source_browser_app_id, source_tab_app_id, capturing_app_id, - new_client_display_mode, disposition, navigation_params_browser), - std::move(debug_data)); -} - -// static -AppNavigationResult AppNavigationResult::CapturedNavigateExisting( - std::optional<webapps::AppId> source_browser_app_id, - std::optional<webapps::AppId> source_tab_app_id, - const webapps::AppId capturing_app_id, - Browser* app_browser, - int browser_tab, - WindowOpenDisposition disposition, - Browser* navigation_params_browser, - base::Value::Dict debug_data) { - CHECK(disposition == WindowOpenDisposition::NEW_FOREGROUND_TAB); - CHECK(browser_tab != -1); - return AppNavigationResult( - /*capturing_feature_enabled=*/true, - /*browser_tab_override=*/{{app_browser, browser_tab}}, - /*perform_app_handling_tasks_in_web_contents=*/true, - NavigationCapturingRedirectionInfo::CapturedNavigateExisting( - source_browser_app_id, source_tab_app_id, capturing_app_id, - disposition, navigation_params_browser), - std::move(debug_data)); -} - -AppNavigationResult::AppNavigationResult(AppNavigationResult&&) = default; -AppNavigationResult& AppNavigationResult::operator=(AppNavigationResult&&) = - default; - -AppNavigationResult::AppNavigationResult( - bool capturing_feature_enabled, - std::optional<std::tuple<Browser*, int>> browser_tab_override, - bool perform_app_handling_tasks_in_web_contents, - const NavigationCapturingRedirectionInfo& redirection_info, - base::Value::Dict debug_value) - : capturing_feature_enabled_(capturing_feature_enabled), - browser_tab_override_(std::move(browser_tab_override)), - perform_app_handling_tasks_in_web_contents_( - perform_app_handling_tasks_in_web_contents), - redirection_info_(redirection_info), - debug_value_(std::move(debug_value)) { - debug_value_.Set("redirection_info", redirection_info_.ToDebugData()); - debug_value_.Set( - "initial_navigation_result", - base::Value::Dict() - .Set("capturing_feature_enabled", capturing_feature_enabled_) - .Set("browser_tab_override", - browser_tab_override_.has_value() - ? base::Value( - base::Value::Dict() - .Set("browser", base::ToString(std::get<Browser*>( - *browser_tab_override_))) - .Set("tab", std::get<int>(*browser_tab_override_))) - : base::Value("<none>")) - .Set("perform_app_handling_tasks_in_web_contents", - perform_app_handling_tasks_in_web_contents_) - .Set("creation_time", base::ToString(base::Time::Now()))); -} - -base::Value::Dict AppNavigationResult::TakeDebugData() { - return std::move(debug_value_); -} - void ReparentWebContentsIntoBrowserImpl(Browser* source_browser, content::WebContents* web_contents, Browser* target_browser, @@ -1473,419 +1121,6 @@ return result; } -AppNavigationResult MaybeHandleAppNavigation(const NavigateParams& params) { - Profile* profile = params.initiating_profile; - - if (!AreWebAppsUserInstallable(profile) || - Browser::GetCreationStatusForProfile(profile) != - Browser::CreationStatus::kOk || - !params.url.is_valid()) { - return AppNavigationResult::CapturingDisabled(); - } - - web_app::WebAppProvider* provider = - web_app::WebAppProvider::GetForWebApps(profile); - if (!provider) { - return AppNavigationResult::CapturingDisabled(); - } - web_app::WebAppRegistrar& registrar = provider->registrar_unsafe(); - - std::optional<webapps::AppId> source_browser_app_id = - params.browser && web_app::AppBrowserController::IsWebApp(params.browser) - ? std::optional(params.browser->app_controller()->app_id()) - : std::nullopt; - std::optional<webapps::AppId> controlling_app_id = - GetWebAppControllingUrl(profile, provider, params.url); - std::optional<DisplayMode> controlling_app_display_mode; - if (controlling_app_id) { - controlling_app_display_mode = - registrar.GetAppEffectiveDisplayMode(*controlling_app_id); - } - - // Only proceed as below if the navigation capturing is enabled. The flag in - // the redirection info has to store the result of this check, so that the - // logic in `OnWebAppNavigationAfterWebContentsCreation()` is skipped when not - // needed. - bool navigation_capturing_enabled = - IsNavigationCapturingReimplExperimentEnabled( - source_browser_app_id, params.url, controlling_app_id, - controlling_app_display_mode); - bool is_service_worker_clients_open_window = - IsServiceWorkerClientOpenNavigation(params); - - // TODO(https://crbug.com/382542907): Remove `open_pwa_window_if_possible` or - // make it IWA-specific. - bool is_service_worker_clients_open_window_with_nav_capturing = - is_service_worker_clients_open_window && navigation_capturing_enabled; - if (params.open_pwa_window_if_possible && - (!is_service_worker_clients_open_window_with_nav_capturing || - params.force_open_pwa_window)) { - std::optional<webapps::AppId> app_id = - web_app::FindInstalledAppWithUrlInScope(profile, params.url, - /*window_only=*/true); - if (!app_id && params.force_open_pwa_window) { - // In theory |force_open_pwa_window| should only be set if we know a - // matching PWA is installed. However, we can reach here if - // `WebAppRegistrar` hasn't finished starting yet, which can happen if - // Chrome is launched with the URL of an isolated app as an argument. - // This isn't a supported way to launch isolated apps, so we can cancel - // the navigation, but if we want to support it in the future we'll need - // to block until `WebAppRegistrar` is loaded. - return AppNavigationResult::CancelNavigation(); - } - if (app_id) { - // Reuse the existing browser for in-app same window navigations. - bool navigating_same_app = - params.browser && - web_app::AppBrowserController::IsForWebApp(params.browser, *app_id); - if (navigating_same_app) { - if (params.disposition == WindowOpenDisposition::CURRENT_TAB) { - return AppNavigationResult::NoCapturingOverrideBrowser( - params.browser); - } - - // If the browser window does not yet have any tabs, and we are - // attempting to add the first tab to it, allow for it to be reused. - bool navigating_new_tab = - params.disposition == WindowOpenDisposition::NEW_FOREGROUND_TAB || - params.disposition == WindowOpenDisposition::NEW_BACKGROUND_TAB; - bool browser_has_no_tabs = - params.browser && params.browser->tab_strip_model()->empty(); - if (navigating_new_tab && browser_has_no_tabs) { - return AppNavigationResult::NoCapturingOverrideBrowser( - params.browser); - } - } - - auto GetOriginSpecified = [](const NavigateParams& params) { - return params.window_features.has_x && params.window_features.has_y - ? Browser::ValueSpecified::kSpecified - : Browser::ValueSpecified::kUnspecified; - }; - - // App popups are handled in the switch statement in - // `GetBrowserAndTabForDisposition()`. - if (params.disposition == WindowOpenDisposition::NEW_POPUP) { - return AppNavigationResult::CapturingDisabled(); - } - std::string app_name = web_app::GenerateApplicationNameFromAppId(*app_id); - // Installed PWAs are considered trusted. - Browser::CreateParams browser_params = - Browser::CreateParams::CreateForApp(app_name, /*trusted_source=*/true, - params.window_features.bounds, - profile, params.user_gesture); - browser_params.initial_origin_specified = GetOriginSpecified(params); - Browser* browser = Browser::Create(browser_params); - return AppNavigationResult::NoCapturingOverrideBrowser(browser); - } - } - - // Below here handles the states outlined in - // https://bit.ly/pwa-navigation-capturing - if (!navigation_capturing_enabled) { - return AppNavigationResult::CapturingDisabled(); - } - if (params.started_from_context_menu || - params.pwa_navigation_capturing_force_off || - params.tabstrip_index != -1) { - return AppNavigationResult::CapturingDisabled(); - } - if (!IsDispositionValidForNavigationCapturing(params.disposition)) { - return AppNavigationResult::CapturingDisabled(); - } - // The service worker clients API currently uses - // PAGE_TRANSITION_AUTO_TOPLEVEL, which is normally considered invalid for - // navigation capturing. Explicitly allow that. - if (!is_service_worker_clients_open_window && - !IsPageTransitionValidForNavigationCapturing(params.transition)) { - return AppNavigationResult::CapturingDisabled(); - } - bool is_for_new_browser = - params.browser && params.browser->tab_strip_model()->count() == 0 && - (params.disposition == WindowOpenDisposition::NEW_FOREGROUND_TAB || - params.disposition == WindowOpenDisposition::NEW_BACKGROUND_TAB); - if (is_for_new_browser) { - // Some calls to `Navigate` populate a newly created browser in - // `params.browser`, with no tabs. Callers can assume that browser is used, - // so enabling capturing cause the user to see a browser with no tabs. We - // cannot simply close it, as sometimes callers then use/reference that - // browser. While that is likely a bug (callers should use the - // `params.browser` to be compatible with other logic that changes the - // browser), disable capturing in this case for now. - return AppNavigationResult::CapturingDisabled(); - } - - // Ensure that we proceed for a `controlling_app_display_mode` to be - // navigation captured only for the use-cases that are supported. - if (controlling_app_display_mode) { - CHECK(WebAppRegistrar::IsSupportedDisplayModeForNavigationCapture( - *controlling_app_display_mode)); - } - - base::Value::Dict debug_data; - content::WebContents* source_contents = params.source_contents; - std::optional<webapps::AppId> source_contents_app_id = - source_contents ? base::OptionalFromPtr( - WebAppTabHelper::GetAppId(params.source_contents)) - : std::nullopt; - std::optional<ClientModeAndBrowser> client_mode_and_browser; - if (controlling_app_id) { - client_mode_and_browser = GetEffectiveClientModeAndBrowserForCapturing( - *profile, *controlling_app_id, source_contents_app_id, - /*ignore_browser_tabs_for_standalone_apps=*/false, - /*navigate_params_requested_browser=*/params.browser); - debug_data.Set( - "effective_client_mode", - base::ToString(client_mode_and_browser->effective_client_mode)); - CHECK(client_mode_and_browser->effective_client_mode != - LaunchHandler::ClientMode::kAuto); - debug_data.Set("controlling_app_host_browser", - client_mode_and_browser->browser - ? base::ToString(client_mode_and_browser->browser) - : "<none>"); - debug_data.Set("controlling_app_host_tab", - client_mode_and_browser->tab_index.has_value() - ? base::ToString(*client_mode_and_browser->tab_index) - : "<none>"); - } - - debug_data.Set("referrer.url", params.referrer.url.possibly_invalid_spec()); - debug_data.Set( - "source_contents.url", - source_contents - ? source_contents->GetLastCommittedURL().possibly_invalid_spec() - : "<nullptr>"); - debug_data.Set("source_contents.app_id", - source_contents_app_id.value_or("<none>")); - - debug_data.Set("controlling_app_id", controlling_app_id.value_or("<none>")); - debug_data.Set("controlling_app_display_mode", - base::ToString(controlling_app_display_mode.value_or( - DisplayMode::kUndefined))); - debug_data.Set("params.browser", base::ToString(params.browser.get())); - - debug_data.Set("params.url", params.url.possibly_invalid_spec()); - debug_data.Set("params.disposition", base::ToString(params.disposition)); - debug_data.Set("params.opener", params.opener != nullptr); - debug_data.Set("params.contents_to_insert", - base::ToString(params.contents_to_insert.get())); - debug_data.Set("source_browser_app_id", - source_browser_app_id.value_or("<none>")); - debug_data.Set("params.transition", - ui::PageTransitionGetCoreTransitionString( - ui::PageTransitionStripQualifier(params.transition))); - debug_data.Set( - "params.transition.qualifiers", - static_cast<int>(ui::PageTransitionGetQualifier(params.transition))); - - const bool is_user_modified_click = - params.disposition == WindowOpenDisposition::NEW_WINDOW || - params.disposition == WindowOpenDisposition::NEW_BACKGROUND_TAB; - - debug_data.Set("is_user_modified_click", is_user_modified_click); - - // Case: Any click (user modified or non-modified) with auxiliary browsing - // context. Only needs to be handled if it is triggered in the context of an - // app browser. - if (IsAuxiliaryBrowsingContext(params)) { - if (!ShouldDisableAuxiliaryBrowsingContextHandling(source_browser_app_id, - params.url)) { - return AppNavigationResult::CapturingDisabled(); - } - debug_data.Set("is_auxiliary_browsing_context", true); - if (source_browser_app_id.has_value()) { - Browser* app_window = CreateWebAppWindowFromNavigationParams( - *source_browser_app_id, params, - params.disposition == WindowOpenDisposition::NEW_POPUP); - - return AppNavigationResult::AuxiliaryContextInAppWindow( - *source_browser_app_id, source_contents_app_id, params.disposition, - app_window, std::move(debug_data)); - } - return AppNavigationResult::AuxiliaryContext(params.disposition, - std::move(debug_data)); - } - debug_data.Set("is_auxiliary_browsing_context", false); - - // If no app controls the the target url, then there cannot be any further - // capturing logic unless a redirect occurs. - if (!controlling_app_id) { - return AppNavigationResult::NoInitialActionRedirectionHandlingEligible( - source_browser_app_id, source_contents_app_id, params.disposition, - params.browser, std::move(debug_data)); - } - CHECK(controlling_app_display_mode); - CHECK(client_mode_and_browser); - const webapps::AppId& app_id = *controlling_app_id; - blink::mojom::DisplayMode app_display_mode = *controlling_app_display_mode; - LaunchHandler::ClientMode client_mode = - client_mode_and_browser->effective_client_mode; - - // Case: User-modified clicks. - if (is_user_modified_click) { - // The default behavior is only modified if the source is an app browser or - // the controlling app's display mode is 'browser'. - if (!source_browser_app_id.has_value() && - app_display_mode != DisplayMode::kBrowser) { - return AppNavigationResult::NoInitialActionRedirectionHandlingEligible( - source_browser_app_id, source_contents_app_id, params.disposition, - params.browser, std::move(debug_data)); - } - // Case: Shift-clicks with a new top level browsing context. - if (params.disposition == WindowOpenDisposition::NEW_WINDOW) { - Browser* app_host_window; - if (app_display_mode == DisplayMode::kBrowser) { - app_host_window = Browser::Create( - Browser::CreateParams(profile, params.user_gesture)); - } else { - app_host_window = - CreateWebAppWindowFromNavigationParams(app_id, params); - } - return AppNavigationResult::ForcedNewAppContext( - source_browser_app_id, source_contents_app_id, app_id, - app_display_mode, app_host_window, params.disposition, params.browser, - std::move(debug_data)); - } - - bool is_in_source_app_with_url_in_scope = - source_browser_app_id - ? registrar.IsUrlInAppScope(params.url, *source_browser_app_id) - : false; - - // Case: Middle clicks with a new top level browsing context. - if (params.disposition == WindowOpenDisposition::NEW_BACKGROUND_TAB && - (app_display_mode == DisplayMode::kBrowser || - (app_id == source_browser_app_id && - is_in_source_app_with_url_in_scope))) { - if (source_browser_app_id.has_value() && - !params.browser->app_controller()->ShouldHideNewTabButton()) { - // Apps that support tabbed mode can open a new tab in the current app - // browser itself. - return AppNavigationResult::ForcedNewAppContext( - source_browser_app_id, source_contents_app_id, app_id, - app_display_mode, params.browser, params.disposition, - params.browser, std::move(debug_data)); - } - Browser* app_host_window; - if (app_display_mode == DisplayMode::kBrowser) { - // For a 'new tab' with the 'browser' requested display mode, prefer - // using an existing browser window. - app_host_window = client_mode_and_browser->browser - ? client_mode_and_browser->browser.get() - : Browser::Create(Browser::CreateParams( - profile, params.user_gesture)); - } else { - app_host_window = - CreateWebAppWindowFromNavigationParams(app_id, params); - } - return AppNavigationResult::ForcedNewAppContext( - source_browser_app_id, source_contents_app_id, app_id, - app_display_mode, app_host_window, params.disposition, params.browser, - std::move(debug_data)); - } - return AppNavigationResult::NoInitialActionRedirectionHandlingEligible( - source_browser_app_id, source_contents_app_id, params.disposition, - params.browser, std::move(debug_data)); - } - - if (params.disposition != WindowOpenDisposition::NEW_FOREGROUND_TAB) { - return AppNavigationResult::CapturingDisabled(); - } - // Case: Left click, non-user-modified. Capturable. - - // Opening in non-browser-tab requires OS integration. Since os integration - // cannot be triggered synchronously, treat this as opening in browser. - if (registrar.GetInstallState(app_id) == - proto::INSTALLED_WITHOUT_OS_INTEGRATION) { - app_display_mode = blink::mojom::DisplayMode::kBrowser; - } - - // Prevent-close requires only focusing the existing tab, and never - // navigating. - if (registrar.IsPreventCloseEnabled(app_id) && - !registrar.IsTabbedWindowModeEnabled(app_id)) { - client_mode = LaunchHandler::ClientMode::kFocusExisting; - } - debug_data.Set("client_mode", base::ToString(client_mode)); - - // Focus existing. - if (client_mode == LaunchHandler::ClientMode::kFocusExisting) { - CHECK(client_mode_and_browser->browser); - CHECK(client_mode_and_browser->tab_index.has_value()); - CHECK_NE(*client_mode_and_browser->tab_index, -1); - content::WebContents* contents = - client_mode_and_browser->browser->tab_strip_model()->GetWebContentsAt( - *client_mode_and_browser->tab_index); - CHECK(contents); - FocusAppContainer(client_mode_and_browser->browser, - *client_mode_and_browser->tab_index); - - // Abort the navigation by returning a `nullptr`. Because this means - // `OnWebAppNavigationAfterWebContentsCreation` won't be called, enqueue - // the launch params instantly and record the debug data. - EnqueueLaunchParams(contents, app_id, params.url, - /*wait_for_navigation_to_complete=*/false); - provider->navigation_capturing_log().StoreNavigationCapturedDebugData( - base::Value(std::move(debug_data))); - - MaybeShowNavigationCaptureIph(app_id, profile, - client_mode_and_browser->browser); - - // TODO(crbug.com/336371044): Update RecordLaunchMetrics() to also work - // with apps that open in a new browser tab. - RecordLaunchMetrics(app_id, apps::LaunchContainer::kLaunchContainerWindow, - apps::LaunchSource::kFromNavigationCapturing, - params.url, contents); - return AppNavigationResult::CancelNavigation(); - } - - // Navigate existing. - if (client_mode == LaunchHandler::ClientMode::kNavigateExisting) { - CHECK(client_mode_and_browser->browser); - CHECK(client_mode_and_browser->tab_index.has_value()); - return AppNavigationResult::CapturedNavigateExisting( - source_browser_app_id, source_contents_app_id, app_id, - client_mode_and_browser->browser, *client_mode_and_browser->tab_index, - params.disposition, params.browser, std::move(debug_data)); - } - - // Navigate new. - CHECK(client_mode == LaunchHandler::ClientMode::kNavigateNew); - - Browser* host_window = nullptr; - switch (app_display_mode) { - case blink::mojom::DisplayMode::kBrowser: - if (client_mode_and_browser->browser) { - host_window = client_mode_and_browser->browser; - } else { - host_window = Browser::Create( - Browser::CreateParams(profile, params.user_gesture)); - } - break; - case blink::mojom::DisplayMode::kMinimalUi: - case blink::mojom::DisplayMode::kStandalone: - case blink::mojom::DisplayMode::kWindowControlsOverlay: - case blink::mojom::DisplayMode::kBorderless: - host_window = CreateWebAppWindowFromNavigationParams(app_id, params); - break; - case blink::mojom::DisplayMode::kTabbed: - if (client_mode_and_browser->browser) { - host_window = client_mode_and_browser->browser; - } else { - host_window = CreateWebAppWindowFromNavigationParams(app_id, params); - } - break; - case blink::mojom::DisplayMode::kUndefined: - case blink::mojom::DisplayMode::kPictureInPicture: - case blink::mojom::DisplayMode::kFullscreen: - NOTREACHED(); - } - - return AppNavigationResult::CapturedNewClient( - source_browser_app_id, source_contents_app_id, app_id, app_display_mode, - host_window, params.disposition, params.browser, std::move(debug_data)); -} - void EnqueueLaunchParams(content::WebContents* contents, const webapps::AppId& app_id, const GURL& url, @@ -1899,56 +1134,6 @@ std::move(launch_params)); } -void OnWebAppNavigationAfterWebContentsCreation( - web_app::AppNavigationResult app_navigation_result, - const NavigateParams& params, - base::WeakPtr<content::NavigationHandle> navigation_handle) { - if (!app_navigation_result.capturing_feature_enabled()) { - // Don't attach info for redirects nor perform any other logic below if the - // capturing wasn't enabled for the navigation. - return; - } - CHECK(AreWebAppsUserInstallable(params.initiating_profile)); - CHECK(!(params.force_open_pwa_window && params.open_pwa_window_if_possible)); - - std::optional<webapps::AppId> first_navigation_app_id = - app_navigation_result.redirection_info().first_navigation_app_id(); - MaybePopulateNavigationHandlingInfoForRedirects( - navigation_handle, params.navigated_or_inserted_contents, - app_navigation_result.redirection_info(), - app_navigation_result.browser_tab_override().has_value() - ? first_navigation_app_id - : std::nullopt, - /*is_launching_in_app_window=*/ - WebAppBrowserController::IsWebApp(params.browser)); - - base::Value::Dict debug_value = app_navigation_result.TakeDebugData(); - web_app::WebAppProvider* provider = - web_app::WebAppProvider::GetForWebApps(params.initiating_profile); - - // Exclude all cases where there isn't navigation capturing logic occurring. - if (!app_navigation_result.browser_tab_override()) { - // Also record debug information for ALL navigations if expensive DCHECKs - // are enabled. -#if EXPENSIVE_DCHECKS_ARE_ON() - debug_value.Set("handled_by_app", false); - debug_value.Set("result.browser", base::ToString(params.browser.get())); - debug_value.Set("result.tab_index", params.tabstrip_index); - provider->navigation_capturing_log().StoreNavigationCapturedDebugData( - base::Value(std::move(debug_value))); -#endif - return; - } - CHECK(params.browser); - - debug_value.Set("handled_by_app", true); - debug_value.Set("params.navigated_or_inserted_contents", - base::ToString(params.navigated_or_inserted_contents)); - debug_value.Set("params.browser", base::ToString(params.browser)); - provider->navigation_capturing_log().StoreNavigationCapturedDebugData( - base::Value(std::move(debug_value))); -} - void FocusAppContainer(Browser* browser, int tab_index) { CHECK(browser); // ActivateTabAt() does not work for PWA windows, so activation is mimicked by
diff --git a/chrome/browser/ui/web_applications/web_app_launch_utils.h b/chrome/browser/ui/web_applications/web_app_launch_utils.h index 3717c5b..381c9884 100644 --- a/chrome/browser/ui/web_applications/web_app_launch_utils.h +++ b/chrome/browser/ui/web_applications/web_app_launch_utils.h
@@ -16,7 +16,6 @@ #include "base/memory/weak_ptr.h" #include "base/values.h" #include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/web_applications/navigation_capturing_navigation_handle_user_data.h" #include "chrome/browser/web_applications/web_app_ui_manager.h" #include "components/services/app_service/public/cpp/app_launch_util.h" #include "components/webapps/common/web_app_id.h" @@ -63,126 +62,6 @@ kMaxValue = kCrafted, }; -// Returns information useful for the browser to show UI affordances if a web -// app handles the navigation. -class AppNavigationResult { - STACK_ALLOCATED(); - - public: - // No navigation capturing will happen for this navigation. - static AppNavigationResult CapturingDisabled(); - // The navigation itself will be cancelled. - static AppNavigationResult CancelNavigation(); - - static AppNavigationResult NoCapturingOverrideBrowser(Browser* browser); - - // TODO(crbug.com/370856876): Possibly remove `disposition`. - static AppNavigationResult AuxiliaryContext(WindowOpenDisposition disposition, - base::Value::Dict debug_data); - - // TODO(crbug.com/370856876): Possibly remove `source_browser_app_id` and - // `disposition`. - static AppNavigationResult AuxiliaryContextInAppWindow( - const webapps::AppId& source_browser_app_id, - std::optional<webapps::AppId> source_tab_app_id, - WindowOpenDisposition disposition, - Browser* app_browser, - base::Value::Dict debug_data); - - // Populates redirection info in case future redirects apply to an - // application. - static AppNavigationResult NoInitialActionRedirectionHandlingEligible( - std::optional<webapps::AppId> source_browser_app_id, - std::optional<webapps::AppId> source_tab_app_id, - WindowOpenDisposition disposition, - Browser* navigation_params_browser, - base::Value::Dict debug_data); - - // Create AppNavigationResult for a navigation triggered by user modified link - // clicks that creates a new app container. - static AppNavigationResult ForcedNewAppContext( - std::optional<webapps::AppId> source_browser_app_id, - std::optional<webapps::AppId> source_tab_app_id, - const webapps::AppId capturing_app_id, - blink::mojom::DisplayMode new_client_display_mode, - Browser* host_browser, - WindowOpenDisposition disposition, - Browser* navigation_params_browser, - base::Value::Dict debug_data); - - // Create AppNavigationResult for a navigation that is captured by non user - // modified link clicks that launch a new app container (either window or - // tab). - static AppNavigationResult CapturedNewClient( - std::optional<webapps::AppId> source_browser_app_id, - std::optional<webapps::AppId> source_tab_app_id, - const webapps::AppId capturing_app_id, - blink::mojom::DisplayMode new_client_display_mode, - Browser* host_browser, - WindowOpenDisposition disposition, - Browser* navigation_params_browser, - base::Value::Dict debug_data); - - // Create AppNavigationResult for a navigation that is captured by non user - // modified link clicks that uses an existing app container (either window or - // tab). - static AppNavigationResult CapturedNavigateExisting( - std::optional<webapps::AppId> source_browser_app_id, - std::optional<webapps::AppId> source_tab_app_id, - const webapps::AppId capturing_app_id, - Browser* app_browser, - int browser_tab, - WindowOpenDisposition disposition, - Browser* navigation_params_browser, - base::Value::Dict debug_data); - - AppNavigationResult(AppNavigationResult&&); - AppNavigationResult& operator=(AppNavigationResult&&); - - // If false, then `OnWebAppNavigationAfterWebContentsCreation() exits early`. - bool capturing_feature_enabled() const { return capturing_feature_enabled_; } - - // The browser instance to perform navigation in, and the tab inside the - // browser if overridden by the web app system. If std::nullopt, performs the - // default navigation behavior in browser_navigator.cc. - const std::optional<std::tuple<Browser*, int>>& browser_tab_override() const { - return browser_tab_override_; - } - - // True if the `MaybeHandleAppNavigation` considered this navigation to - // be capturable, and the resulting navigation should be considered a launch - // for the given app (and do things like enqueue launch params and show IPH). - bool perform_app_handling_tasks_in_web_contents() const { - return perform_app_handling_tasks_in_web_contents_; - } - - // Information necessary for handling redirection after a response is received - // as part of a navigation. - const NavigationCapturingRedirectionInfo& redirection_info() const { - return redirection_info_; - } - - base::Value::Dict TakeDebugData(); - - private: - AppNavigationResult( - bool capturing_feature_enabled, - std::optional<std::tuple<Browser*, int>> browser_tab_override, - bool perform_app_handling_tasks_in_web_contents, - const NavigationCapturingRedirectionInfo& redirection_info, - base::Value::Dict debug_value); - - bool capturing_feature_enabled_ = false; - - std::optional<std::tuple<Browser*, int>> browser_tab_override_; - bool perform_app_handling_tasks_in_web_contents_ = false; - - NavigationCapturingRedirectionInfo redirection_info_; - - // Debug information persisted to chrome://web-app-internals. - base::Value::Dict debug_value_; -}; - std::optional<webapps::AppId> GetWebAppForActiveTab(const Browser* browser); // Clears navigation history prior to user entering app scope. @@ -303,14 +182,6 @@ bool ignore_browser_tabs_for_standalone_apps, Browser* navigate_params_requested_browser); -// Returns an AppNavigationResult with pertinent details on how to handle a -// navigation if the web app system can do so. If not, the -// `browser_tab_override` is set to be std::nullopt so that ::Navigate() inside -// the browser_navigator code can pick this up. This function may create a -// browser instance, an app window or a new tab as needed. -AppNavigationResult MaybeHandleAppNavigation( - const NavigateParams& navigate_params); - // Will enqueue the given url in the launch params for this web contents. Does // not check if the url is within scope of the app. void EnqueueLaunchParams(content::WebContents* contents, @@ -318,16 +189,6 @@ const GURL& url, bool wait_for_navigation_to_complete); -// Handle navigation-related tasks for the app, like enqueuing launch params, -// showing a navigation capturing IPH bubble and storing information necessary -// for handling redirections in the current `WebContents` or `NavigationHandle`, -// after the appropriate app-scoped `WebContents` has been identified and -// prepared for navigation. -void OnWebAppNavigationAfterWebContentsCreation( - web_app::AppNavigationResult app_navigation_result, - const NavigateParams& params, - base::WeakPtr<content::NavigationHandle> navigation_handle); - // Focus the app container depending on whether the `browser` is an app window // or if it is a normal tabbed browser. `browser` shouldn't be a nullptr, and // the `tab_index` should be a valid index for a tab inside `browser`.
diff --git a/chrome/browser/web_applications/BUILD.gn b/chrome/browser/web_applications/BUILD.gn index fb712e1..5ef5c6ea 100644 --- a/chrome/browser/web_applications/BUILD.gn +++ b/chrome/browser/web_applications/BUILD.gn
@@ -1073,7 +1073,6 @@ "isolated_web_apps/isolated_web_app_url_loader_factory_browsertest.cc", "isolated_web_apps/key_distribution/iwa_key_distribution_component_installer_browsertest.cc", "manifest_update_manager_browsertest.cc", - "navigation_capturing_data_transfer_browsertest.cc", "navigation_capturing_forced_off_browsertest.cc", "policy/web_app_policy_manager_browsertest.cc", "preinstalled_web_app_manager_browsertest.cc",
diff --git a/chrome/browser/web_applications/navigation_capturing_data_transfer_browsertest.cc b/chrome/browser/web_applications/navigation_capturing_data_transfer_browsertest.cc deleted file mode 100644 index 7c8131d5..0000000 --- a/chrome/browser/web_applications/navigation_capturing_data_transfer_browsertest.cc +++ /dev/null
@@ -1,384 +0,0 @@ -// Copyright 2024 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <map> -#include <memory> -#include <string> - -#include "base/test/scoped_feature_list.h" -#include "base/types/expected.h" -#include "build/build_config.h" -#include "chrome/browser/apps/link_capturing/link_capturing_feature_test_support.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/browser_commands.h" -#include "chrome/browser/ui/web_applications/navigation_capturing_information_forwarder.h" -#include "chrome/browser/ui/web_applications/navigation_capturing_navigation_handle_user_data.h" -#include "chrome/browser/ui/web_applications/test/web_app_browsertest_util.h" -#include "chrome/browser/ui/web_applications/web_app_browsertest_base.h" -#include "chrome/browser/web_applications/test/web_app_install_test_utils.h" -#include "chrome/test/base/ui_test_utils.h" -#include "components/webapps/common/web_app_id.h" -#include "content/public/browser/navigation_handle.h" -#include "content/public/browser/navigation_handle_user_data.h" -#include "content/public/browser/web_contents.h" -#include "content/public/browser/web_contents_observer.h" -#include "content/public/common/content_features.h" -#include "content/public/test/browser_test.h" -#include "content/public/test/browser_test_utils.h" -#include "net/test/embedded_test_server/embedded_test_server.h" -#include "third_party/blink/public/mojom/manifest/manifest_launch_handler.mojom-shared.h" -#include "ui/base/window_open_disposition.h" - -namespace web_app { - -namespace { - -constexpr char kStartPageScopeA[] = - "/banners/link_capturing/scope_a/start.html"; -constexpr char kDestinationPageScopeB[] = - "/banners/link_capturing/scope_b/destination.html"; -constexpr char kToSiteATargetBlankNoopener[] = "id-LINK-A_TO_A-BLANK-NO_OPENER"; -constexpr char kToSiteATargetBlankWithOpener[] = "id-LINK-A_TO_A-BLANK-OPENER"; -constexpr char kToSiteBTargetBlankNoopener[] = "id-LINK-A_TO_B-BLANK-NO_OPENER"; -constexpr char kToSiteBTargetBlankWithOpener[] = "id-LINK-A_TO_B-BLANK-OPENER"; - -class NavigationCompletionAwaiter : public content::WebContentsObserver, - public ui_test_utils::AllTabsObserver { - public: - explicit NavigationCompletionAwaiter(content::WebContents* web_contents) - : content::WebContentsObserver(web_contents) { - AddAllBrowsers(); - } - ~NavigationCompletionAwaiter() override = default; - - void DidFinishNavigation(content::NavigationHandle* handle) override { - auto* navigation_handle_data = - web_app::NavigationCapturingNavigationHandleUserData:: - GetForNavigationHandle(*handle); - if (navigation_handle_data) { - redirection_info_ = navigation_handle_data->redirection_info(); - } - ConditionMet(); - } - - void AwaitNavigationCompletion() { Wait(); } - - std::optional<NavigationCapturingRedirectionInfo> - GetRedirectionInfoForNavigation() { - return redirection_info_; - } - - // AllTabsObserver override: - std::unique_ptr<base::CheckedObserver> ProcessOneContents( - content::WebContents* web_contents) override { - // Stop observing the current `WebContents` if a new one has been created, - // so that we can process the `WebContents` navigation completed in. - if (content::WebContentsObserver::IsInObserverList()) { - Observe(nullptr); - } - Observe(web_contents); - return nullptr; - } - - private: - std::optional<NavigationCapturingRedirectionInfo> redirection_info_; -}; - -class NavigationCapturingDataTransferBrowserTest - : public WebAppBrowserTestBase { - public: - NavigationCapturingDataTransferBrowserTest() { - std::map<std::string, std::string> parameters; - parameters["link_capturing_state"] = "reimpl_default_on"; - feature_list_.InitAndEnableFeatureWithParameters( - features::kPwaNavigationCapturing, parameters); - } - - ~NavigationCapturingDataTransferBrowserTest() override = default; - - void SetUpOnMainThread() override { - WebAppBrowserTestBase::SetUpOnMainThread(); - ASSERT_TRUE(embedded_test_server()->Start()); - } - - protected: - GURL GetStartUrl() { - return embedded_test_server()->GetURL(kStartPageScopeA); - } - - GURL GetDestinationUrl() { - return embedded_test_server()->GetURL(kDestinationPageScopeB); - } - - webapps::AppId InstallTestWebApp( - const GURL& start_url, - blink::mojom::ManifestLaunchHandler_ClientMode client_mode = - blink::mojom::ManifestLaunchHandler_ClientMode::kAuto) { - auto web_app_info = - web_app::WebAppInstallInfo::CreateWithStartUrlForTesting(start_url); - web_app_info->user_display_mode = - web_app::mojom::UserDisplayMode::kStandalone; - web_app_info->launch_handler = blink::Manifest::LaunchHandler(client_mode); - web_app_info->scope = start_url.GetWithoutFilename(); - web_app_info->display_mode = blink::mojom::DisplayMode::kStandalone; - const webapps::AppId app_id = web_app::test::InstallWebApp( - browser()->profile(), std::move(web_app_info)); -#if BUILDFLAG(IS_CHROMEOS) - EXPECT_EQ(apps::test::EnableLinkCapturingByUser(profile(), app_id), - base::ok()); -#endif - return app_id; - } - - Browser* TriggerNavigationCapturingNewAppWindow( - content::WebContents* contents, - test::ClickMethod click, - const std::string& elementId) { - ui_test_utils::BrowserChangeObserver browser_added_waiter( - nullptr, ui_test_utils::BrowserChangeObserver::ChangeType::kAdded); - test::SimulateClickOnElement(contents, elementId, click); - - Browser* app_browser = browser_added_waiter.Wait(); - EXPECT_NE(browser(), app_browser); - return app_browser; - } - - content::WebContents* OpenStartPageInApp(const webapps::AppId& app_id) { - content::DOMMessageQueue message_queue; - Browser* app_browser = - web_app::LaunchWebAppBrowser(browser()->profile(), app_id); - content::WebContents* contents = - app_browser->tab_strip_model()->GetActiveWebContents(); - - auto result = apps::test::WaitForNavigationFinishedMessage(message_queue); - EXPECT_TRUE(result); - if (!result) { - return nullptr; - } - return contents; - } - - content::WebContents* OpenStartPageInTab() { - content::DOMMessageQueue message_queue; - EXPECT_TRUE(ui_test_utils::NavigateToURL( - browser(), embedded_test_server()->GetURL(kStartPageScopeA))); - - auto result = apps::test::WaitForNavigationFinishedMessage(message_queue); - EXPECT_TRUE(result); - if (!result) { - return nullptr; - } - return browser()->tab_strip_model()->GetActiveWebContents(); - } - - NavigationCapturingInformationForwarder* GetForwarderForWebContents( - content::WebContents* contents) { - if (!contents) { - return nullptr; - } - return NavigationCapturingInformationForwarder::FromWebContents(contents); - } - - private: - base::test::ScopedFeatureList feature_list_; -}; - -IN_PROC_BROWSER_TEST_F(NavigationCapturingDataTransferBrowserTest, - LeftClickNewWebContentsGetsCorrectDisposition) { - const webapps::AppId app_id = InstallTestWebApp(GetDestinationUrl()); - - content::WebContents* contents = OpenStartPageInTab(); - ASSERT_NE(nullptr, contents); - NavigationCompletionAwaiter nav_awaiter(contents); - - Browser* app_browser = TriggerNavigationCapturingNewAppWindow( - contents, test::ClickMethod::kLeftClick, kToSiteBTargetBlankNoopener); - nav_awaiter.AwaitNavigationCompletion(); - ASSERT_NE(nullptr, app_browser); - ASSERT_TRUE(nav_awaiter.GetRedirectionInfoForNavigation().has_value()); - - NavigationCapturingRedirectionInfo redirection_info = - *nav_awaiter.GetRedirectionInfoForNavigation(); - - // Triggered from a tab and not an app window. - EXPECT_FALSE(redirection_info.source_browser_app_id().has_value()); - EXPECT_FALSE(redirection_info.source_tab_app_id().has_value()); - EXPECT_EQ(NavigationHandlingInitialResult::kNavigateCapturedNewAppWindow, - redirection_info.initial_nav_handling_result()); - EXPECT_EQ(WindowOpenDisposition::NEW_FOREGROUND_TAB, - redirection_info.disposition()); - EXPECT_TRUE(redirection_info.first_navigation_app_id().has_value()); - EXPECT_EQ(app_id, *redirection_info.first_navigation_app_id()); - - // Post navigation, the WebContentsUserData instances should be cleaned up. - EXPECT_THAT(GetForwarderForWebContents( - app_browser->tab_strip_model()->GetActiveWebContents()), - testing::IsNull()); -} - -IN_PROC_BROWSER_TEST_F(NavigationCapturingDataTransferBrowserTest, - LeftClickNavigateExistingOpensNavigateNew) { - const webapps::AppId app_id = InstallTestWebApp( - GetDestinationUrl(), - blink::mojom::ManifestLaunchHandler_ClientMode::kNavigateExisting); - - content::WebContents* contents = OpenStartPageInTab(); - ASSERT_NE(nullptr, contents); - NavigationCompletionAwaiter nav_awaiter(contents); - - Browser* app_browser = TriggerNavigationCapturingNewAppWindow( - contents, test::ClickMethod::kLeftClick, kToSiteBTargetBlankNoopener); - nav_awaiter.AwaitNavigationCompletion(); - ASSERT_NE(nullptr, app_browser); - ASSERT_TRUE(nav_awaiter.GetRedirectionInfoForNavigation().has_value()); - - NavigationCapturingRedirectionInfo redirection_info = - *nav_awaiter.GetRedirectionInfoForNavigation(); - - // Triggered from a tab and not an app window. - EXPECT_FALSE(redirection_info.source_browser_app_id().has_value()); - EXPECT_FALSE(redirection_info.source_tab_app_id().has_value()); - EXPECT_EQ(NavigationHandlingInitialResult::kNavigateCapturedNewAppWindow, - redirection_info.initial_nav_handling_result()); - EXPECT_EQ(WindowOpenDisposition::NEW_FOREGROUND_TAB, - redirection_info.disposition()); - EXPECT_TRUE(redirection_info.first_navigation_app_id().has_value()); - EXPECT_EQ(app_id, *redirection_info.first_navigation_app_id()); - - // Post navigation, the WebContentsUserData instances should be cleaned up. - EXPECT_THAT(GetForwarderForWebContents( - app_browser->tab_strip_model()->GetActiveWebContents()), - testing::IsNull()); -} - -IN_PROC_BROWSER_TEST_F(NavigationCapturingDataTransferBrowserTest, - LeftClickSameWebContentsGetsCorrectDisposition) { - content::WebContents* contents = OpenStartPageInTab(); - ASSERT_NE(nullptr, contents); - NavigationCompletionAwaiter nav_awaiter(contents); - test::SimulateClickOnElement(contents, kToSiteATargetBlankNoopener, - test::ClickMethod::kLeftClick); - nav_awaiter.AwaitNavigationCompletion(); - ASSERT_TRUE(nav_awaiter.GetRedirectionInfoForNavigation().has_value()); - - NavigationCapturingRedirectionInfo redirection_info = - *nav_awaiter.GetRedirectionInfoForNavigation(); - - // Triggered from a tab and not an app window. - EXPECT_FALSE(redirection_info.source_browser_app_id().has_value()); - EXPECT_FALSE(redirection_info.source_tab_app_id().has_value()); - EXPECT_EQ(NavigationHandlingInitialResult::kBrowserTab, - redirection_info.initial_nav_handling_result()); - EXPECT_EQ(WindowOpenDisposition::NEW_FOREGROUND_TAB, - redirection_info.disposition()); - EXPECT_FALSE(redirection_info.first_navigation_app_id().has_value()); - - // Post navigation, the WebContentsUserData instances should be cleaned up. - EXPECT_THAT(GetForwarderForWebContents(contents), testing::IsNull()); -} - -IN_PROC_BROWSER_TEST_F(NavigationCapturingDataTransferBrowserTest, - ShiftClickNewWebContentsGetsCorrectDisposition) { - const webapps::AppId app_id_a = InstallTestWebApp(GetStartUrl()); - const webapps::AppId app_id_b = InstallTestWebApp(GetDestinationUrl()); - content::WebContents* contents = OpenStartPageInApp(app_id_a); - ASSERT_NE(nullptr, contents); - - NavigationCompletionAwaiter nav_awaiter(contents); - Browser* app_browser = TriggerNavigationCapturingNewAppWindow( - contents, test::ClickMethod::kShiftClick, kToSiteBTargetBlankWithOpener); - nav_awaiter.AwaitNavigationCompletion(); - ASSERT_NE(nullptr, app_browser); - - ASSERT_TRUE(nav_awaiter.GetRedirectionInfoForNavigation().has_value()); - - NavigationCapturingRedirectionInfo redirection_info = - *nav_awaiter.GetRedirectionInfoForNavigation(); - - // Triggered from an app window for app_id_a. - ASSERT_TRUE(redirection_info.source_browser_app_id().has_value()); - EXPECT_EQ(app_id_a, *redirection_info.source_browser_app_id()); - EXPECT_TRUE(redirection_info.source_tab_app_id().has_value()); - // Navigation capturing only extends to left clicks creating a capturable - // experience, and does not extend to user modified clicks like shift and - // middle clicks. - EXPECT_EQ(NavigationHandlingInitialResult::kForcedNewAppContextAppWindow, - redirection_info.initial_nav_handling_result()); - EXPECT_EQ(WindowOpenDisposition::NEW_WINDOW, redirection_info.disposition()); - ASSERT_TRUE(redirection_info.first_navigation_app_id().has_value()); - EXPECT_EQ(app_id_b, *redirection_info.first_navigation_app_id()); - - EXPECT_THAT(GetForwarderForWebContents( - app_browser->tab_strip_model()->GetActiveWebContents()), - testing::IsNull()); -} - -IN_PROC_BROWSER_TEST_F(NavigationCapturingDataTransferBrowserTest, - MiddleClickNewWebContentsGetsCorrectDisposition) { - const webapps::AppId app_id = InstallTestWebApp(GetStartUrl()); - content::WebContents* contents = OpenStartPageInApp(app_id); - ASSERT_NE(nullptr, contents); - - NavigationCompletionAwaiter nav_awaiter(contents); - - Browser* app_browser = TriggerNavigationCapturingNewAppWindow( - contents, test::ClickMethod::kMiddleClick, kToSiteATargetBlankWithOpener); - nav_awaiter.AwaitNavigationCompletion(); - ASSERT_NE(nullptr, app_browser); - ASSERT_TRUE(nav_awaiter.GetRedirectionInfoForNavigation().has_value()); - - NavigationCapturingRedirectionInfo redirection_info = - *nav_awaiter.GetRedirectionInfoForNavigation(); - - // Triggered from an app window for app_id. - ASSERT_TRUE(redirection_info.source_browser_app_id().has_value()); - EXPECT_EQ(app_id, redirection_info.source_browser_app_id().value()); - EXPECT_TRUE(redirection_info.source_tab_app_id().has_value()); - EXPECT_EQ(NavigationHandlingInitialResult::kForcedNewAppContextAppWindow, - redirection_info.initial_nav_handling_result()); - EXPECT_EQ(WindowOpenDisposition::NEW_BACKGROUND_TAB, - redirection_info.disposition()); - ASSERT_TRUE(redirection_info.first_navigation_app_id().has_value()); - EXPECT_EQ(app_id, *redirection_info.first_navigation_app_id()); - - EXPECT_THAT(GetForwarderForWebContents( - app_browser->tab_strip_model()->GetActiveWebContents()), - testing::IsNull()); -} - -IN_PROC_BROWSER_TEST_F(NavigationCapturingDataTransferBrowserTest, - AuxContextFromTab) { - content::WebContents* contents = OpenStartPageInTab(); - ASSERT_NE(nullptr, contents); - NavigationCompletionAwaiter nav_awaiter(contents); - test::SimulateClickOnElement(contents, kToSiteATargetBlankWithOpener, - test::ClickMethod::kLeftClick); - nav_awaiter.AwaitNavigationCompletion(); - EXPECT_FALSE(nav_awaiter.GetRedirectionInfoForNavigation().has_value()); - - // Post navigation, the WebContentsUserData instances should be cleaned up. - EXPECT_THAT(GetForwarderForWebContents(contents), testing::IsNull()); -} - -IN_PROC_BROWSER_TEST_F(NavigationCapturingDataTransferBrowserTest, - AuxContentFromAppWindow) { - const webapps::AppId app_id_a = InstallTestWebApp(GetStartUrl()); - const webapps::AppId app_id_b = InstallTestWebApp(GetDestinationUrl()); - content::WebContents* contents = OpenStartPageInApp(app_id_a); - ASSERT_NE(nullptr, contents); - - NavigationCompletionAwaiter nav_awaiter(contents); - test::SimulateClickOnElement(contents, kToSiteBTargetBlankWithOpener, - test::ClickMethod::kLeftClick); - nav_awaiter.AwaitNavigationCompletion(); - EXPECT_FALSE(nav_awaiter.GetRedirectionInfoForNavigation().has_value()); - - // Post navigation, the WebContentsUserData instances should be cleaned up. - EXPECT_THAT(GetForwarderForWebContents(contents), testing::IsNull()); -} - -} // namespace - -} // namespace web_app
diff --git a/chrome/browser/xsurface/BUILD.gn b/chrome/browser/xsurface/BUILD.gn index 1a67539..938e50e 100644 --- a/chrome/browser/xsurface/BUILD.gn +++ b/chrome/browser/xsurface/BUILD.gn
@@ -36,7 +36,14 @@ "android/java/src/org/chromium/chrome/browser/xsurface/feed/StreamType.java", ] deps = [ + "//third_party/android_deps:org_jspecify_jspecify_java", "//third_party/androidx:androidx_annotation_annotation_java", "//third_party/androidx:androidx_recyclerview_recyclerview_java", ] + + # Prevent automatic dep on build_java. + chromium_code = false + + # Do not let chromium_code = false disable Error Prone. + enable_errorprone = true }
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ColorProvider.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ColorProvider.java index e127f76..85253885 100644 --- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ColorProvider.java +++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ColorProvider.java
@@ -3,12 +3,15 @@ // found in the LICENSE file. package org.chromium.chrome.browser.xsurface; +import org.jspecify.annotations.NullMarked; + /** * Interface to supply chrome-specific colors to xsurface. * * Used to support dynamic themes on devices that support it. * The methods loosely mimics the Material Next dynamic color tokens. */ +@NullMarked public interface ColorProvider { /** @return the primary color. */ default int getPrimary() {
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/HybridListRenderer.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/HybridListRenderer.java index 11a9bd2..eb9dca2 100644 --- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/HybridListRenderer.java +++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/HybridListRenderer.java
@@ -7,15 +7,18 @@ import android.view.View; import android.view.ViewGroup; -import androidx.annotation.Nullable; import androidx.recyclerview.widget.RecyclerView; +import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; + /** * Implemented internally. * * A renderer that can handle mixing externally-provided views with native Android views * in a RecyclerView. */ +@NullMarked public interface HybridListRenderer { /** * Binds a contentmanager with this renderer. @@ -105,7 +108,7 @@ default void onManualRefreshStarted() {} /** Returns helper to manager the list layout. @{@link ListLayoutHelper} instance. */ - default ListLayoutHelper getListLayoutHelper() { + default @Nullable ListLayoutHelper getListLayoutHelper() { return null; } @@ -114,7 +117,7 @@ * RecyclerView, which may be null before attach and after detach, this is guaranteed to be * valid between the call to bind() and unbind(). */ - default RecyclerView.Adapter<?> getAdapter() { + default RecyclerView.@Nullable Adapter<?> getAdapter() { return null; } }
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ImageCacheHelper.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ImageCacheHelper.java index 39a9107..4a1ecb9 100644 --- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ImageCacheHelper.java +++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ImageCacheHelper.java
@@ -4,6 +4,8 @@ package org.chromium.chrome.browser.xsurface; +import org.jspecify.annotations.NullMarked; + /** * Implemented internally. * @@ -11,6 +13,7 @@ * native code to call to the image loader across the * xsurface. */ +@NullMarked public interface ImageCacheHelper { /** * Prefetches the image from the given URL and stores
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ImageFetchClient.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ImageFetchClient.java index 46a8173..b56eddb 100644 --- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ImageFetchClient.java +++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ImageFetchClient.java
@@ -4,12 +4,15 @@ package org.chromium.chrome.browser.xsurface; +import org.jspecify.annotations.NullMarked; + /** * Implemented in Chromium. * * An object that can send an HTTP GET request and receive bytes in response. This interface should * only be used for fetching images. */ +@NullMarked public interface ImageFetchClient { /** HTTP response. */ public interface HttpResponse {
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ListContentManager.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ListContentManager.java index 9bf0e8ab..cd4e0212 100644 --- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ListContentManager.java +++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ListContentManager.java
@@ -7,7 +7,8 @@ import android.view.View; import android.view.ViewGroup; -import androidx.annotation.Nullable; +import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; import java.util.Map; @@ -19,6 +20,7 @@ * * Models after a RecyclerView.Adapter. */ +@NullMarked public interface ListContentManager { /** Returns whether the item at index is a native view or not. */ default boolean isNativeView(int index) { @@ -31,8 +33,7 @@ } /** Returns map of values which should go in the context of an external view. */ - @Nullable - default Map<String, Object> getContextValues(int index) { + default @Nullable Map<String, Object> getContextValues(int index) { return null; } @@ -42,7 +43,7 @@ * View should not be attached to parent. {@link bindNativeView} will * be called later to attach more information to the view. */ - default View getNativeView(int viewType, ViewGroup parent) { + default @Nullable View getNativeView(int viewType, ViewGroup parent) { return null; }
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ListContentManagerObserver.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ListContentManagerObserver.java index 8534c5e..f09e1e9 100644 --- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ListContentManagerObserver.java +++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ListContentManagerObserver.java
@@ -4,11 +4,14 @@ package org.chromium.chrome.browser.xsurface; +import org.jspecify.annotations.NullMarked; + /** * Implemented in Chromium. * * Interface to observe a list. */ +@NullMarked public interface ListContentManagerObserver { /** Called when range from startIndex to startIndex+count has been inserted. */ default void onItemRangeInserted(int startIndex, int count) {}
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ListLayoutHelper.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ListLayoutHelper.java index d90b6e27..7e19413 100644 --- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ListLayoutHelper.java +++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ListLayoutHelper.java
@@ -5,12 +5,15 @@ import android.view.View; +import org.jspecify.annotations.NullMarked; + /** * Implemented internally. * * <p>Interface providing helper methods to layout list items in an external surface-controlled * RecyclerView. */ +@NullMarked public interface ListLayoutHelper { /** * Helper method to retrieve first visible item position from
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/LoggingParameters.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/LoggingParameters.java index 7b27e80..7d44dba 100644 --- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/LoggingParameters.java +++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/LoggingParameters.java
@@ -4,7 +4,8 @@ package org.chromium.chrome.browser.xsurface; -import androidx.annotation.Nullable; +import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; // TODO(b/269234249): Decide what to do with this class. Some of these things are feed specific. /** @@ -12,6 +13,7 @@ * * The set of parameters necessary for logging. */ +@NullMarked public interface LoggingParameters { // Key for ListContentManager.getContextValues(). String KEY = "LoggingParameters"; @@ -35,8 +37,7 @@ boolean viewActionsEnabled(); /** The EventID, in raw proto bytes, of the first page response, or null if not present. */ - @Nullable - default byte[] rootEventId() { + default byte @Nullable [] rootEventId() { return null; } }
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/PersistentKeyValueCache.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/PersistentKeyValueCache.java index dfaa734..17319e6e 100644 --- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/PersistentKeyValueCache.java +++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/PersistentKeyValueCache.java
@@ -4,13 +4,15 @@ package org.chromium.chrome.browser.xsurface; -import androidx.annotation.Nullable; +import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; /** * Implemented in Chromium. * * A simple key-value cache that is persisting all data on disk. Automatically evicts old data. */ +@NullMarked public interface PersistentKeyValueCache { /** Consumes the result of PersistentKeyValueCache.lookup(). */ public interface ValueConsumer { @@ -19,7 +21,7 @@ * * @param value The value found. null if no value was present. */ - void run(@Nullable byte[] value); + void run(byte @Nullable [] value); } /**
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ProcessScope.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ProcessScope.java index 72a3892..3a04bfd 100644 --- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ProcessScope.java +++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ProcessScope.java
@@ -4,7 +4,8 @@ package org.chromium.chrome.browser.xsurface; -import androidx.annotation.Nullable; +import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; import org.chromium.chrome.browser.xsurface.feed.FeedSurfaceScope; import org.chromium.chrome.browser.xsurface.feed.FeedSurfaceScopeDependencyProvider; @@ -15,6 +16,7 @@ * <p>Used to initialize singleton-level dependencies for xsurface. Also provides surface-level * dependencies that depend on the singleton dependencies. */ +@NullMarked public interface ProcessScope { /** * To be called after a login state change event, will cause the next SurfaceScope to use fresh
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ProcessScopeDependencyProvider.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ProcessScopeDependencyProvider.java index 5b46890..b87d8a09 100644 --- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ProcessScopeDependencyProvider.java +++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ProcessScopeDependencyProvider.java
@@ -7,7 +7,9 @@ import android.content.Context; import androidx.annotation.IntDef; -import androidx.annotation.Nullable; + +import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -17,6 +19,7 @@ * * Provides application-level dependencies for an external surface. */ +@NullMarked public interface ProcessScopeDependencyProvider { /** * Resolves a library name such as "foo" to an absolute path. The library name should be in the @@ -130,7 +133,7 @@ } /** Returns the google API key. */ - default String getGoogleApiKey() { + default @Nullable String getGoogleApiKey() { return null; } @@ -190,7 +193,7 @@ /** @return the Color provider. */ @Deprecated - default ColorProvider getColorProvider() { + default @Nullable ColorProvider getColorProvider() { return null; }
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ReliabilityLoggingTestUtil.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ReliabilityLoggingTestUtil.java index 1ccbeae..698cd75c 100644 --- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ReliabilityLoggingTestUtil.java +++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ReliabilityLoggingTestUtil.java
@@ -4,6 +4,9 @@ package org.chromium.chrome.browser.xsurface; +import org.jspecify.annotations.NullMarked; + /** Moving to ./feed/ */ +@NullMarked public interface ReliabilityLoggingTestUtil extends org.chromium.chrome.browser.xsurface.feed.ReliabilityLoggingTestUtil {}
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/StreamType.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/StreamType.java index 560705f..e56b553 100644 --- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/StreamType.java +++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/StreamType.java
@@ -6,6 +6,8 @@ import androidx.annotation.IntDef; +import org.jspecify.annotations.NullMarked; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -19,6 +21,7 @@ StreamType.SUPERVISED_USER_FEED }) @Retention(RetentionPolicy.SOURCE) +@NullMarked public @interface StreamType { int UNSPECIFIED = 0; int FOR_YOU = 1;
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceActionsHandler.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceActionsHandler.java index 07054ee9..9d3bdf6 100644 --- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceActionsHandler.java +++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceActionsHandler.java
@@ -7,7 +7,9 @@ import android.view.View; import androidx.annotation.IntDef; -import androidx.annotation.Nullable; + +import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -18,6 +20,7 @@ * * Interface to provide chromium calling points for an external surface. */ +@NullMarked public interface SurfaceActionsHandler { String KEY = "GeneralActions"; @@ -170,8 +173,7 @@ } /** The callback to be informed of completion, or null. */ - @Nullable - default WebFeedFollowUpdate.Callback callback() { + default WebFeedFollowUpdate.@Nullable Callback callback() { return null; }
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceHeaderOffsetObserver.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceHeaderOffsetObserver.java index 528767d..8093eb04 100644 --- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceHeaderOffsetObserver.java +++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceHeaderOffsetObserver.java
@@ -4,6 +4,8 @@ package org.chromium.chrome.browser.xsurface; +import org.jspecify.annotations.NullMarked; + /** * Implemented internally. * @@ -13,6 +15,7 @@ * position that is currently rendered onscreen. * @see org.chromium.chrome.browser.feed.ScrollListener */ +@NullMarked public interface SurfaceHeaderOffsetObserver { /** * Called when the vertical offset of the header (1st item) in the scrollable container changes.
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceRenderer.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceRenderer.java index cb53506..cec4c2d0 100644 --- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceRenderer.java +++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceRenderer.java
@@ -6,7 +6,8 @@ import android.view.View; -import androidx.annotation.Nullable; +import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; import java.util.Map; @@ -15,6 +16,7 @@ * * Interface to call a rendering service to render a View sent by a server. */ +@NullMarked public interface SurfaceRenderer { /** Update the card renderer with shared data bytes. */ default void update(byte[] data) {}
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceScope.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceScope.java index dea7856..5111b01 100644 --- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceScope.java +++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceScope.java
@@ -4,7 +4,8 @@ package org.chromium.chrome.browser.xsurface; -import androidx.annotation.Nullable; +import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; /** * Implemented internally. @@ -14,6 +15,7 @@ * "Scope") but each call to provideFoo will return a new renderer, so that a * single surface can support multiple rendered views. */ +@NullMarked public interface SurfaceScope { default @Nullable HybridListRenderer provideListRenderer() { return null;
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceScopeDependencyProvider.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceScopeDependencyProvider.java index 927572a..07190a8 100644 --- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceScopeDependencyProvider.java +++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceScopeDependencyProvider.java
@@ -7,7 +7,8 @@ import android.app.Activity; import android.content.Context; -import androidx.annotation.Nullable; +import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; /** * Implemented in Chromium. @@ -16,6 +17,7 @@ * * Should only be called on the UI thread. */ +@NullMarked public interface SurfaceScopeDependencyProvider { /** Returns the activity. */ default @Nullable Activity getActivity() {
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/feed/FeedActionsHandler.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/feed/FeedActionsHandler.java index e1de19d..fbb67de1 100644 --- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/feed/FeedActionsHandler.java +++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/feed/FeedActionsHandler.java
@@ -8,6 +8,8 @@ import androidx.annotation.IntDef; +import org.jspecify.annotations.NullMarked; + import org.chromium.chrome.browser.xsurface.LoggingParameters; import java.lang.annotation.Retention; @@ -19,6 +21,7 @@ * * Interface to provide chromium calling points for a feed. */ +@NullMarked public interface FeedActionsHandler { String KEY = "FeedActions";
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/feed/FeedCardOpeningReliabilityLogger.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/feed/FeedCardOpeningReliabilityLogger.java index f3a38c1f..01e7616 100644 --- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/feed/FeedCardOpeningReliabilityLogger.java +++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/feed/FeedCardOpeningReliabilityLogger.java
@@ -6,6 +6,8 @@ import androidx.annotation.IntDef; +import org.jspecify.annotations.NullMarked; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -15,6 +17,7 @@ * <p>Interface for capturing the reliability for user tapping a card. One instance exists per feed * surface and lasts for the surface's lifetime. */ +@NullMarked public interface FeedCardOpeningReliabilityLogger { /** Describes the page loading error. */ @IntDef({
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/feed/FeedLaunchReliabilityLogger.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/feed/FeedLaunchReliabilityLogger.java index 25a0d2f..555baa3 100644 --- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/feed/FeedLaunchReliabilityLogger.java +++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/feed/FeedLaunchReliabilityLogger.java
@@ -6,6 +6,8 @@ import androidx.annotation.IntDef; +import org.jspecify.annotations.NullMarked; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -16,6 +18,7 @@ * in terms of nanoseconds since system boot. One instance exists per feed surface and lasts for the * surface's lifetime. */ +@NullMarked public interface FeedLaunchReliabilityLogger { @IntDef({SurfaceType.UNSPECIFIED, SurfaceType.NEW_TAB_PAGE, SurfaceType.START_SURFACE}) @Retention(RetentionPolicy.SOURCE)
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/feed/FeedNetworkRequestReliabilityLogger.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/feed/FeedNetworkRequestReliabilityLogger.java index 5079fd09..cae5c67d 100644 --- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/feed/FeedNetworkRequestReliabilityLogger.java +++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/feed/FeedNetworkRequestReliabilityLogger.java
@@ -4,6 +4,8 @@ package org.chromium.chrome.browser.xsurface.feed; +import org.jspecify.annotations.NullMarked; + /** * Implemented internally. * @@ -12,6 +14,7 @@ * * Obtain instances from FeedLaunchReliabilityLogger.getNetworkRequestReliabilityLogger2(). */ +@NullMarked public interface FeedNetworkRequestReliabilityLogger { /** * Log before filling out and serializing a
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/feed/FeedSurfaceScope.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/feed/FeedSurfaceScope.java index e0201c5..81996c1 100644 --- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/feed/FeedSurfaceScope.java +++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/feed/FeedSurfaceScope.java
@@ -4,6 +4,8 @@ package org.chromium.chrome.browser.xsurface.feed; +import org.jspecify.annotations.NullMarked; + import org.chromium.chrome.browser.xsurface.SurfaceScope; // TODO(b/269234249): Don't use this in Chromium yet, it's not implemented. @@ -15,6 +17,7 @@ * "Scope") but each call to provideFoo will return a new renderer, so that a * single surface can support multiple rendered views. */ +@NullMarked public interface FeedSurfaceScope extends SurfaceScope { /** * Return the FeedLaunchReliabilityLogger associated with the surface, creating it if it
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/feed/FeedSurfaceScopeDependencyProvider.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/feed/FeedSurfaceScopeDependencyProvider.java index d592f39..afc62e5 100644 --- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/feed/FeedSurfaceScopeDependencyProvider.java +++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/feed/FeedSurfaceScopeDependencyProvider.java
@@ -6,7 +6,8 @@ import android.graphics.Rect; -import androidx.annotation.Nullable; +import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; import org.chromium.chrome.browser.xsurface.LoggingParameters; import org.chromium.chrome.browser.xsurface.PersistentKeyValueCache; @@ -20,6 +21,7 @@ * * Should only be called on the UI thread. */ +@NullMarked public interface FeedSurfaceScopeDependencyProvider extends SurfaceScopeDependencyProvider { /** User-set preference for when videos are eligible to autoplay. */ public enum AutoplayPreference { @@ -145,8 +147,7 @@ * Returns a {@link PersistentKeyValueCache}. This value will be cached as an account-level * dependency, and only cleared after {@link ProcessScope#resetAccount()} is called. */ - @Nullable - default PersistentKeyValueCache getPersistentKeyValueCache() { + default @Nullable PersistentKeyValueCache getPersistentKeyValueCache() { return null; }
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/feed/FeedUserInteractionReliabilityLogger.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/feed/FeedUserInteractionReliabilityLogger.java index cafac35..a5aee2b 100644 --- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/feed/FeedUserInteractionReliabilityLogger.java +++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/feed/FeedUserInteractionReliabilityLogger.java
@@ -8,6 +8,8 @@ import androidx.annotation.IntDef; +import org.jspecify.annotations.NullMarked; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -19,6 +21,7 @@ * to the user during the interaction. One instance exists per feed surface and lasts for the * surface's lifetime. */ +@NullMarked public interface FeedUserInteractionReliabilityLogger { /** Called when the stream has been opened. This should be called before reporting any event. */ default void onStreamOpened(@StreamType int streamType) {}
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/feed/ReliabilityLoggingTestUtil.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/feed/ReliabilityLoggingTestUtil.java index 337739a..76925332 100644 --- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/feed/ReliabilityLoggingTestUtil.java +++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/feed/ReliabilityLoggingTestUtil.java
@@ -4,12 +4,15 @@ package org.chromium.chrome.browser.xsurface.feed; +import org.jspecify.annotations.NullMarked; + /** * Implemented internally. * * This interface provides access to the list of recently-sent "flows" of reliability logging events * for verification in integration tests. */ +@NullMarked public interface ReliabilityLoggingTestUtil { /** * Return the most recent "flows" (at most 30), or lists of logged events
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/feed/ResourceFetcher.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/feed/ResourceFetcher.java index e13cc3e5..ec4f98f 100644 --- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/feed/ResourceFetcher.java +++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/feed/ResourceFetcher.java
@@ -4,7 +4,8 @@ package org.chromium.chrome.browser.xsurface.feed; -import androidx.annotation.Nullable; +import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; import java.util.List; @@ -13,6 +14,7 @@ * * Interface to provide network fetching. */ +@NullMarked public interface ResourceFetcher { /** * Represents the key portion of an http header field. Header keys should be compared @@ -29,6 +31,7 @@ } /** Data structure to encapsulate the fetch request. */ + @SuppressWarnings("NullAway") // Uninitialized non-null fields. public class Request { /** Uri of the resource to be fetched. */ public String uri; @@ -40,7 +43,7 @@ public List<Header> headers; /** Post data that needs to be sent along with the POST request. */ - public @Nullable byte[] postData; + public byte @Nullable [] postData; } /** Data structure to encapsulate the fetch response. */
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/feed/StreamType.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/feed/StreamType.java index e788552..f1a613d27 100644 --- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/feed/StreamType.java +++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/feed/StreamType.java
@@ -6,6 +6,8 @@ import androidx.annotation.IntDef; +import org.jspecify.annotations.NullMarked; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -21,6 +23,7 @@ StreamType.SUPERVISED_USER_FEED }) @Retention(RetentionPolicy.SOURCE) +@NullMarked public @interface StreamType { int UNSPECIFIED = 0; int FOR_YOU = 1;
diff --git a/chrome/browser/xsurface_provider/android/java/src/org/chromium/chrome/browser/xsurface_provider/ProcessScopeDependencyProviderFactory.java b/chrome/browser/xsurface_provider/android/java/src/org/chromium/chrome/browser/xsurface_provider/ProcessScopeDependencyProviderFactory.java index 849f460..d489fb76 100644 --- a/chrome/browser/xsurface_provider/android/java/src/org/chromium/chrome/browser/xsurface_provider/ProcessScopeDependencyProviderFactory.java +++ b/chrome/browser/xsurface_provider/android/java/src/org/chromium/chrome/browser/xsurface_provider/ProcessScopeDependencyProviderFactory.java
@@ -4,6 +4,7 @@ package org.chromium.chrome.browser.xsurface_provider; +import org.chromium.build.annotations.NullMarked; import org.chromium.chrome.browser.xsurface.ProcessScopeDependencyProvider; /** @@ -12,6 +13,7 @@ * Note that ProcessScopeDependencyProvider is sometimes needed in response to a Native call, * we use this through reflection rather than simply injecting an instance. */ +@NullMarked public interface ProcessScopeDependencyProviderFactory { /** Constructs and returns a ProcessScopeDependencyProvider instance. */ ProcessScopeDependencyProvider create();
diff --git a/chrome/browser/xsurface_provider/android/java/src/org/chromium/chrome/browser/xsurface_provider/XSurfaceProcessScopeProvider.java b/chrome/browser/xsurface_provider/android/java/src/org/chromium/chrome/browser/xsurface_provider/XSurfaceProcessScopeProvider.java index 92a4a3a6..17231630 100644 --- a/chrome/browser/xsurface_provider/android/java/src/org/chromium/chrome/browser/xsurface_provider/XSurfaceProcessScopeProvider.java +++ b/chrome/browser/xsurface_provider/android/java/src/org/chromium/chrome/browser/xsurface_provider/XSurfaceProcessScopeProvider.java
@@ -4,15 +4,20 @@ package org.chromium.chrome.browser.xsurface_provider; +import static org.chromium.build.NullUtil.assumeNonNull; + import org.chromium.base.ServiceLoaderUtil; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import org.chromium.chrome.browser.xsurface.ProcessScope; import org.chromium.chrome.browser.xsurface_provider.hooks.XSurfaceHooks; /** Holds and provides an instance of {@link ProcessScope}. */ +@NullMarked public final class XSurfaceProcessScopeProvider { - private static ProcessScope sProcessScope; + private static @Nullable ProcessScope sProcessScope; - public static ProcessScope getProcessScope() { + public static @Nullable ProcessScope getProcessScope() { if (sProcessScope != null) { return sProcessScope; } @@ -23,6 +28,7 @@ ProcessScopeDependencyProviderFactory dependencyProviderFactory = ServiceLoaderUtil.maybeCreate(ProcessScopeDependencyProviderFactory.class); + assumeNonNull(dependencyProviderFactory); sProcessScope = hooks.createProcessScope(dependencyProviderFactory.create()); return sProcessScope; }
diff --git a/chrome/browser/xsurface_provider/android/java/src/org/chromium/chrome/browser/xsurface_provider/hooks/XSurfaceHooks.java b/chrome/browser/xsurface_provider/android/java/src/org/chromium/chrome/browser/xsurface_provider/hooks/XSurfaceHooks.java index 7a20560..8eedd759 100644 --- a/chrome/browser/xsurface_provider/android/java/src/org/chromium/chrome/browser/xsurface_provider/hooks/XSurfaceHooks.java +++ b/chrome/browser/xsurface_provider/android/java/src/org/chromium/chrome/browser/xsurface_provider/hooks/XSurfaceHooks.java
@@ -4,10 +4,12 @@ package org.chromium.chrome.browser.xsurface_provider.hooks; +import org.chromium.build.annotations.NullMarked; import org.chromium.chrome.browser.xsurface.ProcessScope; import org.chromium.chrome.browser.xsurface.ProcessScopeDependencyProvider; /** Provides access to internal XSurface implementations, if they are available. */ +@NullMarked public interface XSurfaceHooks { /** Whether the internal implementations of XSurface interfaces are available.*/ default boolean isEnabled() {
diff --git a/chrome/build/android-arm64.pgo.txt b/chrome/build/android-arm64.pgo.txt index 1884c90..326099d 100644 --- a/chrome/build/android-arm64.pgo.txt +++ b/chrome/build/android-arm64.pgo.txt
@@ -1 +1 @@ -chrome-android64-main-1736873670-571427a1ca4d44887a896ee63ecdd4983b0ebcad-6b1ae7cf09752107fd520b9dc7ad05da216df964.profdata +chrome-android64-main-1736892120-980ddfc3240b42074ad5c17588af70b9c7a37c7a-9ac827c60b0e1db8db9d2b55d82f52bbe8bdd939.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt index 6f097fab..e22cdd65 100644 --- a/chrome/build/mac-arm.pgo.txt +++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@ -chrome-mac-arm-main-1736877592-de994976f8cec6a2123c9f09bc259d536c783500-5633081edbf67f45623e0d4d849074fd304df9bd.profdata +chrome-mac-arm-main-1736891676-9a81d38d9b016f82a065b9b278b3d26a872cb305-85c16a5502c2fd74c256aa22a0db83931e38c4ce.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index 60cae6c..4ceb33e 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-main-1736855751-cfd7dff2c5af0155e81c34577e08f91ce6ad41c8-63772cb6f24ec8e62cd1e0088fa087699bea258f.profdata +chrome-mac-main-1736877592-7bff9b78ecc2683b30106277bdbf001cba02edcc-5633081edbf67f45623e0d4d849074fd304df9bd.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index cfaad83..69456fe 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1736855751-c1f7456cee9eab7c5ed7f7d12383bb9cb9ccfa70-63772cb6f24ec8e62cd1e0088fa087699bea258f.profdata +chrome-win32-main-1736866758-d3258608eac4033256ad78eb916cd63a305fb675-6aed92e9dc6f45280d3e996b0373882f04fc32b4.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index 7289162..f54279d1 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1736844869-0bd3ffb49e1c4213b44dcbe43b25abcb0d57db31-7db51209cd219222b958cb73ac3ee1e1bfccf733.profdata +chrome-win64-main-1736866758-2bd50d3076f30b1774754e83ca9e8a5d6ec5fe52-6aed92e9dc6f45280d3e996b0373882f04fc32b4.profdata
diff --git a/chrome/common/media/cdm_registration.cc b/chrome/common/media/cdm_registration.cc index 8321975..6d5c8c41 100644 --- a/chrome/common/media/cdm_registration.cc +++ b/chrome/common/media/cdm_registration.cc
@@ -39,10 +39,6 @@ #include "chrome/common/media/component_widevine_cdm_hint_file_linux.h" #include "media/cdm/cdm_paths.h" // nogncheck #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) -#if BUILDFLAG(IS_CHROMEOS_LACROS) -#include "base/metrics/histogram_functions.h" -#include "content/public/common/content_switches.h" -#endif // BUILDFLAG(IS_CHROMEOS_LACROS) #endif // BUILDFLAG(ENABLE_WIDEVINE) #if BUILDFLAG(IS_ANDROID) @@ -54,29 +50,6 @@ using Robustness = content::CdmInfo::Robustness; #if BUILDFLAG(ENABLE_WIDEVINE) -#if BUILDFLAG(IS_CHROMEOS_LACROS) -// These values are persisted to logs. Entries should not be renumbered and -// numeric values should never be reused. -enum class LacrosBundledWidevine { - kNone = 0, - kLacros = 1, - kAsh = 2, - kMaxValue = kAsh, -}; - -// Record which Widevine CDM was loaded for Lacros. -void ReportLacrosUMA(LacrosBundledWidevine value) { - // Only recorded by the browser process. If recorded by the pre-zygote - // process, then all processes will end up with this value reported. - const auto* command_line = base::CommandLine::ForCurrentProcess(); - std::string process_type = - command_line->GetSwitchValueASCII(switches::kProcessType); - if (process_type.empty()) { - base::UmaHistogramEnumeration("Media.EME.Widevine.LacrosBundledCdm", value); - } -} -#endif // BUILDFLAG(IS_CHROMEOS_LACROS) - #if (BUILDFLAG(BUNDLE_WIDEVINE_CDM) || \ BUILDFLAG(ENABLE_WIDEVINE_CDM_COMPONENT)) && \ (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)) @@ -147,48 +120,13 @@ #endif // BUILDFLAG(BUNDLE_WIDEVINE_CDM) && // (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)) -#if BUILDFLAG(IS_CHROMEOS_LACROS) -// ChromeOS Lacros should use the Widevine CDM bundled with ChromeOS Ash. -// This is determined by using command line arguments passed when Ash -// launches Lacros. -std::unique_ptr<content::CdmInfo> GetAshBundledWidevine() { - if (base::FeatureList::IsEnabled(media::kLacrosUseAshWidevine)) { - const auto* command_line = base::CommandLine::ForCurrentProcess(); - if (command_line->HasSwitch(switches::kCrosWidevineBundledDir)) { - ReportLacrosUMA(LacrosBundledWidevine::kAsh); - base::FilePath install_dir = - command_line->GetSwitchValuePath(switches::kCrosWidevineBundledDir); - return CreateCdmInfoFromWidevineDirectory(install_dir); - } - } - -#if BUILDFLAG(BUNDLE_WIDEVINE_CDM) - // As there will be a transition period where Lacros runs on older versions of - // Ash that do not set the command line argument, use the Widevine CDM bundled - // with Lacros if available. - // TODO(b/332962687): Remove Lacros bundled Widevine CDM once all versions of - // Ash updated to set the command line argument. - ReportLacrosUMA(LacrosBundledWidevine::kLacros); - return GetBundledWidevine(); -#else - ReportLacrosUMA(LacrosBundledWidevine::kNone); - return nullptr; -#endif // BUILDFLAG(BUNDLE_WIDEVINE_CDM) -} -#endif // BUILDFLAG(IS_CHROMEOS_LACROS) - -#if (BUILDFLAG(ENABLE_WIDEVINE_CDM_COMPONENT) && \ - (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_ASH))) || \ - BUILDFLAG(IS_CHROMEOS_LACROS) +#if (BUILDFLAG(ENABLE_WIDEVINE_CDM_COMPONENT) && \ + (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS))) // This code checks to see if Component Updater picked a version of the Widevine // CDM to be used last time it ran. (Component Updater may choose the bundled // CDM if there is not a new version available for download.) If there is one // and it looks valid, return the CdmInfo for that CDM. Otherwise return // nullptr. -// -// On ChromeOS Lacros, Component Update for the Widevine CDM is disabled. -// However, as Lacros uses the Widevine CDM available to ChromeOS Ash, this code -// is needed to check to see if the Ash Widevine CDM has been updated. std::unique_ptr<content::CdmInfo> GetHintedWidevine() { // Ideally this would cache the result, as Component Update may run and // download a new version once Chrome has been running for a while. However, @@ -211,7 +149,7 @@ return CreateCdmInfoFromWidevineDirectory(install_dir); } #endif // (BUILDFLAG(ENABLE_WIDEVINE_CDM_COMPONENT) && (BUILDFLAG(IS_LINUX) || - // BUILDFLAG(IS_CHROMEOS_ASH))) || BUILDFLAG(IS_CHROMEOS_LACROS) + // BUILDFLAG(IS_CHROMEOS))) void AddSoftwareSecureWidevine(std::vector<content::CdmInfo>* cdms) { DVLOG(1) << __func__; @@ -252,9 +190,7 @@ // We should still use the version selected by Component Update (except for // case #3 above). std::unique_ptr<content::CdmInfo> bundled_widevine = nullptr; -#if BUILDFLAG(IS_CHROMEOS_LACROS) - bundled_widevine = GetAshBundledWidevine(); -#elif BUILDFLAG(BUNDLE_WIDEVINE_CDM) +#if BUILDFLAG(BUNDLE_WIDEVINE_CDM) bundled_widevine = GetBundledWidevine(); #endif @@ -262,7 +198,7 @@ // the bundled CDM if it matches the version Component Update determines that // should be used. std::unique_ptr<content::CdmInfo> hinted_widevine; -#if BUILDFLAG(ENABLE_WIDEVINE_CDM_COMPONENT) || BUILDFLAG(IS_CHROMEOS_LACROS) +#if BUILDFLAG(ENABLE_WIDEVINE_CDM_COMPONENT) hinted_widevine = GetHintedWidevine(); #endif @@ -283,21 +219,12 @@ DVLOG(1) << __func__ << " bundled: " << bundled_version; DVLOG(1) << __func__ << " hinted: " << hinted_version; - bool choose_bundled; -#if BUILDFLAG(IS_CHROMEOS_LACROS) - // Downgrading doesn't work on Lacros, so choose the highest version CDM, - // preferring the bundled CDM over the hinted CDM if the versions are the - // same. See bug for details. - // TODO(b/329869597): Get this working on Lacros. - choose_bundled = bundled_version >= hinted_version; -#else - // On all other platforms (Linux and ChromeOS Ash) we want to pick the - // hinted version, except in the case the bundled CDM is newer than the - // hinted CDM and is different than the previously bundled CDM. - choose_bundled = + // On all platforms we want to pick the hinted version, except in the case + // the bundled CDM is newer than the hinted CDM and is different than the + // previously bundled CDM. + bool choose_bundled = bundled_version > hinted_version && bundled_version != GetBundledVersionDuringLastComponentUpdate(); -#endif // BUILDFLAG(IS_CHROMEOS_LACROS) if (choose_bundled) { VLOG(1) << "Choosing bundled Widevine " << bundled_version << " from " @@ -325,12 +252,6 @@ kWidevineCdmType, base::Version(), base::FilePath()); #elif BUILDFLAG(USE_CHROMEOS_PROTECTED_MEDIA) -#if BUILDFLAG(IS_CHROMEOS_LACROS) - if (!base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kLacrosUseChromeosProtectedMedia)) { - return; - } -#endif // BUILDFLAG(IS_CHROMEOS_LACROS) media::CdmCapability capability; // The following audio formats are supported for decrypt-only. @@ -345,26 +266,16 @@ capability.video_codecs.emplace(media::VideoCodec::kH264, kAllProfiles); #endif #if BUILDFLAG(ENABLE_PLATFORM_HEVC) -#if BUILDFLAG(IS_CHROMEOS_LACROS) - if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kLacrosEnablePlatformHevc)) { - capability.video_codecs.emplace(media::VideoCodec::kHEVC, kAllProfiles); - } -#elif BUILDFLAG(IS_CHROMEOS_ASH) +#if BUILDFLAG(IS_CHROMEOS) if (base::FeatureList::IsEnabled(media::kPlatformHEVCDecoderSupport)) { capability.video_codecs.emplace(media::VideoCodec::kHEVC, kAllProfiles); } #else capability.video_codecs.emplace(media::VideoCodec::kHEVC, kAllProfiles); -#endif // BUILDFLAG(IS_CHROMEOS_LACROS) +#endif // BUILDFLAG(IS_CHROMEOS) #endif #if BUILDFLAG(USE_CHROMEOS_PROTECTED_AV1) capability.video_codecs.emplace(media::VideoCodec::kAV1, kAllProfiles); -#elif BUILDFLAG(IS_CHROMEOS_LACROS) - if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kLacrosUseChromeosProtectedAv1)) { - capability.video_codecs.emplace(media::VideoCodec::kAV1, kAllProfiles); - } #endif // Both encryption schemes are supported on ChromeOS. @@ -477,11 +388,11 @@ } #if BUILDFLAG(ENABLE_WIDEVINE) && \ - (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_ASH)) + (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)) std::vector<content::CdmInfo> GetSoftwareSecureWidevine() { std::vector<content::CdmInfo> cdms; AddSoftwareSecureWidevine(&cdms); return cdms; } #endif // BUILDFLAG(ENABLE_WIDEVINE) && (BUILDFLAG(IS_LINUX) || - // BUILDFLAG(IS_CHROMEOS_ASH)) + // BUILDFLAG(IS_CHROMEOS))
diff --git a/chrome/common/media/component_widevine_cdm_hint_file_linux.cc b/chrome/common/media/component_widevine_cdm_hint_file_linux.cc index b3e05e81..c416845d 100644 --- a/chrome/common/media/component_widevine_cdm_hint_file_linux.cc +++ b/chrome/common/media/component_widevine_cdm_hint_file_linux.cc
@@ -19,13 +19,6 @@ #include "base/version.h" #include "chrome/common/chrome_paths.h" -#if BUILDFLAG(IS_CHROMEOS_LACROS) -#include "base/command_line.h" -#include "base/feature_list.h" -#include "base/notreached.h" -#include "media/base/media_switches.h" -#endif - namespace { // Fields used inside the hint file. @@ -36,31 +29,8 @@ // empty dictionary if the hint file does not exist or is formatted incorrectly. base::Value::Dict GetHintFileContents() { base::FilePath hint_file_path; -#if BUILDFLAG(IS_CHROMEOS_LACROS) - // ChromeOS Lacros should use the Widevine CDM Component Updated by ChromeOS - // Ash. This is determined by using command line arguments passed when Ash - // launches Lacros. - if (!base::FeatureList::IsEnabled(media::kLacrosUseAshWidevine)) { - DVLOG(1) << "CDM hint file disabled."; - return base::Value::Dict(); - } - - const auto* command_line = base::CommandLine::ForCurrentProcess(); - if (!command_line->HasSwitch( - switches::kCrosWidevineComponentUpdatedHintFile)) { - DVLOG(1) << "Command line switch " + - std::string( - switches::kCrosWidevineComponentUpdatedHintFile) + - " not found."; - return base::Value::Dict(); - } - - hint_file_path = command_line->GetSwitchValuePath( - switches::kCrosWidevineComponentUpdatedHintFile); -#else CHECK(base::PathService::Get(chrome::FILE_COMPONENT_WIDEVINE_CDM_HINT, &hint_file_path)); -#endif // BUILDFLAG(IS_CHROMEOS_LACROS) DVLOG(1) << __func__ << " checking " << hint_file_path; if (!base::PathExists(hint_file_path)) { @@ -94,9 +64,6 @@ std::optional<base::Version> bundled_version) { DCHECK(!cdm_base_path.empty()); -#if BUILDFLAG(IS_CHROMEOS_LACROS) - NOTREACHED() << "Lacros should not be updating the hint file."; -#else base::FilePath hint_file_path; CHECK(base::PathService::Get(chrome::FILE_COMPONENT_WIDEVINE_CDM_HINT, &hint_file_path)); @@ -117,7 +84,6 @@ DVLOG(1) << __func__ << " setting " << cdm_base_path << " to " << json_string; return base::ImportantFileWriter::WriteFileAtomically(hint_file_path, json_string); -#endif // BUILDFLAG(IS_CHROMEOS_LACROS) } base::FilePath GetHintedWidevineCdmDirectory() {
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index af046762..12f0a30 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -1798,6 +1798,7 @@ "../browser/extensions/api/runtime/runtime_apitest.cc", "../browser/extensions/api/web_request/web_request_apitest.cc", "../browser/extensions/background_script_executor_browsertest.cc", + "../browser/extensions/content_security_policy_apitest.cc", "../browser/extensions/cross_origin_isolation_browsertest.cc", "../browser/extensions/desktop_android/desktop_android_extensions_browsertest.cc", "../browser/extensions/extension_platform_browsertest_browsertest.cc", @@ -8491,6 +8492,7 @@ "//chromeos/ash/components/dbus/update_engine:proto", "//chromeos/ash/components/disks", "//chromeos/ash/components/disks:test_support", + "//chromeos/ash/components/editor_menu/public/cpp", "//chromeos/ash/components/feature_usage", "//chromeos/ash/components/login/auth:test_support", "//chromeos/ash/components/login/login_state:test_support", @@ -8515,7 +8517,6 @@ "//chromeos/ash/services/network_config", "//chromeos/ash/services/network_config:in_process_instance", "//chromeos/ash/services/secure_channel/public/cpp/client:test_support", - "//chromeos/components/editor_menu/public/cpp", "//chromeos/components/kiosk:kiosk", "//chromeos/components/magic_boost/public/cpp:cpp", "//chromeos/components/magic_boost/test:fake_magic_boost_state", @@ -10593,6 +10594,7 @@ "../browser/devtools/devtools_interactive_browsertest.cc", "../browser/download/download_interactive_uitest.cc", "../browser/focus_ring_browsertest.cc", + "../browser/media/webrtc/conditional_focus_interactive_uitest.cc", "../browser/media/webrtc/display_media_access_handler_interactive_uitest.cc", "../browser/media/webrtc/media_stream_permission_interactive_uitest.cc", "../browser/media/webrtc/webrtc_interactive_uitest.cc", @@ -11019,7 +11021,6 @@ if (toolkit_views) { sources += [ - "../browser/media/webrtc/conditional_focus_browsertest.cc", "../browser/ui/toolbar/app_menu_fullscreen_interactive_uitest.cc", "../browser/ui/toolbar/app_menu_model_interactive_uitest.cc", "../browser/ui/user_education/show_promo_in_page_interactive_uitest.cc",
diff --git a/chrome/test/data/webui/lens/overlay/selection_overlay_test.ts b/chrome/test/data/webui/lens/overlay/selection_overlay_test.ts index f161812..0bb333d 100644 --- a/chrome/test/data/webui/lens/overlay/selection_overlay_test.ts +++ b/chrome/test/data/webui/lens/overlay/selection_overlay_test.ts
@@ -10,6 +10,7 @@ import type {CenterRotatedBox} from 'chrome-untrusted://lens-overlay/geometry.mojom-webui.js'; import type {LensPageRemote} from 'chrome-untrusted://lens-overlay/lens.mojom-webui.js'; import {SemanticEvent, UserAction} from 'chrome-untrusted://lens-overlay/lens.mojom-webui.js'; +import {ContextMenuOption} from 'chrome-untrusted://lens-overlay/metrics_utils.js'; import type {OverlayObject} from 'chrome-untrusted://lens-overlay/overlay_object.mojom-webui.js'; import {ScreenshotBitmapBrowserProxyImpl} from 'chrome-untrusted://lens-overlay/screenshot_bitmap_browser_proxy.js'; import type {SelectionOverlayElement} from 'chrome-untrusted://lens-overlay/selection_overlay.js'; @@ -237,20 +238,47 @@ expectedLeft.toString().substring(0, 6)); }); - test( - 'verify that region search triggers selected region context menu', - async () => { - await addEmptyText(); + test('verify that region search triggers selected region context menu', async () => { + await addEmptyText(); - await simulateDrag( - selectionOverlayElement, {x: 50, y: 25}, {x: 300, y: 200}); - await waitAfterNextRender(selectionOverlayElement); + await simulateDrag( + selectionOverlayElement, {x: 50, y: 25}, {x: 300, y: 200}); + await waitAfterNextRender(selectionOverlayElement); - assertTrue(selectionOverlayElement - .getShowSelectedRegionContextMenuForTesting()); - assertFalse(selectionOverlayElement - .getShowDetectedTextContextMenuOptionsForTesting()); - }); + assertTrue( + selectionOverlayElement.getShowSelectedRegionContextMenuForTesting()); + assertFalse(selectionOverlayElement + .getShowDetectedTextContextMenuOptionsForTesting()); + + // Check that the region context menu options were shown. + assertEquals( + 1, + metrics.count( + 'Lens.Overlay.ByInvocationSource.AppMenu.ContextMenuOption.Shown', + ContextMenuOption.COPY_AS_IMAGE)); + assertEquals( + 1, + metrics.count( + 'Lens.Overlay.ByInvocationSource.AppMenu.ContextMenuOption.Shown', + ContextMenuOption.SAVE_AS_IMAGE)); + assertEquals( + 1, + metrics.count( + 'Lens.Overlay.ContextMenuOption.Shown', + ContextMenuOption.COPY_AS_IMAGE)); + assertEquals( + 1, + metrics.count( + 'Lens.Overlay.ContextMenuOption.Shown', + ContextMenuOption.SAVE_AS_IMAGE)); + + // Ensure that no other context menu options were shown. + assertEquals( + 2, + metrics.count( + 'Lens.Overlay.ByInvocationSource.AppMenu.ContextMenuOption.Shown')); + assertEquals(2, metrics.count('Lens.Overlay.ContextMenuOption.Shown')); + }); test('verify that resizing renders image with padding', async () => { @@ -411,35 +439,78 @@ 'issueTextSelectionRequest')); }); - test( - 'verify that region search over text triggers detected text options', - async () => { - await simulateDrag( - selectionOverlayElement, {x: 0, y: 0}, {x: 80, y: 40}); - await waitAfterNextRender(selectionOverlayElement); + test('verify that region search over text triggers detected text options', async () => { + await simulateDrag(selectionOverlayElement, {x: 0, y: 0}, {x: 80, y: 40}); + await waitAfterNextRender(selectionOverlayElement); - assertEquals( - 1, - testBrowserProxy.handler.getCallCount('issueLensRegionRequest')); - assertEquals( - 0, - testBrowserProxy.handler.getCallCount( - 'issueTextSelectionRequest')); - assertTrue(selectionOverlayElement - .getShowSelectedRegionContextMenuForTesting()); - assertTrue(selectionOverlayElement - .getShowDetectedTextContextMenuOptionsForTesting()); + assertEquals( + 1, testBrowserProxy.handler.getCallCount('issueLensRegionRequest')); + assertEquals( + 0, + testBrowserProxy.handler.getCallCount('issueTextSelectionRequest')); + assertTrue( + selectionOverlayElement.getShowSelectedRegionContextMenuForTesting()); + assertTrue(selectionOverlayElement + .getShowDetectedTextContextMenuOptionsForTesting()); - testBrowserProxy.handler.reset(); - selectionOverlayElement.handleSelectTextForTesting(); + // Check that the region with text context menu options were shown. + assertEquals( + 1, + metrics.count( + 'Lens.Overlay.ByInvocationSource.AppMenu.ContextMenuOption.Shown', + ContextMenuOption.SELECT_TEXT_IN_REGION)); + assertEquals( + 1, + metrics.count( + 'Lens.Overlay.ByInvocationSource.AppMenu.ContextMenuOption.Shown', + ContextMenuOption.TRANSLATE_TEXT_IN_REGION)); + assertEquals( + 1, + metrics.count( + 'Lens.Overlay.ByInvocationSource.AppMenu.ContextMenuOption.Shown', + ContextMenuOption.SAVE_AS_IMAGE)); + assertEquals( + 1, + metrics.count( + 'Lens.Overlay.ByInvocationSource.AppMenu.ContextMenuOption.Shown', + ContextMenuOption.COPY_AS_IMAGE)); + assertEquals( + 1, + metrics.count( + 'Lens.Overlay.ContextMenuOption.Shown', + ContextMenuOption.SELECT_TEXT_IN_REGION)); + assertEquals( + 1, + metrics.count( + 'Lens.Overlay.ContextMenuOption.Shown', + ContextMenuOption.TRANSLATE_TEXT_IN_REGION)); + assertEquals( + 1, + metrics.count( + 'Lens.Overlay.ContextMenuOption.Shown', + ContextMenuOption.SAVE_AS_IMAGE)); + assertEquals( + 1, + metrics.count( + 'Lens.Overlay.ContextMenuOption.Shown', + ContextMenuOption.COPY_AS_IMAGE)); - const textQuery = await testBrowserProxy.handler.whenCalled( - 'issueTextSelectionRequest'); - assertDeepEquals('hello there test', textQuery); - assertEquals( - 0, - testBrowserProxy.handler.getCallCount('issueLensRegionRequest')); - }); + // Ensure that no other context menu options were shown. + assertEquals( + 4, + metrics.count( + 'Lens.Overlay.ByInvocationSource.AppMenu.ContextMenuOption.Shown')); + assertEquals(4, metrics.count('Lens.Overlay.ContextMenuOption.Shown')); + + testBrowserProxy.handler.reset(); + selectionOverlayElement.handleSelectTextForTesting(); + + const textQuery = await testBrowserProxy.handler.whenCalled( + 'issueTextSelectionRequest'); + assertDeepEquals('hello there test', textQuery); + assertEquals( + 0, testBrowserProxy.handler.getCallCount('issueLensRegionRequest')); + }); test( `verify that adding text after region selection triggers detected text ` + @@ -508,6 +579,12 @@ async () => { await simulateDrag( selectionOverlayElement, {x: 0, y: 0}, {x: 80, y: 40}); + + // Verify that the image and detected text context menu options are + // shown. + assertEquals( + 4, metrics.count('Lens.Overlay.ContextMenuOption.Shown')); + selectionOverlayElement.handleCopyAsImageForTesting(); await testBrowserProxy.handler.whenCalled('copyImage'); @@ -527,6 +604,11 @@ assertTrue(selectionOverlayElement .getShowSelectedRegionContextMenuForTesting()); + + // Verify that the image and detected text context menu options are + // logged again. + assertEquals( + 8, metrics.count('Lens.Overlay.ContextMenuOption.Shown')); }); test( @@ -582,6 +664,58 @@ 0, testBrowserProxy.handler.getCallCount('issueLensRegionRequest')); }); + test('verify that selecting text triggers context menu options', async () => { + testBrowserProxy.handler.reset(); + + // Drag that starts on a word. + const wordEl = selectionOverlayElement.$.textSelectionLayer + .getWordNodesForTesting()[1]!; + const wordElBoundingBox = wordEl.getBoundingClientRect(); + await simulateDrag( + selectionOverlayElement, { + x: wordElBoundingBox.left + (wordElBoundingBox.width / 2), + y: wordElBoundingBox.top + (wordElBoundingBox.height / 2), + }, + { + x: wordElBoundingBox.right, + y: wordElBoundingBox.bottom, + }); + + assertFalse( + selectionOverlayElement.getShowSelectedRegionContextMenuForTesting()); + assertTrue( + selectionOverlayElement.getShowSelectedTextContextMenuForTesting()); + + // Check that the text context menu options were shown. + assertEquals( + 1, + metrics.count( + 'Lens.Overlay.ByInvocationSource.AppMenu.ContextMenuOption.Shown', + ContextMenuOption.TRANSLATE_TEXT)); + assertEquals( + 1, + metrics.count( + 'Lens.Overlay.ByInvocationSource.AppMenu.ContextMenuOption.Shown', + ContextMenuOption.COPY_TEXT)); + assertEquals( + 1, + metrics.count( + 'Lens.Overlay.ContextMenuOption.Shown', + ContextMenuOption.TRANSLATE_TEXT)); + assertEquals( + 1, + metrics.count( + 'Lens.Overlay.ContextMenuOption.Shown', + ContextMenuOption.COPY_TEXT)); + + // Ensure that no other context menu options were shown. + assertEquals( + 2, + metrics.count( + 'Lens.Overlay.ByInvocationSource.AppMenu.ContextMenuOption.Shown')); + assertEquals(2, metrics.count('Lens.Overlay.ContextMenuOption.Shown')); + }); + test('verify that copy in selected text context menu works', async () => { testBrowserProxy.handler.reset();
diff --git a/chromecast/OWNERS b/chromecast/OWNERS index 6721921..a212118 100644 --- a/chromecast/OWNERS +++ b/chromecast/OWNERS
@@ -1,8 +1,8 @@ set noparent antoniori@google.com -sandv@google.com sanfin@chromium.org +shawnq@google.com vigeni@google.com yucliu@chromium.org @@ -14,7 +14,4 @@ per-file ...fuchsia*=file://build/fuchsia/OWNERS # For major changes, please use one of the reviewers above! -dnicoara@chromium.org -spang@chromium.org halliwell@chromium.org -seantopping@chromium.org
diff --git a/chromeos/components/editor_menu/COMMON_METADATA b/chromeos/ash/components/editor_menu/COMMON_METADATA similarity index 100% rename from chromeos/components/editor_menu/COMMON_METADATA rename to chromeos/ash/components/editor_menu/COMMON_METADATA
diff --git a/chromeos/ash/components/editor_menu/DIR_METADATA b/chromeos/ash/components/editor_menu/DIR_METADATA new file mode 100644 index 0000000..afebe8d7 --- /dev/null +++ b/chromeos/ash/components/editor_menu/DIR_METADATA
@@ -0,0 +1 @@ +mixins: "//chromeos/ash/components/editor_menu/COMMON_METADATA"
diff --git a/chromeos/ash/components/editor_menu/OWNERS b/chromeos/ash/components/editor_menu/OWNERS new file mode 100644 index 0000000..4f9c10b --- /dev/null +++ b/chromeos/ash/components/editor_menu/OWNERS
@@ -0,0 +1,2 @@ +file://chrome/browser/ash/input_method/OWNERS +file://chrome/browser/ui/ash/read_write_cards/OWNERS
diff --git a/chromeos/components/editor_menu/public/cpp/BUILD.gn b/chromeos/ash/components/editor_menu/public/cpp/BUILD.gn similarity index 100% rename from chromeos/components/editor_menu/public/cpp/BUILD.gn rename to chromeos/ash/components/editor_menu/public/cpp/BUILD.gn
diff --git a/chromeos/components/editor_menu/public/cpp/DEPS b/chromeos/ash/components/editor_menu/public/cpp/DEPS similarity index 100% rename from chromeos/components/editor_menu/public/cpp/DEPS rename to chromeos/ash/components/editor_menu/public/cpp/DEPS
diff --git a/chromeos/components/editor_menu/public/cpp/editor_helpers.cc b/chromeos/ash/components/editor_menu/public/cpp/editor_helpers.cc similarity index 89% rename from chromeos/components/editor_menu/public/cpp/editor_helpers.cc rename to chromeos/ash/components/editor_menu/public/cpp/editor_helpers.cc index 8ee9774..e65396b9 100644 --- a/chromeos/components/editor_menu/public/cpp/editor_helpers.cc +++ b/chromeos/ash/components/editor_menu/public/cpp/editor_helpers.cc
@@ -1,8 +1,8 @@ -// Copyright 2024 The Chromium Authors +// Copyright 2025 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/components/editor_menu/public/cpp/editor_helpers.h" +#include "chromeos/ash/components/editor_menu/public/cpp/editor_helpers.h" #include <string>
diff --git a/chromeos/components/editor_menu/public/cpp/editor_helpers.h b/chromeos/ash/components/editor_menu/public/cpp/editor_helpers.h similarity index 63% rename from chromeos/components/editor_menu/public/cpp/editor_helpers.h rename to chromeos/ash/components/editor_menu/public/cpp/editor_helpers.h index cbae805..507affb 100644 --- a/chromeos/components/editor_menu/public/cpp/editor_helpers.h +++ b/chromeos/ash/components/editor_menu/public/cpp/editor_helpers.h
@@ -1,9 +1,9 @@ -// Copyright 2024 The Chromium Authors +// Copyright 2025 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_COMPONENTS_EDITOR_MENU_PUBLIC_CPP_EDITOR_HELPERS_H_ -#define CHROMEOS_COMPONENTS_EDITOR_MENU_PUBLIC_CPP_EDITOR_HELPERS_H_ +#ifndef CHROMEOS_ASH_COMPONENTS_EDITOR_MENU_PUBLIC_CPP_EDITOR_HELPERS_H_ +#define CHROMEOS_ASH_COMPONENTS_EDITOR_MENU_PUBLIC_CPP_EDITOR_HELPERS_H_ #include <string> @@ -18,4 +18,4 @@ } // namespace chromeos::editor_helpers -#endif // CHROMEOS_COMPONENTS_EDITOR_MENU_PUBLIC_CPP_EDITOR_HELPERS_H_ +#endif // CHROMEOS_ASH_COMPONENTS_EDITOR_MENU_PUBLIC_CPP_EDITOR_HELPERS_H_
diff --git a/chromeos/components/editor_menu/public/cpp/editor_helpers_unittest.cc b/chromeos/ash/components/editor_menu/public/cpp/editor_helpers_unittest.cc similarity index 94% rename from chromeos/components/editor_menu/public/cpp/editor_helpers_unittest.cc rename to chromeos/ash/components/editor_menu/public/cpp/editor_helpers_unittest.cc index 09370fa..afe35c1 100644 --- a/chromeos/components/editor_menu/public/cpp/editor_helpers_unittest.cc +++ b/chromeos/ash/components/editor_menu/public/cpp/editor_helpers_unittest.cc
@@ -1,8 +1,8 @@ -// Copyright 2024 The Chromium Authors +// Copyright 2025 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/components/editor_menu/public/cpp/editor_helpers.h" +#include "chromeos/ash/components/editor_menu/public/cpp/editor_helpers.h" #include "base/test/gtest_util.h" #include "testing/gtest/include/gtest/gtest.h" @@ -93,4 +93,4 @@ } } // namespace -} // namespace ash::input_method +} // namespace chromeos::editor_helpers
diff --git a/chromeos/components/editor_menu/public/cpp/icon.cc b/chromeos/ash/components/editor_menu/public/cpp/icon.cc similarity index 88% rename from chromeos/components/editor_menu/public/cpp/icon.cc rename to chromeos/ash/components/editor_menu/public/cpp/icon.cc index 339b6c1..8d70b1a7 100644 --- a/chromeos/components/editor_menu/public/cpp/icon.cc +++ b/chromeos/ash/components/editor_menu/public/cpp/icon.cc
@@ -1,13 +1,13 @@ -// Copyright 2023 The Chromium Authors +// Copyright 2025 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/components/editor_menu/public/cpp/icon.h" +#include "chromeos/ash/components/editor_menu/public/cpp/icon.h" #include <string_view> #include "build/branding_buildflags.h" -#include "chromeos/components/editor_menu/public/cpp/preset_text_query.h" +#include "chromeos/ash/components/editor_menu/public/cpp/preset_text_query.h" #include "chromeos/ui/vector_icons/vector_icons.h" #include "components/vector_icons/vector_icons.h" #include "ui/gfx/vector_icon_types.h"
diff --git a/chromeos/ash/components/editor_menu/public/cpp/icon.h b/chromeos/ash/components/editor_menu/public/cpp/icon.h new file mode 100644 index 0000000..85b078a --- /dev/null +++ b/chromeos/ash/components/editor_menu/public/cpp/icon.h
@@ -0,0 +1,23 @@ +// Copyright 2025 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_COMPONENTS_EDITOR_MENU_PUBLIC_CPP_ICON_H_ +#define CHROMEOS_ASH_COMPONENTS_EDITOR_MENU_PUBLIC_CPP_ICON_H_ + +#include "base/component_export.h" +#include "chromeos/ash/components/editor_menu/public/cpp/preset_text_query.h" + +namespace gfx { +struct VectorIcon; +} + +namespace chromeos::editor_menu { + +const COMPONENT_EXPORT(EDITOR_MENU_PUBLIC_CPP) + gfx::VectorIcon& GetIconForPresetQueryCategory( + PresetQueryCategory category); + +} // namespace chromeos::editor_menu + +#endif // CHROMEOS_ASH_COMPONENTS_EDITOR_MENU_PUBLIC_CPP_ICON_H_
diff --git a/chromeos/components/editor_menu/public/cpp/preset_text_query.cc b/chromeos/ash/components/editor_menu/public/cpp/preset_text_query.cc similarity index 79% rename from chromeos/components/editor_menu/public/cpp/preset_text_query.cc rename to chromeos/ash/components/editor_menu/public/cpp/preset_text_query.cc index 0a4f2b22..78087f53 100644 --- a/chromeos/components/editor_menu/public/cpp/preset_text_query.cc +++ b/chromeos/ash/components/editor_menu/public/cpp/preset_text_query.cc
@@ -1,8 +1,8 @@ -// Copyright 2024 The Chromium Authors +// Copyright 2025 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/components/editor_menu/public/cpp/preset_text_query.h" +#include "chromeos/ash/components/editor_menu/public/cpp/preset_text_query.h" #include <string_view>
diff --git a/chromeos/components/editor_menu/public/cpp/preset_text_query.h b/chromeos/ash/components/editor_menu/public/cpp/preset_text_query.h similarity index 77% rename from chromeos/components/editor_menu/public/cpp/preset_text_query.h rename to chromeos/ash/components/editor_menu/public/cpp/preset_text_query.h index 35fbe3b..091356e 100644 --- a/chromeos/components/editor_menu/public/cpp/preset_text_query.h +++ b/chromeos/ash/components/editor_menu/public/cpp/preset_text_query.h
@@ -1,9 +1,9 @@ -// Copyright 2024 The Chromium Authors +// Copyright 2025 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_COMPONENTS_EDITOR_MENU_PUBLIC_CPP_PRESET_TEXT_QUERY_H_ -#define CHROMEOS_COMPONENTS_EDITOR_MENU_PUBLIC_CPP_PRESET_TEXT_QUERY_H_ +#ifndef CHROMEOS_ASH_COMPONENTS_EDITOR_MENU_PUBLIC_CPP_PRESET_TEXT_QUERY_H_ +#define CHROMEOS_ASH_COMPONENTS_EDITOR_MENU_PUBLIC_CPP_PRESET_TEXT_QUERY_H_ #include <string> #include <string_view> @@ -42,4 +42,4 @@ } // namespace chromeos::editor_menu -#endif // CHROMEOS_COMPONENTS_EDITOR_MENU_PUBLIC_CPP_PRESET_TEXT_QUERY_H_ +#endif // CHROMEOS_ASH_COMPONENTS_EDITOR_MENU_PUBLIC_CPP_PRESET_TEXT_QUERY_H_
diff --git a/chromeos/components/editor_menu/DIR_METADATA b/chromeos/components/editor_menu/DIR_METADATA deleted file mode 100644 index 9143772..0000000 --- a/chromeos/components/editor_menu/DIR_METADATA +++ /dev/null
@@ -1 +0,0 @@ -mixins: "//chromeos/components/editor_menu/COMMON_METADATA"
diff --git a/chromeos/components/editor_menu/OWNERS b/chromeos/components/editor_menu/OWNERS deleted file mode 100644 index a349b67..0000000 --- a/chromeos/components/editor_menu/OWNERS +++ /dev/null
@@ -1,2 +0,0 @@ -file://chrome/browser/ash/input_method/OWNERS -file://chrome/browser/ui/chromeos/read_write_cards/OWNERS
diff --git a/chromeos/components/editor_menu/public/cpp/icon.h b/chromeos/components/editor_menu/public/cpp/icon.h deleted file mode 100644 index d00f071..0000000 --- a/chromeos/components/editor_menu/public/cpp/icon.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 CHROMEOS_COMPONENTS_EDITOR_MENU_PUBLIC_CPP_ICON_H_ -#define CHROMEOS_COMPONENTS_EDITOR_MENU_PUBLIC_CPP_ICON_H_ - -#include "base/component_export.h" -#include "chromeos/components/editor_menu/public/cpp/preset_text_query.h" - -namespace gfx { -struct VectorIcon; -} - -namespace chromeos::editor_menu { - -const COMPONENT_EXPORT(EDITOR_MENU_PUBLIC_CPP) - gfx::VectorIcon& GetIconForPresetQueryCategory( - PresetQueryCategory category); - -} // namespace chromeos::editor_menu - -#endif // CHROMEOS_COMPONENTS_EDITOR_MENU_PUBLIC_CPP_ICON_H_
diff --git a/clank b/clank index 55a0561..c1dc9b6 160000 --- a/clank +++ b/clank
@@ -1 +1 @@ -Subproject commit 55a05617506990654db113866e78b0480b9b10f3 +Subproject commit c1dc9b6b30f065a36bba170249ef302124342b45
diff --git a/components/BUILD.gn b/components/BUILD.gn index dcb1d7da..73eb5e40 100644 --- a/components/BUILD.gn +++ b/components/BUILD.gn
@@ -671,7 +671,6 @@ "//components/signin/public/android:signin_java_test_support", "//components/spellcheck/browser/android:java", "//components/translate/content/android:unit_tests", - "//components/variations:variations_associated_data", "//components/variations/android:variations_java", "//components/webapps/browser/android:java", "//components/webapps/browser/android:unit_tests",
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn index 53215fd1..22a4531 100644 --- a/components/autofill/core/browser/BUILD.gn +++ b/components/autofill/core/browser/BUILD.gn
@@ -974,6 +974,7 @@ "metrics/autofill_metrics_test_base.h", "metrics/ukm_metrics_test_utils.cc", "metrics/ukm_metrics_test_utils.h", + "payments/bnpl_manager_test_api.h", "payments/credit_card_access_manager_test_api.h", "payments/credit_card_access_manager_test_base.cc", "payments/credit_card_access_manager_test_base.h",
diff --git a/components/autofill/core/browser/form_parsing/address_field_parser.cc b/components/autofill/core/browser/form_parsing/address_field_parser.cc index 0c4558bd..db104dcb 100644 --- a/components/autofill/core/browser/form_parsing/address_field_parser.cc +++ b/components/autofill/core/browser/form_parsing/address_field_parser.cc
@@ -24,16 +24,6 @@ namespace { -base::span<const MatchPatternRef> GetMatchPatterns(std::string_view name, - ParsingContext& context) { - return GetMatchPatterns(name, context.page_language, context.pattern_file); -} - -base::span<const MatchPatternRef> GetMatchPatterns(FieldType type, - ParsingContext& context) { - return GetMatchPatterns(type, context.page_language, context.pattern_file); -} - // Removes a MatchAttribute from MatchParams. MatchParams WithoutAttribute(MatchParams p, MatchAttribute attribute) { p.attributes.erase(attribute); @@ -60,30 +50,17 @@ const AutofillField* const initial_field = scanner->Cursor(); size_t saved_cursor = scanner->SaveCursor(); - base::span<const MatchPatternRef> email_patterns = - GetMatchPatterns("EMAIL_ADDRESS", context); - base::span<const MatchPatternRef> address_patterns = - GetMatchPatterns("ADDRESS_LOOKUP", context); - base::span<const MatchPatternRef> address_ignore_patterns = - GetMatchPatterns("ADDRESS_NAME_IGNORED", context); - base::span<const MatchPatternRef> attention_ignore_patterns = - GetMatchPatterns("ATTENTION_IGNORED", context); - base::span<const MatchPatternRef> region_ignore_patterns = - GetMatchPatterns("REGION_IGNORED", context); - // Allow address fields to appear in any order. size_t begin_trailing_non_labeled_fields = 0; bool has_trailing_non_labeled_fields = false; while (!scanner->IsEnd()) { const size_t cursor = scanner->SaveCursor(); // Ignore "Address Lookup" field. http://crbug.com/427622 - if (ParseField(context, scanner, address_patterns, nullptr, - "ADDRESS_LOOKUP") || - ParseField(context, scanner, address_ignore_patterns, nullptr, - "ADDRESS_NAME_IGNORED")) { + if (ParseField(context, scanner, "ADDRESS_LOOKUP") || + ParseField(context, scanner, "ADDRESS_NAME_IGNORED")) { continue; // Ignore email addresses. - } else if (ParseField(context, scanner, email_patterns, nullptr, "kEmailRe", + } else if (ParseField(context, scanner, "EMAIL_ADDRESS", nullptr, [](const MatchParams& p) { return WithFieldType(p, FormControlType::kTextArea); })) { @@ -93,10 +70,8 @@ address_field->ParseCompany(context, scanner)) { has_trailing_non_labeled_fields = false; continue; - } else if (ParseField(context, scanner, attention_ignore_patterns, nullptr, - "ATTENTION_IGNORED") || - ParseField(context, scanner, region_ignore_patterns, nullptr, - "REGION_IGNORED")) { + } else if (ParseField(context, scanner, "ATTENTION_IGNORED") || + ParseField(context, scanner, "REGION_IGNORED")) { // We ignore the following: // * Attention. // * Province/Region/Other. @@ -240,10 +215,7 @@ if (company_) return false; - base::span<const MatchPatternRef> company_patterns = - GetMatchPatterns("COMPANY_NAME", context); - return ParseField(context, scanner, company_patterns, &company_, - "COMPANY_NAME"); + return ParseField(context, scanner, "COMPANY_NAME", &company_); } bool AddressFieldParser::ParseAddressFieldSequence(ParsingContext& context, @@ -421,16 +393,12 @@ if (address1_ || street_address_) return false; - base::span<const MatchPatternRef> address_line1_patterns = - GetMatchPatterns("ADDRESS_LINE_1", context); - // Address line 1 is skipped if a |street_name_|, |house_number_| combination // is present. if (!(street_name_ && house_number_) && - !ParseField(context, scanner, address_line1_patterns, &address1_, - "ADDRESS_LINE_1") && - !ParseField(context, scanner, address_line1_patterns, &street_address_, - "ADDRESS_LINE_1", [](const MatchParams& p) { + !ParseField(context, scanner, "ADDRESS_LINE_1", &address1_) && + !ParseField(context, scanner, "ADDRESS_LINE_1", &street_address_, + [](const MatchParams& p) { return WithFieldType(p, FormControlType::kTextArea); })) { return false; @@ -439,23 +407,14 @@ if (street_address_) return true; - base::span<const MatchPatternRef> address_line2_patterns = - GetMatchPatterns("ADDRESS_LINE_2", context); - - if (!ParseField(context, scanner, address_line2_patterns, &address2_, - "ADDRESS_LINE_2")) { + if (!ParseField(context, scanner, "ADDRESS_LINE_2", &address2_)) { return true; } - base::span<const MatchPatternRef> address_line_extra_patterns = - GetMatchPatterns("ADDRESS_LINE_EXTRA", context); - // Optionally parse address line 3. This uses the same regexp as address 2 // above. - if (!ParseField(context, scanner, address_line_extra_patterns, &address3_, - "ADDRESS_LINE_EXTRA") && - !ParseField(context, scanner, address_line2_patterns, &address3_, - "ADDRESS_LINE_2")) { + if (!ParseField(context, scanner, "ADDRESS_LINE_EXTRA", &address3_) && + !ParseField(context, scanner, "ADDRESS_LINE_2", &address3_)) { return true; } @@ -464,8 +423,7 @@ // // Since these are rare, don't bother considering unlabeled lines as extra // address lines. - while (ParseField(context, scanner, address_line_extra_patterns, nullptr, - "ADDRESS_LINE_EXTRA")) { + while (ParseField(context, scanner, "ADDRESS_LINE_EXTRA")) { // Consumed a surplus line, try for another. } return true; @@ -523,18 +481,13 @@ if (zip_) return false; - base::span<const MatchPatternRef> zip_code_patterns = - GetMatchPatterns("ZIP_CODE", context); - base::span<const MatchPatternRef> four_digit_zip_code_patterns = - GetMatchPatterns("ZIP_4", context); - - if (!ParseField(context, scanner, zip_code_patterns, &zip_, "ZIP_CODE")) { + if (!ParseField(context, scanner, "ZIP_CODE", &zip_)) { return false; } // Look for a zip+4, whose field name will also often contain // the substring "zip". - ParseField(context, scanner, four_digit_zip_code_patterns, &zip4_, "ZIP_4"); + ParseField(context, scanner, "ZIP_4", &zip4_); return true; } @@ -543,9 +496,7 @@ if (city_) return false; - base::span<const MatchPatternRef> city_patterns = - GetMatchPatterns("CITY", context); - return ParseField(context, scanner, city_patterns, &city_, "CITY"); + return ParseField(context, scanner, "CITY", &city_); } bool AddressFieldParser::ParseState(ParsingContext& context, @@ -553,9 +504,7 @@ if (state_) return false; - base::span<const MatchPatternRef> patterns_state = - GetMatchPatterns("STATE", context); - return ParseField(context, scanner, patterns_state, &state_, "STATE"); + return ParseField(context, scanner, "STATE", &state_); } bool AddressFieldParser::ParseStreetLocation(ParsingContext& context, @@ -569,10 +518,8 @@ return false; } - base::span<const MatchPatternRef> street_location_patterns = - GetMatchPatterns(ADDRESS_HOME_STREET_LOCATION, context); - return ParseField(context, scanner, street_location_patterns, - &street_location_, "ADDRESS_HOME_STREET_LOCATION"); + return ParseField(context, scanner, "ADDRESS_HOME_STREET_LOCATION", + &street_location_); } bool AddressFieldParser::ParseStreetName(ParsingContext& context, @@ -581,10 +528,8 @@ return false; } - base::span<const MatchPatternRef> street_name_patterns = - GetMatchPatterns(ADDRESS_HOME_STREET_NAME, context); - return ParseField(context, scanner, street_name_patterns, &street_name_, - "ADDRESS_HOME_STREET_NAME"); + return ParseField(context, scanner, "ADDRESS_HOME_STREET_NAME", + &street_name_); } bool AddressFieldParser::ParseHouseNumber(ParsingContext& context, @@ -593,10 +538,8 @@ return false; } - base::span<const MatchPatternRef> house_number_patterns = - GetMatchPatterns(ADDRESS_HOME_HOUSE_NUMBER, context); - return ParseField(context, scanner, house_number_patterns, &house_number_, - "ADDRESS_HOME_HOUSE_NUMBER"); + return ParseField(context, scanner, "ADDRESS_HOME_HOUSE_NUMBER", + &house_number_); } bool AddressFieldParser::ParseApartmentNumber(ParsingContext& context, @@ -607,10 +550,8 @@ return false; } - base::span<const MatchPatternRef> apartment_number_patterns = - GetMatchPatterns(ADDRESS_HOME_APT_NUM, context); - return ParseField(context, scanner, apartment_number_patterns, - &apartment_number_, "ADDRESS_HOME_APT_NUM"); + return ParseField(context, scanner, "ADDRESS_HOME_APT_NUM", + &apartment_number_); } bool AddressFieldParser::ParseBetweenStreetsOrLandmark( @@ -623,11 +564,8 @@ return false; } - base::span<const MatchPatternRef> between_streets_or_landmark_patterns = - GetMatchPatterns("BETWEEN_STREETS_OR_LANDMARK", context); - return ParseField(context, scanner, between_streets_or_landmark_patterns, - &between_streets_or_landmark_, - "BETWEEN_STREETS_OR_LANDMARK"); + return ParseField(context, scanner, "BETWEEN_STREETS_OR_LANDMARK", + &between_streets_or_landmark_); } bool AddressFieldParser::ParseOverflowAndLandmark(ParsingContext& context, @@ -639,10 +577,8 @@ return false; } - base::span<const MatchPatternRef> overflow_and_landmark_patterns = - GetMatchPatterns("OVERFLOW_AND_LANDMARK", context); - return ParseField(context, scanner, overflow_and_landmark_patterns, - &overflow_and_landmark_, "OVERFLOW_AND_LANDMARK"); + return ParseField(context, scanner, "OVERFLOW_AND_LANDMARK", + &overflow_and_landmark_); } bool AddressFieldParser::ParseOverflow(ParsingContext& context, @@ -653,10 +589,7 @@ return false; } - base::span<const MatchPatternRef> overflow_patterns = - GetMatchPatterns("OVERFLOW", context); - return ParseField(context, scanner, overflow_patterns, &overflow_, - "OVERFLOW"); + return ParseField(context, scanner, "OVERFLOW", &overflow_); } bool AddressFieldParser::ParseBetweenStreetsFields(ParsingContext& context, @@ -667,29 +600,21 @@ return false; } - base::span<const MatchPatternRef> between_streets_patterns = - GetMatchPatterns("BETWEEN_STREETS", context); - base::span<const MatchPatternRef> between_streets_line_1_patterns = - GetMatchPatterns("BETWEEN_STREETS_LINE_1", context); - base::span<const MatchPatternRef> between_streets_line_2_patterns = - GetMatchPatterns("BETWEEN_STREETS_LINE_2", context); - if (!between_streets_ && !between_streets_line_1_ && - ParseField(context, scanner, between_streets_patterns, &between_streets_, - "BETWEEN_STREETS")) { + ParseField(context, scanner, "BETWEEN_STREETS", &between_streets_)) { return true; } if (!between_streets_line_1_ && - ParseField(context, scanner, between_streets_line_1_patterns, - &between_streets_line_1_, "BETWEEN_STREETS_LINE_1")) { + ParseField(context, scanner, "BETWEEN_STREETS_LINE_1", + &between_streets_line_1_)) { return true; } if (!between_streets_line_2_ && (between_streets_ || between_streets_line_1_) && - ParseField(context, scanner, between_streets_line_2_patterns, - &between_streets_line_2_, "BETWEEN_STREETS_LINE_2")) { + ParseField(context, scanner, "BETWEEN_STREETS_LINE_2", + &between_streets_line_2_)) { return true; } return false; @@ -700,25 +625,22 @@ AddressFieldParser::ParseNameAndLabelSeparately( ParsingContext& context, AutofillScanner* scanner, - base::span<const MatchPatternRef> patterns, - std::optional<FieldAndMatchInfo>* match, - const char* regex_name) { + const char* regex_name, + std::optional<FieldAndMatchInfo>* match) { if (scanner->IsEnd()) return RESULT_MATCH_NONE; std::optional<FieldAndMatchInfo> cur_match; size_t saved_cursor = scanner->SaveCursor(); - bool parsed_name = - ParseField(context, scanner, patterns, &cur_match, regex_name, - [](const MatchParams& p) { - return WithoutAttribute(p, MatchAttribute::kLabel); - }); + bool parsed_name = ParseField( + context, scanner, regex_name, &cur_match, [](const MatchParams& p) { + return WithoutAttribute(p, MatchAttribute::kLabel); + }); scanner->RewindTo(saved_cursor); - bool parsed_label = - ParseField(context, scanner, patterns, &cur_match, regex_name, - [](const MatchParams& p) { - return WithoutAttribute(p, MatchAttribute::kName); - }); + bool parsed_label = ParseField( + context, scanner, regex_name, &cur_match, [](const MatchParams& p) { + return WithoutAttribute(p, MatchAttribute::kName); + }); // Only consider high quality label matches to avoid false positives. parsed_label = parsed_label && cur_match->match_info.matched_attribute == @@ -947,13 +869,8 @@ if (zip_) return RESULT_MATCH_NONE; - base::span<const MatchPatternRef> zip_code_patterns = - GetMatchPatterns("ZIP_CODE", context); - base::span<const MatchPatternRef> four_digit_zip_code_patterns = - GetMatchPatterns("ZIP_4", context); - - ParseNameLabelResult result = ParseNameAndLabelSeparately( - context, scanner, zip_code_patterns, &zip_, "ZIP_CODE"); + ParseNameLabelResult result = + ParseNameAndLabelSeparately(context, scanner, "ZIP_CODE", &zip_); if (result != RESULT_MATCH_NAME_LABEL || scanner->IsEnd()) return result; @@ -975,7 +892,7 @@ if (!found_non_zip4) { // Look for a zip+4, whose field name will also often contain // the substring "zip". - ParseField(context, scanner, four_digit_zip_code_patterns, &zip4_, "ZIP_4"); + ParseField(context, scanner, "ZIP_4", &zip4_); } return result; } @@ -988,12 +905,9 @@ return RESULT_MATCH_NONE; } - base::span<const MatchPatternRef> dependent_locality_patterns = - GetMatchPatterns(ADDRESS_HOME_DEPENDENT_LOCALITY, context.page_language, - context.pattern_file); - return ParseNameAndLabelSeparately( - context, scanner, dependent_locality_patterns, &dependent_locality_, - "ADDRESS_HOME_DEPENDENT_LOCALITY"); + return ParseNameAndLabelSeparately(context, scanner, + "ADDRESS_HOME_DEPENDENT_LOCALITY", + &dependent_locality_); } AddressFieldParser::ParseNameLabelResult @@ -1002,10 +916,7 @@ if (city_) return RESULT_MATCH_NONE; - base::span<const MatchPatternRef> city_patterns = - GetMatchPatterns("CITY", context); - return ParseNameAndLabelSeparately(context, scanner, city_patterns, &city_, - "CITY"); + return ParseNameAndLabelSeparately(context, scanner, "CITY", &city_); } AddressFieldParser::ParseNameLabelResult @@ -1014,10 +925,7 @@ if (state_) return RESULT_MATCH_NONE; - base::span<const MatchPatternRef> patterns_state = - GetMatchPatterns("STATE", context); - return ParseNameAndLabelSeparately(context, scanner, patterns_state, &state_, - "STATE"); + return ParseNameAndLabelSeparately(context, scanner, "STATE", &state_); } AddressFieldParser::ParseNameLabelResult @@ -1026,21 +934,15 @@ if (country_) return RESULT_MATCH_NONE; - base::span<const MatchPatternRef> country_patterns = - GetMatchPatterns("COUNTRY", context); - base::span<const MatchPatternRef> country_location_patterns = - GetMatchPatterns("COUNTRY_LOCATION", context); - - ParseNameLabelResult country_result = ParseNameAndLabelSeparately( - context, scanner, country_patterns, &country_, "COUNTRY"); + ParseNameLabelResult country_result = + ParseNameAndLabelSeparately(context, scanner, "COUNTRY", &country_); if (country_result != RESULT_MATCH_NONE) return country_result; // The occasional page (e.g. google account registration page) calls this a // "location". However, this only makes sense for select tags. - return ParseNameAndLabelSeparately(context, scanner, - country_location_patterns, &country_, - "COUNTRY_LOCATION"); + return ParseNameAndLabelSeparately(context, scanner, "COUNTRY_LOCATION", + &country_); } AddressFieldParser::ParseNameLabelResult @@ -1055,11 +957,9 @@ return RESULT_MATCH_NONE; } - base::span<const MatchPatternRef> between_streets_or_landmark_patterns = - GetMatchPatterns("BETWEEN_STREETS_OR_LANDMARK", context); - auto result = ParseNameAndLabelSeparately( - context, scanner, between_streets_or_landmark_patterns, - &between_streets_or_landmark_, "BETWEEN_STREETS_OR_LANDMARK"); + auto result = ParseNameAndLabelSeparately(context, scanner, + "BETWEEN_STREETS_OR_LANDMARK", + &between_streets_or_landmark_); return result; } @@ -1076,11 +976,8 @@ return RESULT_MATCH_NONE; } - base::span<const MatchPatternRef> overflow_and_landmark_patterns = - GetMatchPatterns("OVERFLOW_AND_LANDMARK", context); auto result = ParseNameAndLabelSeparately( - context, scanner, overflow_and_landmark_patterns, &overflow_and_landmark_, - "OVERFLOW_AND_LANDMARK"); + context, scanner, "OVERFLOW_AND_LANDMARK", &overflow_and_landmark_); return result; } @@ -1095,10 +992,7 @@ return RESULT_MATCH_NONE; } - base::span<const MatchPatternRef> overflow_patterns = - GetMatchPatterns("OVERFLOW", context); - return ParseNameAndLabelSeparately(context, scanner, overflow_patterns, - &overflow_, "OVERFLOW"); + return ParseNameAndLabelSeparately(context, scanner, "OVERFLOW", &overflow_); } AddressFieldParser::ParseNameLabelResult @@ -1111,10 +1005,7 @@ return RESULT_MATCH_NONE; } - base::span<const MatchPatternRef> landmark_patterns = - GetMatchPatterns("LANDMARK", context); - return ParseNameAndLabelSeparately(context, scanner, landmark_patterns, - &landmark_, "LANDMARK"); + return ParseNameAndLabelSeparately(context, scanner, "LANDMARK", &landmark_); } AddressFieldParser::ParseNameLabelResult @@ -1129,10 +1020,8 @@ return RESULT_MATCH_NONE; } - base::span<const MatchPatternRef> between_streets_patterns = - GetMatchPatterns("BETWEEN_STREETS", context); - return ParseNameAndLabelSeparately(context, scanner, between_streets_patterns, - &between_streets_, "BETWEEN_STREETS"); + return ParseNameAndLabelSeparately(context, scanner, "BETWEEN_STREETS", + &between_streets_); } AddressFieldParser::ParseNameLabelResult @@ -1148,19 +1037,11 @@ } if (!between_streets_line_1_) { - base::span<const MatchPatternRef> between_streets_patterns_line_1 = - GetMatchPatterns("BETWEEN_STREETS_LINE_1", context.page_language, - context.pattern_file); return ParseNameAndLabelSeparately( - context, scanner, between_streets_patterns_line_1, - &between_streets_line_1_, "BETWEEN_STREETS_LINE_1"); + context, scanner, "BETWEEN_STREETS_LINE_1", &between_streets_line_1_); } else if (!between_streets_line_2_) { - base::span<const MatchPatternRef> between_streets_patterns_line_2 = - GetMatchPatterns("BETWEEN_STREETS_LINE_2", context.page_language, - context.pattern_file); return ParseNameAndLabelSeparately( - context, scanner, between_streets_patterns_line_2, - &between_streets_line_2_, "BETWEEN_STREETS_LINE_2"); + context, scanner, "BETWEEN_STREETS_LINE_2", &between_streets_line_2_); } return RESULT_MATCH_NONE; @@ -1176,10 +1057,8 @@ return RESULT_MATCH_NONE; } - base::span<const MatchPatternRef> admin_level2_patterns = - GetMatchPatterns("ADMIN_LEVEL_2", context); - return ParseNameAndLabelSeparately(context, scanner, admin_level2_patterns, - &admin_level2_, "ADMIN_LEVEL_2"); + return ParseNameAndLabelSeparately(context, scanner, "ADMIN_LEVEL_2", + &admin_level2_); } bool AddressFieldParser::SetFieldAndAdvanceCursor( @@ -1217,11 +1096,8 @@ return RESULT_MATCH_NONE; } - base::span<const MatchPatternRef> house_number_and_apt_patterns = - GetMatchPatterns("ADDRESS_HOME_HOUSE_NUMBER_AND_APT", context); - return ParseField(context, scanner, house_number_and_apt_patterns, - &house_number_and_apt_, - "ADDRESS_HOME_HOUSE_NUMBER_AND_APT"); + return ParseField(context, scanner, "ADDRESS_HOME_HOUSE_NUMBER_AND_APT", + &house_number_and_apt_); } bool AddressFieldParser::PossiblyAStructuredAddressForm() const {
diff --git a/components/autofill/core/browser/form_parsing/address_field_parser.h b/components/autofill/core/browser/form_parsing/address_field_parser.h index 570dd5d..4ea289b9 100644 --- a/components/autofill/core/browser/form_parsing/address_field_parser.h +++ b/components/autofill/core/browser/form_parsing/address_field_parser.h
@@ -108,17 +108,16 @@ bool ParseFieldSpecificsForHouseNumberAndApt(ParsingContext& context, AutofillScanner* scanner); - // Like ParseField(), but applies `pattern` against the name and - // label of the current field separately. If the return value is + // Like ParseField(), but applies pattern named with `regex_name` against the + // name and label of the current field separately. If the return value is // RESULT_MATCH_NAME_LABEL, then `scanner` advances and `match` is filled if // it is non-NULL. Otherwise `scanner` does not advance and `match` does not // change. static ParseNameLabelResult ParseNameAndLabelSeparately( ParsingContext& context, AutofillScanner* scanner, - base::span<const MatchPatternRef> patterns, - std::optional<FieldAndMatchInfo>* match, - const char* regex_name); + const char* regex_name, + std::optional<FieldAndMatchInfo>* match); // Run matches on the name and label separately. If the return result is // RESULT_MATCH_NAME_LABEL, then `scanner` advances and the field is set.
diff --git a/components/autofill/core/browser/form_parsing/alternative_name_field_parser.cc b/components/autofill/core/browser/form_parsing/alternative_name_field_parser.cc index 8c2d730..68262a1 100644 --- a/components/autofill/core/browser/form_parsing/alternative_name_field_parser.cc +++ b/components/autofill/core/browser/form_parsing/alternative_name_field_parser.cc
@@ -38,23 +38,15 @@ auto v = base::WrapUnique(new AlternativeFullNameField()); scanner->SaveCursor(); - base::span<const MatchPatternRef> address_name_ignored_patterns = - GetMatchPatterns("ADDRESS_NAME_IGNORED", context.page_language, - context.pattern_file); - base::span<const MatchPatternRef> alternative_full_name_patterns = - GetMatchPatterns("ALTERNATIVE_FULL_NAME", context.page_language, - context.pattern_file); - while (!scanner->IsEnd()) { // Skip over address label fields, which can have misleading names // e.g. "title" or "name". - if (ParseField(context, scanner, address_name_ignored_patterns, nullptr, - "ADDRESS_NAME_IGNORED")) { + if (ParseField(context, scanner, "ADDRESS_NAME_IGNORED")) { continue; } if (!v->alternative_full_name_ && - ParseField(context, scanner, alternative_full_name_patterns, - &v->alternative_full_name_, "ALTERNATIVE_FULL_NAME")) { + ParseField(context, scanner, "ALTERNATIVE_FULL_NAME", + &v->alternative_full_name_)) { continue; } break; @@ -102,31 +94,20 @@ auto v = base::WrapUnique(new AlternativeFamilyAndGivenNameField()); scanner->SaveCursor(); - base::span<const MatchPatternRef> address_name_ignored_patterns = - GetMatchPatterns("ADDRESS_NAME_IGNORED", context.page_language, - context.pattern_file); - base::span<const MatchPatternRef> alternative_family_name_patterns = - GetMatchPatterns("ALTERNATIVE_FAMILY_NAME", context.page_language, - context.pattern_file); - base::span<const MatchPatternRef> alternative_given_name_patterns = - GetMatchPatterns("ALTERNATIVE_GIVEN_NAME", context.page_language, - context.pattern_file); - while (!scanner->IsEnd()) { // Skip over address label fields, which can have misleading names // e.g. "title" or "name". - if (ParseField(context, scanner, address_name_ignored_patterns, nullptr, - "ADDRESS_NAME_IGNORED")) { + if (ParseField(context, scanner, "ADDRESS_NAME_IGNORED")) { continue; } if (!v->alternative_family_name_ && - ParseField(context, scanner, alternative_family_name_patterns, - &v->alternative_family_name_, "ALTERNATIVE_FAMILY_NAME")) { + ParseField(context, scanner, "ALTERNATIVE_FAMILY_NAME", + &v->alternative_family_name_)) { continue; } if (!v->alternative_given_name_ && - ParseField(context, scanner, alternative_given_name_patterns, - &v->alternative_given_name_, "ALTERNATIVE_GIVEN_NAME")) { + ParseField(context, scanner, "ALTERNATIVE_GIVEN_NAME", + &v->alternative_given_name_)) { continue; }
diff --git a/components/autofill/core/browser/form_parsing/autofill_ai_field_parser.cc b/components/autofill/core/browser/form_parsing/autofill_ai_field_parser.cc index 32544715..53442473 100644 --- a/components/autofill/core/browser/form_parsing/autofill_ai_field_parser.cc +++ b/components/autofill/core/browser/form_parsing/autofill_ai_field_parser.cc
@@ -17,9 +17,7 @@ #if BUILDFLAG(USE_INTERNAL_AUTOFILL_PATTERNS) CHECK_EQ(context.pattern_file, PatternFile::kAutofillAi); std::optional<FieldAndMatchInfo> match; - base::span<const MatchPatternRef> patterns = GetMatchPatterns( - "AUTOFILL_AI", /*language_code=*/std::nullopt, context.pattern_file); - if (ParseField(context, scanner, patterns, &match, "AUTOFILL_AI")) { + if (ParseField(context, scanner, "AUTOFILL_AI", &match)) { return std::make_unique<AutofillAiFieldParser>(std::move(*match)); } #endif
diff --git a/components/autofill/core/browser/form_parsing/email_field_parser.cc b/components/autofill/core/browser/form_parsing/email_field_parser.cc index 1d67034..7115765 100644 --- a/components/autofill/core/browser/form_parsing/email_field_parser.cc +++ b/components/autofill/core/browser/form_parsing/email_field_parser.cc
@@ -20,9 +20,7 @@ AutofillScanner* scanner) { std::optional<FieldAndMatchInfo> match; - base::span<const MatchPatternRef> email_patterns = GetMatchPatterns( - "EMAIL_ADDRESS", context.page_language, context.pattern_file); - if (ParseField(context, scanner, email_patterns, &match, "EMAIL_ADDRESS")) { + if (ParseField(context, scanner, "EMAIL_ADDRESS", &match)) { return std::make_unique<EmailFieldParser>(std::move(*match)); }
diff --git a/components/autofill/core/browser/form_parsing/iban_field_parser.cc b/components/autofill/core/browser/form_parsing/iban_field_parser.cc index 096165f..0429dbf 100644 --- a/components/autofill/core/browser/form_parsing/iban_field_parser.cc +++ b/components/autofill/core/browser/form_parsing/iban_field_parser.cc
@@ -16,9 +16,7 @@ ParsingContext& context, AutofillScanner* scanner) { std::optional<FieldAndMatchInfo> match; - base::span<const MatchPatternRef> iban_patterns = - GetMatchPatterns(IBAN_VALUE, context.page_language, context.pattern_file); - if (ParseField(context, scanner, iban_patterns, &match, "IBAN_VALUE")) { + if (ParseField(context, scanner, "IBAN_VALUE", &match)) { return std::make_unique<IbanFieldParser>(std::move(*match)); } return nullptr;
diff --git a/components/autofill/core/browser/form_parsing/merchant_promo_code_field_parser.cc b/components/autofill/core/browser/form_parsing/merchant_promo_code_field_parser.cc index 1e9f0a58..fd9a256c 100644 --- a/components/autofill/core/browser/form_parsing/merchant_promo_code_field_parser.cc +++ b/components/autofill/core/browser/form_parsing/merchant_promo_code_field_parser.cc
@@ -16,11 +16,7 @@ ParsingContext& context, AutofillScanner* scanner) { std::optional<FieldAndMatchInfo> match; - base::span<const MatchPatternRef> merchant_promo_code_patterns = - GetMatchPatterns("MERCHANT_PROMO_CODE", context.page_language, - context.pattern_file); - if (ParseField(context, scanner, merchant_promo_code_patterns, &match, - "MERCHANT_PROMO_CODE")) { + if (ParseField(context, scanner, "MERCHANT_PROMO_CODE", &match)) { return std::make_unique<MerchantPromoCodeFieldParser>(std::move(*match)); } return nullptr;
diff --git a/components/autofill/core/browser/form_parsing/phone_field_parser.cc b/components/autofill/core/browser/form_parsing/phone_field_parser.cc index a7a6f26..fe146d7 100644 --- a/components/autofill/core/browser/form_parsing/phone_field_parser.cc +++ b/components/autofill/core/browser/form_parsing/phone_field_parser.cc
@@ -378,16 +378,12 @@ std::optional<FieldAndMatchInfo>* match, const bool is_country_code_field, const std::string& json_field_type) { - base::span<const MatchPatternRef> patterns = GetMatchPatterns( - json_field_type, context.page_language, context.pattern_file); - // Phone country code fields can be discovered via the generic "PHONE" regex // (see e.g. the "Phone: <cc> <ac>:3 - <phone>:3 - <suffix>:4" grammar rule). // However, for phone country code fields, <select> elements should also be // considered. if (is_country_code_field) { - return ParseField(context, scanner, patterns, match, - /*regex_name=*/json_field_type.c_str(), + return ParseField(context, scanner, json_field_type.c_str(), match, [](const MatchParams& p) { return MatchParams(p.attributes, kDefaultMatchParamsWith< @@ -395,9 +391,7 @@ FormControlType::kSelectOne>.field_types); }); } - - return ParseField(context, scanner, patterns, match, - /*regex_name=*/json_field_type.c_str()); + return ParseField(context, scanner, json_field_type.c_str(), match); } } // namespace autofill
diff --git a/components/autofill/core/browser/form_parsing/price_field_parser.cc b/components/autofill/core/browser/form_parsing/price_field_parser.cc index c1e4cc6..621ade3 100644 --- a/components/autofill/core/browser/form_parsing/price_field_parser.cc +++ b/components/autofill/core/browser/form_parsing/price_field_parser.cc
@@ -16,9 +16,7 @@ ParsingContext& context, AutofillScanner* scanner) { std::optional<FieldAndMatchInfo> match; - base::span<const MatchPatternRef> price_patterns = - GetMatchPatterns("PRICE", context.page_language, context.pattern_file); - if (ParseField(context, scanner, price_patterns, &match, "PRICE")) { + if (ParseField(context, scanner, "PRICE", &match)) { return std::make_unique<PriceFieldParser>(std::move(*match)); } return nullptr;
diff --git a/components/autofill/core/browser/form_parsing/search_field_parser.cc b/components/autofill/core/browser/form_parsing/search_field_parser.cc index 30ec766d..ccdceb2 100644 --- a/components/autofill/core/browser/form_parsing/search_field_parser.cc +++ b/components/autofill/core/browser/form_parsing/search_field_parser.cc
@@ -16,9 +16,7 @@ ParsingContext& context, AutofillScanner* scanner) { std::optional<FieldAndMatchInfo> match; - base::span<const MatchPatternRef> patterns = GetMatchPatterns( - SEARCH_TERM, context.page_language, context.pattern_file); - if (ParseField(context, scanner, patterns, &match, "SEARCH_TERM")) { + if (ParseField(context, scanner, "SEARCH_TERM", &match)) { return std::make_unique<SearchFieldParser>(std::move(*match)); } return nullptr;
diff --git a/components/autofill/core/browser/form_parsing/standalone_cvc_field_parser.cc b/components/autofill/core/browser/form_parsing/standalone_cvc_field_parser.cc index 00c8279e..5fe7d25 100644 --- a/components/autofill/core/browser/form_parsing/standalone_cvc_field_parser.cc +++ b/components/autofill/core/browser/form_parsing/standalone_cvc_field_parser.cc
@@ -29,12 +29,7 @@ } std::optional<FieldAndMatchInfo> match; - base::span<const MatchPatternRef> cvc_patterns = - GetMatchPatterns(CREDIT_CARD_VERIFICATION_CODE, context.page_language, - context.pattern_file); - - if (ParseField(context, scanner, cvc_patterns, &match, - "CREDIT_CARD_VERIFICATION_CODE(standalone)")) { + if (ParseField(context, scanner, "CREDIT_CARD_VERIFICATION_CODE", &match)) { return std::make_unique<StandaloneCvcFieldParser>(std::move(*match)); } @@ -50,12 +45,8 @@ return false; } - base::span<const MatchPatternRef> gift_card_patterns = GetMatchPatterns( - "GIFT_CARD", context.page_language, context.pattern_file); - size_t saved_cursor = scanner->SaveCursor(); - const bool gift_card_match = - ParseField(context, scanner, gift_card_patterns, nullptr, "GIFT_CARD"); + const bool gift_card_match = ParseField(context, scanner, "GIFT_CARD"); // MatchGiftCard only wants to test the presence of a gift card but not // consume the field. scanner->RewindTo(saved_cursor);
diff --git a/components/autofill/core/browser/form_parsing/travel_field_parser.cc b/components/autofill/core/browser/form_parsing/travel_field_parser.cc index 690adb26..b61e618 100644 --- a/components/autofill/core/browser/form_parsing/travel_field_parser.cc +++ b/components/autofill/core/browser/form_parsing/travel_field_parser.cc
@@ -13,13 +13,6 @@ namespace autofill { -namespace { -base::span<const MatchPatternRef> GetMatchPatterns(std::string_view name, - ParsingContext& context) { - return GetMatchPatterns(name, context.page_language, context.pattern_file); -} -} // namespace - TravelFieldParser::TravelFieldParser() = default; TravelFieldParser::~TravelFieldParser() = default; @@ -31,24 +24,12 @@ return nullptr; } - base::span<const MatchPatternRef> passport_patterns = - GetMatchPatterns("PASSPORT", context); - base::span<const MatchPatternRef> travel_origin_patterns = - GetMatchPatterns("TRAVEL_ORIGIN", context); - base::span<const MatchPatternRef> travel_destination_patterns = - GetMatchPatterns("TRAVEL_DESTINATION", context); - base::span<const MatchPatternRef> flight_patterns = - GetMatchPatterns("FLIGHT", context); - auto travel_field = std::make_unique<TravelFieldParser>(); - if (ParseField(context, scanner, passport_patterns, &travel_field->passport_, - "PASSPORT") || - ParseField(context, scanner, travel_origin_patterns, - &travel_field->origin_, "TRAVEL_ORIGIN") || - ParseField(context, scanner, travel_destination_patterns, - &travel_field->destination_, "TRAVEL_DESTINATION") || - ParseField(context, scanner, flight_patterns, &travel_field->flight_, - "FLIGHT")) { + if (ParseField(context, scanner, "PASSPORT", &travel_field->passport_) || + ParseField(context, scanner, "TRAVEL_ORIGIN", &travel_field->origin_) || + ParseField(context, scanner, "TRAVEL_DESTINATION", + &travel_field->destination_) || + ParseField(context, scanner, "FLIGHT", &travel_field->flight_)) { // If any regex matches, then we found a travel field. return std::move(travel_field); }
diff --git a/components/autofill/core/browser/payments/bnpl_manager.cc b/components/autofill/core/browser/payments/bnpl_manager.cc index cec01c8..57a93b9a 100644 --- a/components/autofill/core/browser/payments/bnpl_manager.cc +++ b/components/autofill/core/browser/payments/bnpl_manager.cc
@@ -18,11 +18,27 @@ namespace autofill::payments { +BnplManager::OngoingFlowState::OngoingFlowState() = default; + +BnplManager::OngoingFlowState::~OngoingFlowState() = default; + BnplManager::BnplManager(PaymentsAutofillClient* payments_autofill_client) : payments_autofill_client_(CHECK_DEREF(payments_autofill_client)) {} BnplManager::~BnplManager() = default; +void BnplManager::InitBnplFlow( + uint64_t final_checkout_amount, + OnBnplVcnFetchedCallback on_bnpl_vcn_fetched_callback) { + ongoing_flow_state_ = std::make_unique<OngoingFlowState>(); + + ongoing_flow_state_->final_checkout_amount = final_checkout_amount; + ongoing_flow_state_->on_bnpl_vcn_fetched_callback = + std::move(on_bnpl_vcn_fetched_callback); + + // TODO(crbug.com/356443046): Add integration for the BNPL dialogs. +} + std::optional<uint64_t> BnplManager::MaybeParseAmountToMonetaryMicroUnits( const std::string& amount) { const RE2 re( @@ -57,11 +73,12 @@ void BnplManager::FetchVcnDetails() { GetBnplPaymentInstrumentForFetchingVcnRequestDetails request_details; - request_details.billing_customer_number = billing_customer_number_; - request_details.risk_data = risk_data_; - request_details.instrument_id = instrument_id_; - request_details.context_token = context_token_; - request_details.redirect_url = redirect_url_; + request_details.billing_customer_number = + ongoing_flow_state_->billing_customer_number; + request_details.risk_data = ongoing_flow_state_->risk_data; + request_details.instrument_id = ongoing_flow_state_->instrument_id; + request_details.context_token = ongoing_flow_state_->context_token; + request_details.redirect_url = ongoing_flow_state_->redirect_url; payments_autofill_client_->GetPaymentsNetworkInterface() ->GetBnplPaymentInstrumentForFetchingVcn( @@ -75,6 +92,8 @@ const BnplFetchVcnResponseDetails& response_details) { // TODO(crbug.com/378518604): Implement OnVcnDetailsFetched() to fill the form // from the VCN details that were fetched. + + ongoing_flow_state_.reset(); } } // namespace autofill::payments
diff --git a/components/autofill/core/browser/payments/bnpl_manager.h b/components/autofill/core/browser/payments/bnpl_manager.h index 73166c7f..ff8901f 100644 --- a/components/autofill/core/browser/payments/bnpl_manager.h +++ b/components/autofill/core/browser/payments/bnpl_manager.h
@@ -22,11 +22,23 @@ // transaction. class BnplManager { public: + using OnBnplVcnFetchedCallback = base::OnceCallback<void(const CreditCard&)>; + explicit BnplManager(PaymentsAutofillClient* payments_autofill_client); BnplManager(const BnplManager& other) = delete; BnplManager& operator=(const BnplManager& other) = delete; ~BnplManager(); + // Initializes the BNPL flow, which includes UI shown to the user to select an + // issuer, a possible ToS dialog, and redirecting to the selected issuer's + // website before filling the form, if the flow succeeds. + // `final_checkout_amount` is the checkout amount extracted from the page (in + // micros). `on_bnpl_vcn_fetched_callback` is the callback that should be run + // if the flow is completed successfully, to fill the form with the VCN that + // will facilitate the BNPL transaction. + void InitBnplFlow(uint64_t final_checkout_amount, + OnBnplVcnFetchedCallback on_bnpl_vcn_fetched_callback); + // This function attempts to convert a string representation of a monetary // value in dollars into a uint64_t by parsing it as a double and multiplying // the result by 1,000,000. It assumes the input uses a decimal point ('.') as @@ -38,6 +50,43 @@ std::optional<uint64_t> MaybeParseAmountToMonetaryMicroUnits( const std::string& amount); + private: + friend class BnplManagerTestApi; + + // A collection of information that represents the state of an ongoing BNPL + // flow. + struct OngoingFlowState { + OngoingFlowState(); + OngoingFlowState(const OngoingFlowState&) = delete; + OngoingFlowState& operator=(const OngoingFlowState&) = delete; + ~OngoingFlowState(); + + // Billing customer number for the user's Google Payments account. + std::string billing_customer_number; + + // Risk data contains the fingerprint data for the user and the device. + std::string risk_data; + + // BNPL Issuer Data - Populated when user selects a BNPL issuer + // Instrument ID used by the server to identify a specific BNPL issuer. This + // is selected by the user. + std::string instrument_id; + + // Context token shared between client and Payments server. + std::string context_token; + + // URL that the the partner redirected the user to after finishing the BNPL + // flow on the partner website. + GURL redirect_url; + + // The final checkout amount on the page (in micros), used for the ongoing + // BNPL flow. + uint64_t final_checkout_amount; + + // The callback that will fill the fetched BNPL VCN into the form. + OnBnplVcnFetchedCallback on_bnpl_vcn_fetched_callback; + }; + // This function makes the appropriate call to the payments server to fetch // the VCN details for the BNPL issuer selected in the BNPL manager. void FetchVcnDetails(); @@ -47,26 +96,12 @@ void OnVcnDetailsFetched(PaymentsAutofillClient::PaymentsRpcResult result, const BnplFetchVcnResponseDetails& response_details); - private: - friend class BnplManagerTest; - // The associated payments autofill client. const raw_ref<PaymentsAutofillClient> payments_autofill_client_; - // Billing customer number for the user's Google Payments account. - std::string billing_customer_number_; - // Risk data contains the fingerprint data for the user and the device. - std::string risk_data_; - - // BNPL Issuer Data - Populated when user selects a BNPL issuer - // Instrument ID used by the server to identify a specific BNPL issuer. This - // is selected by the user. - std::string instrument_id_; - // Context token shared between client and Payments server. - std::string context_token_; - // URL that the the partner redirected the user to after finishing the BNPL - // flow on the partner website. - GURL redirect_url_; + // The state for the ongoing flow. Only present if there is a flow currently + // ongoing. Set when a flow is initiated, and reset upon flow completion. + std::unique_ptr<OngoingFlowState> ongoing_flow_state_; base::WeakPtrFactory<BnplManager> weak_factory_{this}; };
diff --git a/components/autofill/core/browser/payments/bnpl_manager_test_api.h b/components/autofill/core/browser/payments/bnpl_manager_test_api.h new file mode 100644 index 0000000..cc6dd9f --- /dev/null +++ b/components/autofill/core/browser/payments/bnpl_manager_test_api.h
@@ -0,0 +1,61 @@ +// Copyright 2025 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_AUTOFILL_CORE_BROWSER_PAYMENTS_BNPL_MANAGER_TEST_API_H_ +#define COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_BNPL_MANAGER_TEST_API_H_ + +#include "base/check_deref.h" +#include "components/autofill/core/browser/payments/bnpl_manager.h" + +namespace autofill::payments { + +class BnplManagerTestApi { + public: + explicit BnplManagerTestApi(BnplManager* bnpl_manager) + : bnpl_manager_(CHECK_DEREF(bnpl_manager)) {} + BnplManagerTestApi(const BnplManagerTestApi&) = delete; + BnplManagerTestApi& operator=(const BnplManagerTestApi&) = delete; + ~BnplManagerTestApi() = default; + + void PopulateManagerWithUserAndBnplIssuerDetails( + std::string billing_customer_number, + std::string risk_data, + std::string instrument_id, + std::string context_token, + GURL redirect_url) { + bnpl_manager_->ongoing_flow_state_ = + std::make_unique<BnplManager::OngoingFlowState>(); + bnpl_manager_->ongoing_flow_state_->billing_customer_number = + std::move(billing_customer_number); + bnpl_manager_->ongoing_flow_state_->risk_data = std::move(risk_data); + bnpl_manager_->ongoing_flow_state_->instrument_id = + std::move(instrument_id); + bnpl_manager_->ongoing_flow_state_->context_token = + std::move(context_token); + bnpl_manager_->ongoing_flow_state_->redirect_url = std::move(redirect_url); + } + + void FetchVcnDetails() { bnpl_manager_->FetchVcnDetails(); } + + void OnVcnDetailsFetched( + PaymentsAutofillClient::PaymentsRpcResult result, + const BnplFetchVcnResponseDetails& response_details) { + bnpl_manager_->OnVcnDetailsFetched(result, response_details); + } + + BnplManager::OngoingFlowState* GetOngoingFlowState() { + return bnpl_manager_->ongoing_flow_state_.get(); + } + + private: + const raw_ref<BnplManager> bnpl_manager_; +}; + +inline BnplManagerTestApi test_api(BnplManager& manager) { + return BnplManagerTestApi(&manager); +} + +} // namespace autofill::payments + +#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_BNPL_MANAGER_TEST_API_H_
diff --git a/components/autofill/core/browser/payments/bnpl_manager_unittest.cc b/components/autofill/core/browser/payments/bnpl_manager_unittest.cc index eb784b23..86b57ee 100644 --- a/components/autofill/core/browser/payments/bnpl_manager_unittest.cc +++ b/components/autofill/core/browser/payments/bnpl_manager_unittest.cc
@@ -6,6 +6,7 @@ #include "base/test/task_environment.h" #include "components/autofill/core/browser/foundations/test_autofill_client.h" +#include "components/autofill/core/browser/payments/bnpl_manager_test_api.h" #include "components/autofill/core/browser/payments/payments_autofill_client.h" #include "components/autofill/core/browser/payments/payments_network_interface.h" #include "components/autofill/core/browser/payments/payments_request_details.h" @@ -55,14 +56,6 @@ autofill_client_->GetPaymentsAutofillClient()); } - void PopulateManagerWithUserAndBnplIssuerDetails() { - bnpl_manager_->billing_customer_number_ = kBillingCustomerNumber; - bnpl_manager_->risk_data_ = kRiskData; - bnpl_manager_->instrument_id_ = kInstrumentId; - bnpl_manager_->context_token_ = kContextToken; - bnpl_manager_->redirect_url_ = kRedirectUrl; - } - protected: base::test::TaskEnvironment task_environment_; std::unique_ptr<TestAutofillClient> autofill_client_; @@ -179,10 +172,29 @@ std::nullopt); } +// Tests that the initial state for a BNPL flow is set when +// BnplManager::InitBnplFlow() is triggered. +TEST_F(BnplManagerTest, InitBnplFlow_SetsInitialState) { + uint64_t final_checkout_amount = 1000000; + bnpl_manager_->InitBnplFlow(final_checkout_amount, base::DoNothing()); + + EXPECT_EQ( + final_checkout_amount, + test_api(*bnpl_manager_).GetOngoingFlowState()->final_checkout_amount); + EXPECT_FALSE(test_api(*bnpl_manager_) + .GetOngoingFlowState() + ->on_bnpl_vcn_fetched_callback.is_null()); +} + // Tests that FetchVcnDetails calls the payments network interface with the -// request details filled out correctly. +// request details filled out correctly, and once the VCN is filled the state of +// BnplManager is reset. TEST_F(BnplManagerTest, FetchVcnDetails_CallsGetBnplPaymentInstrument) { - PopulateManagerWithUserAndBnplIssuerDetails(); + bnpl_manager_->InitBnplFlow(1000000, base::DoNothing()); + test_api(*bnpl_manager_) + .PopulateManagerWithUserAndBnplIssuerDetails(kBillingCustomerNumber, + kRiskData, kInstrumentId, + kContextToken, kRedirectUrl); EXPECT_CALL(*payments_network_interface_, GetBnplPaymentInstrumentForFetchingVcn( @@ -191,7 +203,14 @@ kContextToken, kRedirectUrl), /*callback=*/_)); - bnpl_manager_->FetchVcnDetails(); + EXPECT_NE(test_api(*bnpl_manager_).GetOngoingFlowState(), nullptr); + + test_api(*bnpl_manager_).FetchVcnDetails(); + test_api(*bnpl_manager_) + .OnVcnDetailsFetched(PaymentsAutofillClient::PaymentsRpcResult::kSuccess, + BnplFetchVcnResponseDetails()); + + EXPECT_EQ(test_api(*bnpl_manager_).GetOngoingFlowState(), nullptr); } } // namespace autofill::payments
diff --git a/components/collaboration/internal/collaboration_controller.cc b/components/collaboration/internal/collaboration_controller.cc index c9cf4c0b..120b26d 100644 --- a/components/collaboration/internal/collaboration_controller.cc +++ b/components/collaboration/internal/collaboration_controller.cc
@@ -4,9 +4,11 @@ #include "components/collaboration/internal/collaboration_controller.h" +#include "base/functional/bind.h" #include "base/logging.h" #include "base/scoped_observation.h" #include "base/task/single_thread_task_runner.h" +#include "components/collaboration/internal/metrics.h" #include "components/collaboration/public/collaboration_service.h" #include "components/saved_tab_groups/public/saved_tab_group.h" #include "components/saved_tab_groups/public/tab_group_sync_service.h" @@ -53,6 +55,8 @@ } // namespace // This is base class for each state and handles the logic for the state. +// TODO(crbug.com/389953812): Consider consolidating metric recording into the +// base class. Provide a utility function to handle state specific metrics. class ControllerState { public: ControllerState(StateId id, CollaborationController* controller) @@ -140,6 +144,11 @@ ServiceStatus status = controller->collaboration_service()->GetServiceStatus(); if (!status.IsAuthenticationValid()) { + if (Flow::Type::kJoin == controller->flow().type) { + collaboration::metrics::RecordJoinEvent( + metrics::CollaborationServiceJoinEvent::kNotSignedIn); + } + controller->TransitionTo(StateId::kAuthenticating); return; } @@ -159,9 +168,22 @@ : ControllerState(id, controller) {} void OnEnter(const ErrorInfo& error) override { - controller->delegate()->ShowAuthenticationUi(base::BindOnce( - &AuthenticatingState::ProcessOutcome, weak_ptr_factory_.GetWeakPtr())); + controller->delegate()->ShowAuthenticationUi( + base::BindOnce(&AuthenticatingState::ProcessOutcome, + local_weak_ptr_factory_.GetWeakPtr())); } + + void ProcessOutcome(Outcome outcome) override { + if (Outcome::kCancel == outcome) { + if (Flow::Type::kJoin == controller->flow().type) { + collaboration::metrics::RecordJoinEvent( + metrics::CollaborationServiceJoinEvent::kCanceledNotSignedIn); + } + } + + ControllerState::ProcessOutcome(outcome); + } + void OnProcessingFinishedWithSuccess() override { ServiceStatus status = controller->collaboration_service()->GetServiceStatus(); @@ -193,6 +215,8 @@ private: base::ScopedObservation<CollaborationService, CollaborationService::Observer> collaboration_service_observer_{this}; + + base::WeakPtrFactory<AuthenticatingState> local_weak_ptr_factory_{this}; }; class CheckingFlowRequirementsState : public ControllerState { @@ -280,6 +304,18 @@ local_weak_ptr_factory_.GetWeakPtr())); } + void ProcessOutcome(Outcome outcome) override { + if (Outcome::kCancel == outcome) { + CHECK_EQ(controller->flow().type, Flow::Type::kJoin) + << "Only the join flow can transition into the AddingUserToGroup " + "state."; + collaboration::metrics::RecordJoinEvent( + metrics::CollaborationServiceJoinEvent::kCanceled); + } + + ControllerState::ProcessOutcome(outcome); + } + void OnProcessingFinishedWithSuccess() override { const data_sharing::GroupId group_id = controller->flow().join_token().group_id; @@ -302,7 +338,7 @@ controller->delegate()->ShowJoinDialog( controller->flow().join_token(), preview_outcome.value(), base::BindOnce(&AddingUserToGroupState::ProcessOutcome, - weak_ptr_factory_.GetWeakPtr())); + local_weak_ptr_factory_.GetWeakPtr())); } base::WeakPtrFactory<AddingUserToGroupState> local_weak_ptr_factory_{this};
diff --git a/components/collaboration/internal/collaboration_controller_unittest.cc b/components/collaboration/internal/collaboration_controller_unittest.cc index eaa9866..a3f1d8cf 100644 --- a/components/collaboration/internal/collaboration_controller_unittest.cc +++ b/components/collaboration/internal/collaboration_controller_unittest.cc
@@ -4,14 +4,18 @@ #include "components/collaboration/internal/collaboration_controller.h" +#include "base/functional/callback_forward.h" #include "base/run_loop.h" #include "base/test/gmock_callback_support.h" #include "base/test/gmock_move_support.h" +#include "base/test/metrics/histogram_tester.h" #include "base/test/mock_callback.h" #include "base/test/task_environment.h" +#include "components/collaboration/internal/metrics.h" #include "components/collaboration/public/collaboration_controller_delegate.h" #include "components/collaboration/test_support/mock_collaboration_controller_delegate.h" #include "components/collaboration/test_support/mock_collaboration_service.h" +#include "components/data_sharing/public/group_data.h" #include "components/data_sharing/test_support/mock_data_sharing_service.h" #include "components/saved_tab_groups/public/saved_tab_group.h" #include "components/saved_tab_groups/test_support/mock_tab_group_sync_service.h" @@ -287,6 +291,82 @@ EXPECT_EQ(controller_->GetStateForTesting(), StateId::kError); } +TEST_F(CollaborationControllerTest, AuthenticationCanceledBeforeSignIn) { + base::HistogramTester histogram_tester; + + RunLoop run_loop; + + // Start Join flow at pending state. + InitializeJoinController(run_loop.QuitClosure()); + EXPECT_EQ(controller_->GetStateForTesting(), StateId::kPending); + + // Simulate user is not signed in or syncing. + ServiceStatus status; + status.signin_status = SigninStatus::kNotSignedIn; + status.sync_status = SyncStatus::kNotSyncing; + ASSERT_FALSE(status.IsAuthenticationValid()); + EXPECT_CALL(*collaboration_service_, GetServiceStatus()) + .WillOnce(Return(status)); + + // The user should be shown authentication screens. + base::OnceCallback<void(Outcome)> authentication_ui_calback; + EXPECT_CALL(*delegate_, ShowAuthenticationUi(IsNotNullCallback())) + .WillOnce(MoveArg<0>(&authentication_ui_calback)); + + // Pending -> Authenticating. + std::move(prepare_ui_callback_).Run(Outcome::kSuccess); + + // Authenticating -> Cancel state. + EXPECT_CALL(*delegate_, OnFlowFinished); + std::move(authentication_ui_calback).Run(Outcome::kCancel); + + run_loop.Run(); + + // Verify the not signed in metrics are recorded properly. + histogram_tester.ExpectBucketCount( + "CollaborationService.JoinFlow", + metrics::CollaborationServiceJoinEvent::kNotSignedIn, 1); + histogram_tester.ExpectBucketCount( + "CollaborationService.JoinFlow", + metrics::CollaborationServiceJoinEvent::kCanceledNotSignedIn, 1); +} + +TEST_F(CollaborationControllerTest, AuthenticationCanceledAfterSignIn) { + base::HistogramTester histogram_tester; + + RunLoop run_loop; + + // Start Join flow. + InitializeJoinController(run_loop.QuitClosure()); + + // Simulate getting to the Adding User To Group state. + base::OnceCallback<void(Outcome)> join_ui_callback; + base::OnceCallback<void(const data_sharing::DataSharingService:: + SharedDataPreviewOrFailureOutcome&)> + preview_callback; + EXPECT_CALL(*data_sharing_service_, + GetSharedEntitiesPreview( + GroupToken(data_sharing::GroupId(kGroupId), kAccessToken), + IsNotNullCallback())) + .WillOnce(MoveArg<1>(&preview_callback)); + EXPECT_CALL(*delegate_, ShowJoinDialog(_, _, IsNotNullCallback())) + .WillOnce(MoveArg<2>(&join_ui_callback)); + controller_->SetStateForTesting(StateId::kAddingUserToGroup); + + // Show group preview screen. + std::move(preview_callback).Run(data_sharing::SharedDataPreview()); + + // Cancel the join flow. + EXPECT_CALL(*delegate_, OnFlowFinished); + std::move(join_ui_callback).Run(Outcome::kCancel); + + run_loop.Run(); + + histogram_tester.ExpectBucketCount( + "CollaborationService.JoinFlow", + metrics::CollaborationServiceJoinEvent::kCanceled, 1); +} + TEST_F(CollaborationControllerTest, AuthenticationError) { RunLoop run_loop; // Start Join flow with authenticating screens.
diff --git a/components/collaboration/internal/metrics.h b/components/collaboration/internal/metrics.h index 56994d45..7628347 100644 --- a/components/collaboration/internal/metrics.h +++ b/components/collaboration/internal/metrics.h
@@ -14,7 +14,10 @@ enum class CollaborationServiceJoinEvent { kUnknown = 0, kStarted = 1, - kMaxValue = kStarted + kCanceled = 2, + kCanceledNotSignedIn = 3, + kNotSignedIn = 4, + kMaxValue = kNotSignedIn }; // LINT.ThenChange(//tools/metrics/histograms/metadata/collaboration_service/enums.xml:CollaborationServiceJoinEvent)
diff --git a/components/cronet/android/cronet_combined_impl_native_proguard_golden.cfg b/components/cronet/android/cronet_combined_impl_native_proguard_golden.cfg index 74f36dc..2e16579 100644 --- a/components/cronet/android/cronet_combined_impl_native_proguard_golden.cfg +++ b/components/cronet/android/cronet_combined_impl_native_proguard_golden.cfg
@@ -98,16 +98,16 @@ # Use assumevalues in addition to assumenosideeffects block because Google3 proguard cannot parse # assumenosideeffects blocks which overwrite return value. -assumevalues class ** { - @org.chromium.build.annotations.AssumeNonNull *** *(...) return _NONNULL_; + @org.chromium.build.annotations.OptimizeAsNonNull *** *(...) return _NONNULL_; } -assumenosideeffects class ** { - @org.chromium.build.annotations.AssumeNonNull *** *(...); + @org.chromium.build.annotations.OptimizeAsNonNull *** *(...); } -assumevalues class ** { - @org.chromium.build.annotations.AssumeNonNull *** * return _NONNULL_; + @org.chromium.build.annotations.OptimizeAsNonNull *** * return _NONNULL_; } -assumenosideeffects class ** { - @org.chromium.build.annotations.AssumeNonNull *** *; + @org.chromium.build.annotations.OptimizeAsNonNull *** *; } # -------- Config Path: components/cronet/android/cronet_impl_common_proguard.cfg -------- # Proguard config for apps that depend on cronet_impl_common_java.jar.
diff --git a/components/data_sharing/public/android/java/src/org/chromium/components/data_sharing/configs/DataSharingCreateUiConfig.java b/components/data_sharing/public/android/java/src/org/chromium/components/data_sharing/configs/DataSharingCreateUiConfig.java index 2a00a84..3d3077d1 100644 --- a/components/data_sharing/public/android/java/src/org/chromium/components/data_sharing/configs/DataSharingCreateUiConfig.java +++ b/components/data_sharing/public/android/java/src/org/chromium/components/data_sharing/configs/DataSharingCreateUiConfig.java
@@ -28,6 +28,10 @@ default void onCancelClicked() {} default void getDataSharingUrl(GroupToken tokenSecret, Callback<String> url) {} + + // This will always be called when user creates the group, ui closes, or + // session is finished. + default void onSessionFinished() {} } private DataSharingCreateUiConfig(Builder builder) {
diff --git a/components/data_sharing/public/android/java/src/org/chromium/components/data_sharing/configs/DataSharingJoinUiConfig.java b/components/data_sharing/public/android/java/src/org/chromium/components/data_sharing/configs/DataSharingJoinUiConfig.java index 1232fd68..ddc89dc 100644 --- a/components/data_sharing/public/android/java/src/org/chromium/components/data_sharing/configs/DataSharingJoinUiConfig.java +++ b/components/data_sharing/public/android/java/src/org/chromium/components/data_sharing/configs/DataSharingJoinUiConfig.java
@@ -30,11 +30,15 @@ // DEPRECATED: use the version with callback, to close the loading UI. default void onGroupJoined(GroupData groupData) {} - // Called when group is joined, the `onJoinFinished` should be called when any processing is - // done. + // Called when group is joined, the `onSessionFinished` should be called + // when any processing is done. default void onGroupJoinedWithWait(GroupData groupData, Callback<Boolean> onJoinFinished) {} default void onPreviewTabGroupDetailsClicked(String groupId) {} + + // This will always be called when user joins the group, ui closes, or + // session is finished. + default void onSessionFinished() {} } private DataSharingJoinUiConfig(Builder builder) {
diff --git a/components/data_sharing/public/android/java/src/org/chromium/components/data_sharing/configs/DataSharingManageUiConfig.java b/components/data_sharing/public/android/java/src/org/chromium/components/data_sharing/configs/DataSharingManageUiConfig.java index 4a22102c6..0bcce49 100644 --- a/components/data_sharing/public/android/java/src/org/chromium/components/data_sharing/configs/DataSharingManageUiConfig.java +++ b/components/data_sharing/public/android/java/src/org/chromium/components/data_sharing/configs/DataSharingManageUiConfig.java
@@ -46,6 +46,10 @@ default void onLeaveGroup() {} default void getDataSharingUrl(GroupToken groupToken, Callback<String> url) {} + + // This will always be called when user exits the managing the group, + // ui closes, or session is finished. + default void onSessionFinished() {} } private DataSharingManageUiConfig(Builder builder) {
diff --git a/components/facilitated_payments/content/browser/content_facilitated_payments_driver.cc b/components/facilitated_payments/content/browser/content_facilitated_payments_driver.cc index 7daf248..00b08908 100644 --- a/components/facilitated_payments/content/browser/content_facilitated_payments_driver.cc +++ b/components/facilitated_payments/content/browser/content_facilitated_payments_driver.cc
@@ -11,7 +11,7 @@ #include "components/facilitated_payments/content/browser/security_checker.h" #include "components/facilitated_payments/core/browser/ewallet_manager.h" #include "components/facilitated_payments/core/browser/facilitated_payments_api_client.h" -#include "components/facilitated_payments/core/browser/facilitated_payments_manager.h" +#include "components/facilitated_payments/core/browser/pix_manager.h" #include "content/public/browser/render_frame_host.h" #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" @@ -22,16 +22,16 @@ optimization_guide::OptimizationGuideDecider* optimization_guide_decider, content::RenderFrameHost* render_frame_host, std::unique_ptr<SecurityChecker> security_checker) - : FacilitatedPaymentsDriver(std::make_unique<FacilitatedPaymentsManager>( - client, - GetFacilitatedPaymentsApiClientCreator( - render_frame_host->GetGlobalId()), - optimization_guide_decider), - std::make_unique<EwalletManager>( - client, - GetFacilitatedPaymentsApiClientCreator( - render_frame_host->GetGlobalId()), - optimization_guide_decider)), + : FacilitatedPaymentsDriver( + std::make_unique<PixManager>(client, + GetFacilitatedPaymentsApiClientCreator( + render_frame_host->GetGlobalId()), + optimization_guide_decider), + std::make_unique<EwalletManager>( + client, + GetFacilitatedPaymentsApiClientCreator( + render_frame_host->GetGlobalId()), + optimization_guide_decider)), render_frame_host_id_(render_frame_host->GetGlobalId()), security_checker_(std::move(security_checker)) {}
diff --git a/components/facilitated_payments/content/browser/content_facilitated_payments_driver_unittest.cc b/components/facilitated_payments/content/browser/content_facilitated_payments_driver_unittest.cc index 14461b2..6ba9353 100644 --- a/components/facilitated_payments/content/browser/content_facilitated_payments_driver_unittest.cc +++ b/components/facilitated_payments/content/browser/content_facilitated_payments_driver_unittest.cc
@@ -12,7 +12,7 @@ #include "components/facilitated_payments/content/browser/security_checker.h" #include "components/facilitated_payments/core/browser/ewallet_manager.h" #include "components/facilitated_payments/core/browser/facilitated_payments_client.h" -#include "components/facilitated_payments/core/browser/facilitated_payments_manager.h" +#include "components/facilitated_payments/core/browser/pix_manager.h" #include "components/optimization_guide/core/test_optimization_guide_decider.h" #include "content/public/browser/web_contents.h" #include "content/public/test/test_renderer_host.h" @@ -47,16 +47,16 @@ MOCK_METHOD(bool, IsInLandscapeMode, (), (override)); }; -class MockFacilitatedPaymentsManager : public FacilitatedPaymentsManager { +class MockPixManager : public PixManager { public: - MockFacilitatedPaymentsManager( + MockPixManager( FacilitatedPaymentsClient* client, FacilitatedPaymentsApiClientCreator api_client_creator, optimization_guide::OptimizationGuideDecider* optimization_guide_decider) - : FacilitatedPaymentsManager(client, - std::move(api_client_creator), - optimization_guide_decider) {} - ~MockFacilitatedPaymentsManager() override = default; + : PixManager(client, + std::move(api_client_creator), + optimization_guide_decider) {} + ~MockPixManager() override = default; MOCK_METHOD(void, OnPixCodeCopiedToClipboard, @@ -116,17 +116,15 @@ render_frame_host->GetGlobalId()), decider_.get()); ewallet_manager_ = em.get(); - std::unique_ptr<MockFacilitatedPaymentsManager> - facilitated_payments_manager = - std::make_unique<testing::NiceMock<MockFacilitatedPaymentsManager>>( - client_.get(), - GetFacilitatedPaymentsApiClientCreator( - render_frame_host->GetGlobalId()), - decider_.get()); - facilitated_payments_manager_ = facilitated_payments_manager.get(); + std::unique_ptr<MockPixManager> pix_manager = + std::make_unique<testing::NiceMock<MockPixManager>>( + client_.get(), + GetFacilitatedPaymentsApiClientCreator( + render_frame_host->GetGlobalId()), + decider_.get()); + pix_manager_ = pix_manager.get(); - driver_->SetFacilitatedPaymentsManagerForTesting( - std::move(facilitated_payments_manager)); + driver_->SetPixManagerForTesting(std::move(pix_manager)); driver_->SetEwalletManagerForTesting(std::move(em)); } @@ -134,7 +132,7 @@ decider_.reset(); driver_.reset(); security_checker_ = nullptr; - facilitated_payments_manager_ = nullptr; + pix_manager_ = nullptr; ewallet_manager_ = nullptr; content::RenderViewHostTestHarness::TearDown(); } @@ -143,7 +141,7 @@ std::unique_ptr<optimization_guide::TestOptimizationGuideDecider> decider_; std::unique_ptr<FacilitatedPaymentsClient> client_; std::unique_ptr<ContentFacilitatedPaymentsDriver> driver_; - raw_ptr<MockFacilitatedPaymentsManager> facilitated_payments_manager_; + raw_ptr<MockPixManager> pix_manager_; raw_ptr<MockEwalletManager> ewallet_manager_; raw_ptr<MockSecurityChecker> security_checker_; }; @@ -152,7 +150,7 @@ PixIdentifierExists_OnPixCodeCopiedToClipboardTriggered) { GURL url("https://example.com/"); - EXPECT_CALL(*facilitated_payments_manager_, OnPixCodeCopiedToClipboard); + EXPECT_CALL(*pix_manager_, OnPixCodeCopiedToClipboard); // "0014br.gov.bcb.pix" is the Pix identifier. driver_->OnTextCopiedToClipboard( @@ -165,8 +163,7 @@ PixIdentifierAbsent_OnPixCodeCopiedToClipboardNotTriggered) { GURL url("https://example.com/"); - EXPECT_CALL(*facilitated_payments_manager_, OnPixCodeCopiedToClipboard) - .Times(0); + EXPECT_CALL(*pix_manager_, OnPixCodeCopiedToClipboard).Times(0); driver_->OnTextCopiedToClipboard( /*render_frame_host_url=*/url, /*copied_text=*/u"notAValidPixIdentifier",
diff --git a/components/facilitated_payments/core/browser/BUILD.gn b/components/facilitated_payments/core/browser/BUILD.gn index 8ed9ea1..166d8b2 100644 --- a/components/facilitated_payments/core/browser/BUILD.gn +++ b/components/facilitated_payments/core/browser/BUILD.gn
@@ -11,8 +11,6 @@ "facilitated_payments_client.h", "facilitated_payments_driver.cc", "facilitated_payments_driver.h", - "facilitated_payments_manager.cc", - "facilitated_payments_manager.h", "network_api/facilitated_payments_initiate_payment_request.cc", "network_api/facilitated_payments_initiate_payment_request.h", "network_api/facilitated_payments_initiate_payment_request_details.cc", @@ -21,6 +19,8 @@ "network_api/facilitated_payments_initiate_payment_response_details.h", "network_api/facilitated_payments_network_interface.cc", "network_api/facilitated_payments_network_interface.h", + "pix_manager.cc", + "pix_manager.h", ] public_deps = [ @@ -43,10 +43,10 @@ testonly = true sources = [ "ewallet_manager_unittest.cc", - "facilitated_payments_manager_unittest.cc", "network_api/facilitated_payments_initiate_payment_request_details_unittest.cc", "network_api/facilitated_payments_initiate_payment_request_unittest.cc", "network_api/facilitated_payments_network_interface_unittest.cc", + "pix_manager_unittest.cc", ] deps = [
diff --git a/components/facilitated_payments/core/browser/ewallet_manager.h b/components/facilitated_payments/core/browser/ewallet_manager.h index a08b330..531bd54c 100644 --- a/components/facilitated_payments/core/browser/ewallet_manager.h +++ b/components/facilitated_payments/core/browser/ewallet_manager.h
@@ -64,7 +64,7 @@ // Lazily initializes an API client and returns a pointer to it. Returns a // pointer to the existing API client, if one is already initialized. The - // FacilitatedPaymentManager owns this API client. This method can return + // EwalletManager owns this API client. This method can return // `nullptr` if the API client fails to initialize, e.g., if the // `RenderFrameHost` has been destroyed. FacilitatedPaymentsApiClient* GetApiClient();
diff --git a/components/facilitated_payments/core/browser/facilitated_payments_driver.cc b/components/facilitated_payments/core/browser/facilitated_payments_driver.cc index 9a5cf48..5aeb74e 100644 --- a/components/facilitated_payments/core/browser/facilitated_payments_driver.cc +++ b/components/facilitated_payments/core/browser/facilitated_payments_driver.cc
@@ -8,22 +8,22 @@ #include "base/strings/utf_string_conversions.h" #include "components/facilitated_payments/core/browser/ewallet_manager.h" -#include "components/facilitated_payments/core/browser/facilitated_payments_manager.h" +#include "components/facilitated_payments/core/browser/pix_manager.h" #include "components/facilitated_payments/core/features/features.h" #include "components/facilitated_payments/core/validation/pix_code_validator.h" namespace payments::facilitated { FacilitatedPaymentsDriver::FacilitatedPaymentsDriver( - std::unique_ptr<FacilitatedPaymentsManager> manager, + std::unique_ptr<PixManager> pix_manager, std::unique_ptr<EwalletManager> ewallet_manager) - : manager_(std::move(manager)), + : pix_manager_(std::move(pix_manager)), ewallet_manager_(std::move(ewallet_manager)) {} FacilitatedPaymentsDriver::~FacilitatedPaymentsDriver() = default; void FacilitatedPaymentsDriver::DidNavigateToOrAwayFromPage() const { - manager_->Reset(); + pix_manager_->Reset(); ewallet_manager_->Reset(); } @@ -35,7 +35,7 @@ base::UTF16ToUTF8(copied_text))) { return; } - manager_->OnPixCodeCopiedToClipboard( + pix_manager_->OnPixCodeCopiedToClipboard( render_frame_host_url, base::UTF16ToUTF8(copied_text), ukm_source_id); } @@ -46,9 +46,9 @@ ewallet_manager_->TriggerEwalletPushPayment(payment_link_url, page_url); } -void FacilitatedPaymentsDriver::SetFacilitatedPaymentsManagerForTesting( - std::unique_ptr<FacilitatedPaymentsManager> manager) { - manager_ = std::move(manager); +void FacilitatedPaymentsDriver::SetPixManagerForTesting( + std::unique_ptr<PixManager> pix_manager) { + pix_manager_ = std::move(pix_manager); } void FacilitatedPaymentsDriver::SetEwalletManagerForTesting(
diff --git a/components/facilitated_payments/core/browser/facilitated_payments_driver.h b/components/facilitated_payments/core/browser/facilitated_payments_driver.h index a9e36c6..4fc370e 100644 --- a/components/facilitated_payments/core/browser/facilitated_payments_driver.h +++ b/components/facilitated_payments/core/browser/facilitated_payments_driver.h
@@ -15,7 +15,7 @@ namespace payments::facilitated { class EwalletManager; -class FacilitatedPaymentsManager; +class PixManager; // A cross-platform interface which is a gateway for all Facilitated Payments // related communication between the browser and the DOM. There can be one @@ -27,20 +27,20 @@ // to handle common logics shared by cross-platform. class FacilitatedPaymentsDriver { public: - FacilitatedPaymentsDriver(std::unique_ptr<FacilitatedPaymentsManager> manager, + FacilitatedPaymentsDriver(std::unique_ptr<PixManager> pix_manager, std::unique_ptr<EwalletManager> ewallet_manager); FacilitatedPaymentsDriver(const FacilitatedPaymentsDriver&) = delete; FacilitatedPaymentsDriver& operator=(const FacilitatedPaymentsDriver&) = delete; virtual ~FacilitatedPaymentsDriver(); - // Informs `FacilitatedPaymentsManager` that a navigation related event has + // Informs `PixManager` that a navigation related event has // taken place. The navigation could be to the currently displayed page, or // away from the currently displayed page. It is invoked only for the primary // main frame by the platform-specific implementation. void DidNavigateToOrAwayFromPage() const; - // Inform the `FacilitatedPaymentsManager` about `copied_text` being copied to + // Inform the `PixManager` about `copied_text` being copied to // the clipboard. It is invoked only for the primary main frame. virtual void OnTextCopiedToClipboard(const GURL& render_frame_host_url, const std::u16string& copied_text, @@ -52,13 +52,12 @@ virtual void TriggerEwalletPushPayment(const GURL& payment_link_url, const GURL& page_url); - virtual void SetFacilitatedPaymentsManagerForTesting( - std::unique_ptr<FacilitatedPaymentsManager> manager); + virtual void SetPixManagerForTesting(std::unique_ptr<PixManager> pix_manager); virtual void SetEwalletManagerForTesting( std::unique_ptr<EwalletManager> ewallet_manager); private: - std::unique_ptr<FacilitatedPaymentsManager> manager_; + std::unique_ptr<PixManager> pix_manager_; std::unique_ptr<EwalletManager> ewallet_manager_; };
diff --git a/components/facilitated_payments/core/browser/network_api/facilitated_payments_initiate_payment_request.h b/components/facilitated_payments/core/browser/network_api/facilitated_payments_initiate_payment_request.h index f06a5352..cde5d4c 100644 --- a/components/facilitated_payments/core/browser/network_api/facilitated_payments_initiate_payment_request.h +++ b/components/facilitated_payments/core/browser/network_api/facilitated_payments_initiate_payment_request.h
@@ -19,7 +19,7 @@ // This class is used for making a payment request to the Payments server. It is // used by all FOPs under Facilitated Payments. It encapsulates the info // required for making the server call, and pipes the server response back to -// the `FacilitatedPaymentsManager` through a callback. +// the payment manager through a callback. class FacilitatedPaymentsInitiatePaymentRequest : public autofill::payments::PaymentsRequest { public:
diff --git a/components/facilitated_payments/core/browser/facilitated_payments_manager.cc b/components/facilitated_payments/core/browser/pix_manager.cc similarity index 80% rename from components/facilitated_payments/core/browser/facilitated_payments_manager.cc rename to components/facilitated_payments/core/browser/pix_manager.cc index 3e9b9cdc..f91d133 100644 --- a/components/facilitated_payments/core/browser/facilitated_payments_manager.cc +++ b/components/facilitated_payments/core/browser/pix_manager.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/facilitated_payments/core/browser/facilitated_payments_manager.h" +#include "components/facilitated_payments/core/browser/pix_manager.h" #include <algorithm> #include <utility> @@ -30,7 +30,7 @@ } // namespace -FacilitatedPaymentsManager::FacilitatedPaymentsManager( +PixManager::PixManager( FacilitatedPaymentsClient* client, FacilitatedPaymentsApiClientCreator api_client_creator, optimization_guide::OptimizationGuideDecider* optimization_guide_decider) @@ -44,11 +44,11 @@ RegisterPixAllowlist(); } -FacilitatedPaymentsManager::~FacilitatedPaymentsManager() { +PixManager::~PixManager() { DismissPrompt(); } -void FacilitatedPaymentsManager::Reset() { +void PixManager::Reset() { has_payflow_started_ = false; ukm_source_id_ = 0; initiate_payment_request_details_ = @@ -57,16 +57,15 @@ weak_ptr_factory_.InvalidateWeakPtrs(); } -void FacilitatedPaymentsManager::OnPixCodeCopiedToClipboard( - const GURL& render_frame_host_url, - const std::string& pix_code, - ukm::SourceId ukm_source_id) { +void PixManager::OnPixCodeCopiedToClipboard(const GURL& render_frame_host_url, + const std::string& pix_code, + ukm::SourceId ukm_source_id) { if (has_payflow_started_) { return; } has_payflow_started_ = true; client_->SetUiEventListener(base::BindRepeating( - &FacilitatedPaymentsManager::OnUiEvent, weak_ptr_factory_.GetWeakPtr())); + &PixManager::OnUiEvent, weak_ptr_factory_.GetWeakPtr())); pix_code_copied_timestamp_ = base::TimeTicks::Now(); ukm_source_id_ = ukm_source_id; // Check whether the domain for the render_frame_host_url is allowlisted. @@ -79,17 +78,17 @@ render_frame_host_url.host(); // Trigger Pix code validation. utility_process_validator_.ValidatePixCode( - pix_code, base::BindOnce(&FacilitatedPaymentsManager::OnPixCodeValidated, + pix_code, base::BindOnce(&PixManager::OnPixCodeValidated, weak_ptr_factory_.GetWeakPtr(), pix_code, base::TimeTicks::Now())); } -void FacilitatedPaymentsManager::RegisterPixAllowlist() const { +void PixManager::RegisterPixAllowlist() const { optimization_guide_decider_->RegisterOptimizationTypes( {optimization_guide::proto::PIX_MERCHANT_ORIGINS_ALLOWLIST}); } -bool FacilitatedPaymentsManager::IsMerchantAllowlisted(const GURL& url) const { +bool PixManager::IsMerchantAllowlisted(const GURL& url) const { // Since the optimization guide decider integration corresponding to PIX // merchant lists are allowlists for the question "Can this site be // optimized?", a match on the allowlist answers the question with "yes". @@ -102,7 +101,7 @@ optimization_guide::OptimizationGuideDecision::kTrue; } -void FacilitatedPaymentsManager::OnPixCodeValidated( +void PixManager::OnPixCodeValidated( std::string pix_code, base::TimeTicks start_time, base::expected<bool, std::string> is_pix_code_valid) { @@ -154,12 +153,11 @@ initiate_payment_request_details_->pix_code_ = std::move(pix_code); api_availability_check_start_time_ = base::TimeTicks::Now(); - GetApiClient()->IsAvailable( - base::BindOnce(&FacilitatedPaymentsManager::OnApiAvailabilityReceived, - weak_ptr_factory_.GetWeakPtr())); + GetApiClient()->IsAvailable(base::BindOnce( + &PixManager::OnApiAvailabilityReceived, weak_ptr_factory_.GetWeakPtr())); } -FacilitatedPaymentsApiClient* FacilitatedPaymentsManager::GetApiClient() { +FacilitatedPaymentsApiClient* PixManager::GetApiClient() { if (!api_client_) { if (api_client_creator_) { api_client_ = std::move(api_client_creator_).Run(); @@ -169,8 +167,7 @@ return api_client_.get(); } -void FacilitatedPaymentsManager::OnApiAvailabilityReceived( - bool is_api_available) { +void PixManager::OnApiAvailabilityReceived(bool is_api_available) { LogApiAvailabilityCheckResultAndLatency( kPaymentsType, is_api_available, (base::TimeTicks::Now() - api_availability_check_start_time_)); @@ -185,13 +182,12 @@ ShowPixPaymentPrompt( client_->GetPaymentsDataManager()->GetMaskedBankAccounts(), - base::BindOnce(&FacilitatedPaymentsManager::OnPixPaymentPromptResult, + base::BindOnce(&PixManager::OnPixPaymentPromptResult, weak_ptr_factory_.GetWeakPtr())); } -void FacilitatedPaymentsManager::OnPixPaymentPromptResult( - bool is_prompt_accepted, - int64_t selected_instrument_id) { +void PixManager::OnPixPaymentPromptResult(bool is_prompt_accepted, + int64_t selected_instrument_id) { if (!is_prompt_accepted) { // The metric for the reason of this early-return is logged in `OnUiEvent`. return; @@ -202,14 +198,13 @@ initiate_payment_request_details_->instrument_id_ = selected_instrument_id; - client_->LoadRiskData( - base::BindOnce(&FacilitatedPaymentsManager::OnRiskDataLoaded, - weak_ptr_factory_.GetWeakPtr(), base::TimeTicks::Now())); + client_->LoadRiskData(base::BindOnce(&PixManager::OnRiskDataLoaded, + weak_ptr_factory_.GetWeakPtr(), + base::TimeTicks::Now())); } -void FacilitatedPaymentsManager::OnRiskDataLoaded( - base::TimeTicks start_time, - const std::string& risk_data) { +void PixManager::OnRiskDataLoaded(base::TimeTicks start_time, + const std::string& risk_data) { LogLoadRiskDataResultAndLatency(kPaymentsType, /*was_successful=*/!risk_data.empty(), base::TimeTicks::Now() - start_time); @@ -221,13 +216,11 @@ initiate_payment_request_details_->risk_data_ = risk_data; get_client_token_loading_start_time_ = base::TimeTicks::Now(); - GetApiClient()->GetClientToken( - base::BindOnce(&FacilitatedPaymentsManager::OnGetClientToken, - weak_ptr_factory_.GetWeakPtr())); + GetApiClient()->GetClientToken(base::BindOnce( + &PixManager::OnGetClientToken, weak_ptr_factory_.GetWeakPtr())); } -void FacilitatedPaymentsManager::OnGetClientToken( - std::vector<uint8_t> client_token) { +void PixManager::OnGetClientToken(std::vector<uint8_t> client_token) { LogGetClientTokenResultAndLatency( kPaymentsType, !client_token.empty(), (base::TimeTicks::Now() - get_client_token_loading_start_time_)); @@ -243,21 +236,20 @@ } } -void FacilitatedPaymentsManager::SendInitiatePaymentRequest() { +void PixManager::SendInitiatePaymentRequest() { initiate_payment_network_start_time_ = base::TimeTicks::Now(); if (FacilitatedPaymentsNetworkInterface* payments_network_interface = client_->GetFacilitatedPaymentsNetworkInterface()) { LogInitiatePaymentAttempt(kPaymentsType); payments_network_interface->InitiatePayment( std::move(initiate_payment_request_details_), - base::BindOnce( - &FacilitatedPaymentsManager::OnInitiatePaymentResponseReceived, - weak_ptr_factory_.GetWeakPtr()), + base::BindOnce(&PixManager::OnInitiatePaymentResponseReceived, + weak_ptr_factory_.GetWeakPtr()), client_->GetPaymentsDataManager()->app_locale()); } } -void FacilitatedPaymentsManager::OnInitiatePaymentResponseReceived( +void PixManager::OnInitiatePaymentResponseReceived( autofill::payments::PaymentsAutofillClient::PaymentsRpcResult result, std::unique_ptr<FacilitatedPaymentsInitiatePaymentResponseDetails> response_details) { @@ -281,7 +273,7 @@ } std::optional<CoreAccountInfo> account_info = client_->GetCoreAccountInfo(); // If the user logged out after selecting the payment method, the - // `account_info` would be empty, and the `FacilitatedPaymentsManager` should + // `account_info` would be empty, and the `PixManager` should // abandon the payment flow. if (!account_info.has_value() || account_info.value().IsEmpty()) { LogPixFlowExitedReason(PixFlowExitedReason::kUserLoggedOut); @@ -293,18 +285,16 @@ purchase_action_start_time_ = base::TimeTicks::Now(); GetApiClient()->InvokePurchaseAction( account_info.value(), response_details->action_token_, - base::BindOnce(&FacilitatedPaymentsManager::OnPurchaseActionResult, + base::BindOnce(&PixManager::OnPurchaseActionResult, weak_ptr_factory_.GetWeakPtr())); // Close the progress screen just after the platform screen appears. - ui_timer_.Start( - FROM_HERE, kProgressScreenDismissDelay, - base::BindOnce(&FacilitatedPaymentsManager::DismissProgressScreen, - weak_ptr_factory_.GetWeakPtr())); + ui_timer_.Start(FROM_HERE, kProgressScreenDismissDelay, + base::BindOnce(&PixManager::DismissProgressScreen, + weak_ptr_factory_.GetWeakPtr())); } -void FacilitatedPaymentsManager::OnPurchaseActionResult( - PurchaseActionResult result) { +void PixManager::OnPurchaseActionResult(PurchaseActionResult result) { switch (result) { case PurchaseActionResult::kCouldNotInvoke: LogPixFlowExitedReason( @@ -323,7 +313,7 @@ LogInitiatePurchaseActionResultUkm(result, ukm_source_id_); } -void FacilitatedPaymentsManager::OnUiEvent(UiEvent ui_event_type) { +void PixManager::OnUiEvent(UiEvent ui_event_type) { switch (ui_event_type) { case UiEvent::kNewScreenShown: { CHECK_NE(ui_state_, UiState::kHidden); @@ -354,12 +344,12 @@ } } -void FacilitatedPaymentsManager::DismissPrompt() { +void PixManager::DismissPrompt() { ui_state_ = UiState::kHidden; client_->DismissPrompt(); } -void FacilitatedPaymentsManager::ShowPixPaymentPrompt( +void PixManager::ShowPixPaymentPrompt( base::span<const autofill::BankAccount> bank_account_suggestions, base::OnceCallback<void(bool, int64_t)> on_user_decision_callback) { ui_state_ = UiState::kFopSelector; @@ -367,17 +357,17 @@ std::move(on_user_decision_callback)); } -void FacilitatedPaymentsManager::ShowProgressScreen() { +void PixManager::ShowProgressScreen() { ui_state_ = UiState::kProgressScreen; client_->ShowProgressScreen(); } -void FacilitatedPaymentsManager::ShowErrorScreen() { +void PixManager::ShowErrorScreen() { ui_state_ = UiState::kErrorScreen; client_->ShowErrorScreen(); } -void FacilitatedPaymentsManager::DismissProgressScreen() { +void PixManager::DismissProgressScreen() { if (ui_state_ == UiState::kProgressScreen) { DismissPrompt(); }
diff --git a/components/facilitated_payments/core/browser/facilitated_payments_manager.h b/components/facilitated_payments/core/browser/pix_manager.h similarity index 67% rename from components/facilitated_payments/core/browser/facilitated_payments_manager.h rename to components/facilitated_payments/core/browser/pix_manager.h index fcdb8b6f..19ee25299 100644 --- a/components/facilitated_payments/core/browser/facilitated_payments_manager.h +++ b/components/facilitated_payments/core/browser/pix_manager.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_FACILITATED_PAYMENTS_CORE_BROWSER_FACILITATED_PAYMENTS_MANAGER_H_ -#define COMPONENTS_FACILITATED_PAYMENTS_CORE_BROWSER_FACILITATED_PAYMENTS_MANAGER_H_ +#ifndef COMPONENTS_FACILITATED_PAYMENTS_CORE_BROWSER_PIX_MANAGER_H_ +#define COMPONENTS_FACILITATED_PAYMENTS_CORE_BROWSER_PIX_MANAGER_H_ #include <cstring> #include <memory> @@ -34,21 +34,17 @@ class FacilitatedPaymentsClient; -// A cross-platform interface that manages the flow of payments for non-form -// based form-of-payments between the browser and the Payments platform. It is +// A cross-platform interface that manages the Pix payment flow. It is // owned by `FacilitatedPaymentsDriver`. -// TODO(crbug.com/369898977): Rename `FacilitatedPaymentsManager` to be PIX -// specific and update the class level comment. -class FacilitatedPaymentsManager { +class PixManager { public: - FacilitatedPaymentsManager( + PixManager( FacilitatedPaymentsClient* client, FacilitatedPaymentsApiClientCreator api_client_creator, optimization_guide::OptimizationGuideDecider* optimization_guide_decider); - FacilitatedPaymentsManager(const FacilitatedPaymentsManager&) = delete; - FacilitatedPaymentsManager& operator=(const FacilitatedPaymentsManager&) = - delete; - virtual ~FacilitatedPaymentsManager(); + PixManager(const PixManager&) = delete; + PixManager& operator=(const PixManager&) = delete; + virtual ~PixManager(); // Resets `this` to initial state. Cancels any alive async callbacks. void Reset(); @@ -62,124 +58,107 @@ ukm::SourceId ukm_source_id); private: - friend class FacilitatedPaymentsManagerTest; - friend class FacilitatedPaymentsManagerTestForUiScreens; + friend class PixManagerTest; + friend class PixManagerTestForUiScreens; // Keep all entries in alphabetical order! - FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTest, - ApiClientInitializedLazily); - FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTest, + FRIEND_TEST_ALL_PREFIXES(PixManagerTest, ApiClientInitializedLazily); + FRIEND_TEST_ALL_PREFIXES(PixManagerTest, ApiClientTriggeredAfterPixCodeValidation); - FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTest, + FRIEND_TEST_ALL_PREFIXES(PixManagerTest, CopyTrigger_UrlInAllowlist_PixValidationTriggered); FRIEND_TEST_ALL_PREFIXES( - FacilitatedPaymentsManagerTest, + PixManagerTest, CopyTrigger_UrlNotInAllowlist_PixValidationNotTriggered); - FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTest, DismissPrompt); + FRIEND_TEST_ALL_PREFIXES(PixManagerTest, DismissPrompt); FRIEND_TEST_ALL_PREFIXES( - FacilitatedPaymentsManagerTest, + PixManagerTest, ErrorScreenNotAutoDismissedAfterInvokingPurchaseAction); - FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTest, + FRIEND_TEST_ALL_PREFIXES(PixManagerTest, HandlesFailureToLazilyInitializeApiClient); - FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTest, + FRIEND_TEST_ALL_PREFIXES(PixManagerTest, LogApiAvailabilityCheckResultAndLatency); - FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTest, - LogGetClientTokenResultAndLatency); - FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTest, - LogInitiatePurchaseActionAttempt); - FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTest, + FRIEND_TEST_ALL_PREFIXES(PixManagerTest, LogGetClientTokenResultAndLatency); + FRIEND_TEST_ALL_PREFIXES(PixManagerTest, LogInitiatePurchaseActionAttempt); + FRIEND_TEST_ALL_PREFIXES(PixManagerTest, LogInitiatePurchaseActionResultAndLatency); - FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTest, + FRIEND_TEST_ALL_PREFIXES(PixManagerTest, NoPaymentsDataManager_NoApiClientTriggered); - FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTest, - NoPixAccounts_NoApiClientTriggered); - FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTest, + FRIEND_TEST_ALL_PREFIXES(PixManagerTest, NoPixAccounts_NoApiClientTriggered); + FRIEND_TEST_ALL_PREFIXES(PixManagerTest, NoPixPaymentPromptWhenApiClientNotAvailable); - FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTest, + FRIEND_TEST_ALL_PREFIXES(PixManagerTest, OnGetClientToken_ClientTokenEmpty_ErrorScreenShown); - FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTest, + FRIEND_TEST_ALL_PREFIXES(PixManagerTest, OnInitiatePaymentResponseReceived_FailureResponse); FRIEND_TEST_ALL_PREFIXES( - FacilitatedPaymentsManagerTest, + PixManagerTest, OnInitiatePaymentResponseReceived_InvokePurchaseActionTriggered); FRIEND_TEST_ALL_PREFIXES( - FacilitatedPaymentsManagerTest, + PixManagerTest, OnInitiatePaymentResponseReceived_LoggedOutProfile_ErrorScreenShown); FRIEND_TEST_ALL_PREFIXES( - FacilitatedPaymentsManagerTest, + PixManagerTest, OnInitiatePaymentResponseReceived_NoActionToken_ErrorScreenShown); FRIEND_TEST_ALL_PREFIXES( - FacilitatedPaymentsManagerTest, + PixManagerTest, OnInitiatePaymentResponseReceived_NoCoreAccountInfo_ErrorScreenShown); - FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTest, + FRIEND_TEST_ALL_PREFIXES(PixManagerTest, OnPixPaymentPromptResult_FopSelected); - FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTest, + FRIEND_TEST_ALL_PREFIXES(PixManagerTest, OnPixPaymentPromptResult_FopSelectorDeclined); FRIEND_TEST_ALL_PREFIXES( - FacilitatedPaymentsManagerTest, + PixManagerTest, OnPurchaseActionResult_CouldNotInvoke_ErrorScreenShown); FRIEND_TEST_ALL_PREFIXES( - FacilitatedPaymentsManagerTest, + PixManagerTest, OnPurchaseActionResult_ResultCanceled_UiScreenDismissed); - FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTest, + FRIEND_TEST_ALL_PREFIXES(PixManagerTest, OnPurchaseActionResult_ResultOk_UiScreenDismissed); - FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTest, + FRIEND_TEST_ALL_PREFIXES(PixManagerTest, PayflowExitedReason_ApiClientNotAvailable); - FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTest, + FRIEND_TEST_ALL_PREFIXES(PixManagerTest, PayflowExitedReason_ClientTokenNotAvailable); - FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTest, + FRIEND_TEST_ALL_PREFIXES(PixManagerTest, PayflowExitedReason_CodeValidatorFailed); - FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTest, - PayflowExitedReason_InvalidCode); - FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTest, - PayflowExitedReason_NoLinkedAccount); - FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTest, - PayflowExitedReason_RiskDataEmpty); - FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTest, - PayflowExitedReason_UserOptedOut); - FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTest, + FRIEND_TEST_ALL_PREFIXES(PixManagerTest, PayflowExitedReason_InvalidCode); + FRIEND_TEST_ALL_PREFIXES(PixManagerTest, PayflowExitedReason_NoLinkedAccount); + FRIEND_TEST_ALL_PREFIXES(PixManagerTest, PayflowExitedReason_RiskDataEmpty); + FRIEND_TEST_ALL_PREFIXES(PixManagerTest, PayflowExitedReason_UserOptedOut); + FRIEND_TEST_ALL_PREFIXES(PixManagerTest, PixCodeValidationFailed_NoApiClientTriggered); FRIEND_TEST_ALL_PREFIXES( - FacilitatedPaymentsManagerTest, + PixManagerTest, PixCodeValidatorTerminatedUnexpectedly_NoApiClientTriggered); - FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTest, + FRIEND_TEST_ALL_PREFIXES(PixManagerTest, PixFopSelectorShown_HistogramsLogged); - FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTest, + FRIEND_TEST_ALL_PREFIXES(PixManagerTest, PixPrefTurnedOff_NoApiClientTriggered); FRIEND_TEST_ALL_PREFIXES( - FacilitatedPaymentsManagerTest, + PixManagerTest, ProgressScreenAutoDismissedAfterInvokingPurchaseAction); - FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTest, - RegisterPixAllowlist); - FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTest, - ResettingPreventsPayment); + FRIEND_TEST_ALL_PREFIXES(PixManagerTest, RegisterPixAllowlist); + FRIEND_TEST_ALL_PREFIXES(PixManagerTest, ResettingPreventsPayment); FRIEND_TEST_ALL_PREFIXES( - FacilitatedPaymentsManagerTest, + PixManagerTest, RiskDataEmpty_GetClientTokenNotCalled_ErrorScreenShown); - FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTest, - RiskDataEmpty_HistogramsLogged); - FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTest, + FRIEND_TEST_ALL_PREFIXES(PixManagerTest, RiskDataEmpty_HistogramsLogged); + FRIEND_TEST_ALL_PREFIXES(PixManagerTest, RiskDataNotEmpty_GetClientTokenCalled); - FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTest, - RiskDataNotEmpty_HistogramsLogged); - FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTest, - SendInitiatePaymentRequest); - FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTest, ShowErrorScreen); - FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTest, - ShowPixPaymentPrompt); - FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTest, ShowProgressScreen); - FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTest, + FRIEND_TEST_ALL_PREFIXES(PixManagerTest, RiskDataNotEmpty_HistogramsLogged); + FRIEND_TEST_ALL_PREFIXES(PixManagerTest, SendInitiatePaymentRequest); + FRIEND_TEST_ALL_PREFIXES(PixManagerTest, ShowErrorScreen); + FRIEND_TEST_ALL_PREFIXES(PixManagerTest, ShowPixPaymentPrompt); + FRIEND_TEST_ALL_PREFIXES(PixManagerTest, ShowProgressScreen); + FRIEND_TEST_ALL_PREFIXES(PixManagerTest, ShowsPixPaymentPromptWhenApiClientAvailable); - FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTestForUiScreens, + FRIEND_TEST_ALL_PREFIXES(PixManagerTestForUiScreens, NewScreenCouldNotBeShown); - FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTestForUiScreens, - NewScreenShown); - FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTestForUiScreens, - ScreenClosedByUser); - FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTestForUiScreens, - ScreenClosedNotByUser); - FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTestInLandscapeMode, + FRIEND_TEST_ALL_PREFIXES(PixManagerTestForUiScreens, NewScreenShown); + FRIEND_TEST_ALL_PREFIXES(PixManagerTestForUiScreens, ScreenClosedByUser); + FRIEND_TEST_ALL_PREFIXES(PixManagerTestForUiScreens, ScreenClosedNotByUser); + FRIEND_TEST_ALL_PREFIXES(PixManagerTestInLandscapeMode, PayflowExitedReason_LandscapeScreenOrientation); - FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTestInLandscapeMode, + FRIEND_TEST_ALL_PREFIXES(PixManagerTestInLandscapeMode, PixPayflowBlockedWhenFlagDisabled); // Register optimization guide deciders for PIX. It is an allowlist of URLs @@ -204,7 +183,7 @@ // Lazily initializes an API client and returns a pointer to it. Returns a // pointer to the existing API client, if one is already initialized. The - // FacilitatedPaymentManager owns this API client. This method can return + // PixManager owns this API client. This method can return // `nullptr` if the API client fails to initialize, e.g., if the // `RenderFrameHost` has been destroyed. FacilitatedPaymentsApiClient* GetApiClient(); @@ -322,9 +301,9 @@ // state via a callback. UiState ui_state_ = UiState::kHidden; - base::WeakPtrFactory<FacilitatedPaymentsManager> weak_ptr_factory_{this}; + base::WeakPtrFactory<PixManager> weak_ptr_factory_{this}; }; } // namespace payments::facilitated -#endif // COMPONENTS_FACILITATED_PAYMENTS_CORE_BROWSER_FACILITATED_PAYMENTS_MANAGER_H_ +#endif // COMPONENTS_FACILITATED_PAYMENTS_CORE_BROWSER_PIX_MANAGER_H_
diff --git a/components/facilitated_payments/core/browser/facilitated_payments_manager_unittest.cc b/components/facilitated_payments/core/browser/pix_manager_unittest.cc similarity index 74% rename from components/facilitated_payments/core/browser/facilitated_payments_manager_unittest.cc rename to components/facilitated_payments/core/browser/pix_manager_unittest.cc index cd19c5b..65cf4b9 100644 --- a/components/facilitated_payments/core/browser/facilitated_payments_manager_unittest.cc +++ b/components/facilitated_payments/core/browser/pix_manager_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/facilitated_payments/core/browser/facilitated_payments_manager.h" +#include "components/facilitated_payments/core/browser/pix_manager.h" #include <cstdint> #include <memory> @@ -64,7 +64,7 @@ } // namespace -class FacilitatedPaymentsManagerTest : public testing::Test { +class PixManagerTest : public testing::Test { public: base::test::TaskEnvironment task_environment_{ base::test::TaskEnvironment::TimeSource::MOCK_TIME}; @@ -74,7 +74,7 @@ std::make_unique<optimization_guide::MockOptimizationGuideDecider>(); client_ = std::make_unique<MockFacilitatedPaymentsClient>(); - manager_ = std::make_unique<FacilitatedPaymentsManager>( + pix_manager_ = std::make_unique<PixManager>( client_.get(), /*api_client_creator=*/ base::BindOnce(&MockFacilitatedPaymentsApiClient::CreateApiClient), optimization_guide_decider_.get()); @@ -105,14 +105,14 @@ MockFacilitatedPaymentsApiClient& GetApiClient() { return *static_cast<MockFacilitatedPaymentsApiClient*>( - manager_->GetApiClient()); + pix_manager_->GetApiClient()); } protected: std::unique_ptr<optimization_guide::MockOptimizationGuideDecider> optimization_guide_decider_; std::unique_ptr<MockFacilitatedPaymentsClient> client_; - std::unique_ptr<FacilitatedPaymentsManager> manager_; + std::unique_ptr<PixManager> pix_manager_; std::unique_ptr<PrefService> pref_service_; std::unique_ptr<autofill::TestPaymentsDataManager> payments_data_manager_; MockFacilitatedPaymentsNetworkInterface payments_network_interface_; @@ -125,19 +125,18 @@ // Test that the `PIX_PAYMENT_MERCHANT_ALLOWLIST` optimization type is // registered when RegisterPixOptimizationGuide is called. -TEST_F(FacilitatedPaymentsManagerTest, RegisterPixAllowlist) { +TEST_F(PixManagerTest, RegisterPixAllowlist) { EXPECT_CALL(*optimization_guide_decider_, RegisterOptimizationTypes(testing::ElementsAre( optimization_guide::proto::PIX_MERCHANT_ORIGINS_ALLOWLIST))) .Times(1); - manager_->RegisterPixAllowlist(); + pix_manager_->RegisterPixAllowlist(); } // If the facilitated payment API is not available, then the manager does not // show the Pix payment prompt. -TEST_F(FacilitatedPaymentsManagerTest, - NoPixPaymentPromptWhenApiClientNotAvailable) { +TEST_F(PixManagerTest, NoPixPaymentPromptWhenApiClientNotAvailable) { payments_data_manager_->AddMaskedBankAccountForTest( CreatePixBankAccount(/*instrument_id=*/1)); payments_data_manager_->AddMaskedBankAccountForTest( @@ -145,13 +144,12 @@ EXPECT_CALL(*client_, ShowPixPaymentPrompt(testing::_, testing::_)).Times(0); - manager_->OnApiAvailabilityReceived(false); + pix_manager_->OnApiAvailabilityReceived(false); } // If the facilitated payment API is available, then the manager shows the PIX // payment prompt. -TEST_F(FacilitatedPaymentsManagerTest, - ShowsPixPaymentPromptWhenApiClientAvailable) { +TEST_F(PixManagerTest, ShowsPixPaymentPromptWhenApiClientAvailable) { autofill::BankAccount pix_account1 = CreatePixBankAccount(/*instrument_id=*/1); autofill::BankAccount pix_account2 = @@ -163,22 +161,21 @@ {pix_account1, pix_account2}), testing::_)); - manager_->OnApiAvailabilityReceived(true); + pix_manager_->OnApiAvailabilityReceived(true); } // If the user does not select a payment account on the payment prompt, // 1. Request for risk data is not made. // 2. Progress screen is not shown. // 3. Histogram is not logged. -TEST_F(FacilitatedPaymentsManagerTest, - OnPixPaymentPromptResult_FopSelectorDeclined) { +TEST_F(PixManagerTest, OnPixPaymentPromptResult_FopSelectorDeclined) { base::HistogramTester histogram_tester; EXPECT_CALL(*client_, ShowProgressScreen()).Times(0); EXPECT_CALL(*client_, LoadRiskData(testing::_)).Times(0); - manager_->OnPixPaymentPromptResult(/*is_prompt_accepted=*/false, - /*selected_instrument_id=*/0); + pix_manager_->OnPixPaymentPromptResult(/*is_prompt_accepted=*/false, + /*selected_instrument_id=*/0); histogram_tester.ExpectUniqueSample( "FacilitatedPayments.Pix.FopSelector.UserAction", @@ -190,14 +187,14 @@ // 1. Request for risk data is made. // 2. Progress screen is shown. // 3. Histogram is logged. -TEST_F(FacilitatedPaymentsManagerTest, OnPixPaymentPromptResult_FopSelected) { +TEST_F(PixManagerTest, OnPixPaymentPromptResult_FopSelected) { base::HistogramTester histogram_tester; EXPECT_CALL(*client_, ShowProgressScreen()); EXPECT_CALL(*client_, LoadRiskData(testing::_)); - manager_->OnPixPaymentPromptResult(/*is_prompt_accepted=*/true, - /*selected_instrument_id=*/0); + pix_manager_->OnPixPaymentPromptResult(/*is_prompt_accepted=*/true, + /*selected_instrument_id=*/0); histogram_tester.ExpectUniqueSample( "FacilitatedPayments.Pix.FopSelector.UserAction", @@ -212,11 +209,11 @@ } // Verify risk data metrics are logged when risk data is fetched successfully. -TEST_F(FacilitatedPaymentsManagerTest, RiskDataNotEmpty_HistogramsLogged) { +TEST_F(PixManagerTest, RiskDataNotEmpty_HistogramsLogged) { base::HistogramTester histogram_tester; - manager_->OnRiskDataLoaded(base::TimeTicks::Now() - base::Seconds(2), - "seems pretty risky"); + pix_manager_->OnRiskDataLoaded(base::TimeTicks::Now() - base::Seconds(2), + "seems pretty risky"); histogram_tester.ExpectUniqueSample( "FacilitatedPayments.Pix.LoadRiskData.Success.Latency", @@ -225,10 +222,10 @@ } // Verify risk data metrics are logged when risk data is empty. -TEST_F(FacilitatedPaymentsManagerTest, RiskDataEmpty_HistogramsLogged) { +TEST_F(PixManagerTest, RiskDataEmpty_HistogramsLogged) { base::HistogramTester histogram_tester; - manager_->OnRiskDataLoaded(base::TimeTicks::Now() - base::Seconds(2), ""); + pix_manager_->OnRiskDataLoaded(base::TimeTicks::Now() - base::Seconds(2), ""); histogram_tester.ExpectUniqueSample( "FacilitatedPayments.Pix.LoadRiskData.Failure.Latency", @@ -238,10 +235,10 @@ // If the risk data is empty, then the PayflowExitedReason histogram should // be logged. -TEST_F(FacilitatedPaymentsManagerTest, PayflowExitedReason_RiskDataEmpty) { +TEST_F(PixManagerTest, PayflowExitedReason_RiskDataEmpty) { base::HistogramTester histogram_tester; - manager_->OnRiskDataLoaded(base::TimeTicks::Now(), ""); + pix_manager_->OnRiskDataLoaded(base::TimeTicks::Now(), ""); histogram_tester.ExpectUniqueSample( "FacilitatedPayments.Pix.PayflowExitedReason", @@ -251,36 +248,35 @@ // If the risk data is empty, then the manager does not retrieve a client token // from the facilitated payments API client. -TEST_F(FacilitatedPaymentsManagerTest, - RiskDataEmpty_GetClientTokenNotCalled_ErrorScreenShown) { +TEST_F(PixManagerTest, RiskDataEmpty_GetClientTokenNotCalled_ErrorScreenShown) { EXPECT_CALL(GetApiClient(), GetClientToken(testing::_)).Times(0); EXPECT_CALL(*client_, ShowErrorScreen()); - manager_->OnRiskDataLoaded(/*start_time=*/base::TimeTicks::Now(), - /*risk_data=*/""); + pix_manager_->OnRiskDataLoaded(/*start_time=*/base::TimeTicks::Now(), + /*risk_data=*/""); } // If the risk data is not empty, then the manager retrieves a client token from // the facilitated payments API client. -TEST_F(FacilitatedPaymentsManagerTest, RiskDataNotEmpty_GetClientTokenCalled) { +TEST_F(PixManagerTest, RiskDataNotEmpty_GetClientTokenCalled) { EXPECT_CALL(GetApiClient(), GetClientToken(testing::_)); - manager_->OnRiskDataLoaded(/*start_time=*/base::TimeTicks::Now(), - /*risk_data=*/"seems pretty risky"); + pix_manager_->OnRiskDataLoaded(/*start_time=*/base::TimeTicks::Now(), + /*risk_data=*/"seems pretty risky"); } // The GetClientToken async call is made after fetching the risk data. This test // verifies that the result and latency of the GetClientToken call is logged // correctly. -TEST_F(FacilitatedPaymentsManagerTest, LogGetClientTokenResultAndLatency) { +TEST_F(PixManagerTest, LogGetClientTokenResultAndLatency) { for (bool get_client_token_result : {true, false}) { base::HistogramTester histogram_tester; EXPECT_CALL(GetApiClient(), GetClientToken(testing::_)); - manager_->OnRiskDataLoaded(/*start_time=*/base::TimeTicks::Now(), - /*risk_data=*/"seems pretty risky"); + pix_manager_->OnRiskDataLoaded(/*start_time=*/base::TimeTicks::Now(), + /*risk_data=*/"seems pretty risky"); FastForwardBy(base::Seconds(2)); - manager_->OnGetClientToken( + pix_manager_->OnGetClientToken( get_client_token_result ? std::vector<uint8_t>{'t', 'o', 'k', 'e', 'n'} : std::vector<uint8_t>{}); @@ -295,11 +291,10 @@ // If the client token is not available, then the PayflowExitedReason histogram // should be logged. -TEST_F(FacilitatedPaymentsManagerTest, - PayflowExitedReason_ClientTokenNotAvailable) { +TEST_F(PixManagerTest, PayflowExitedReason_ClientTokenNotAvailable) { base::HistogramTester histogram_tester; - manager_->OnGetClientToken(std::vector<uint8_t>{}); + pix_manager_->OnGetClientToken(std::vector<uint8_t>{}); histogram_tester.ExpectUniqueSample( "FacilitatedPayments.Pix.PayflowExitedReason", @@ -307,35 +302,34 @@ /*expected_bucket_count=*/1); } -TEST_F(FacilitatedPaymentsManagerTest, - OnGetClientToken_ClientTokenEmpty_ErrorScreenShown) { +TEST_F(PixManagerTest, OnGetClientToken_ClientTokenEmpty_ErrorScreenShown) { EXPECT_CALL(*client_, ShowErrorScreen()); - manager_->OnGetClientToken(std::vector<uint8_t>{}); + pix_manager_->OnGetClientToken(std::vector<uint8_t>{}); } -TEST_F(FacilitatedPaymentsManagerTest, ResettingPreventsPayment) { - manager_->initiate_payment_request_details_->risk_data_ = +TEST_F(PixManagerTest, ResettingPreventsPayment) { + pix_manager_->initiate_payment_request_details_->risk_data_ = "seems pretty risky"; - manager_->initiate_payment_request_details_->client_token_ = + pix_manager_->initiate_payment_request_details_->client_token_ = std::vector<uint8_t>{'t', 'o', 'k', 'e', 'n'}; - manager_->initiate_payment_request_details_->billing_customer_number_ = 13; - manager_->initiate_payment_request_details_->merchant_payment_page_hostname_ = - "foo.com"; - manager_->initiate_payment_request_details_->instrument_id_ = 13; - manager_->initiate_payment_request_details_->pix_code_ = "a valid code"; + pix_manager_->initiate_payment_request_details_->billing_customer_number_ = + 13; + pix_manager_->initiate_payment_request_details_ + ->merchant_payment_page_hostname_ = "foo.com"; + pix_manager_->initiate_payment_request_details_->instrument_id_ = 13; + pix_manager_->initiate_payment_request_details_->pix_code_ = "a valid code"; EXPECT_TRUE( - manager_->initiate_payment_request_details_->IsReadyForPixPayment()); + pix_manager_->initiate_payment_request_details_->IsReadyForPixPayment()); - manager_->Reset(); + pix_manager_->Reset(); EXPECT_FALSE( - manager_->initiate_payment_request_details_->IsReadyForPixPayment()); + pix_manager_->initiate_payment_request_details_->IsReadyForPixPayment()); } -TEST_F(FacilitatedPaymentsManagerTest, - CopyTrigger_UrlInAllowlist_LogPixCodeCopied) { +TEST_F(PixManagerTest, CopyTrigger_UrlInAllowlist_LogPixCodeCopied) { base::HistogramTester histogram_tester; payments_data_manager_->AddMaskedBankAccountForTest( CreatePixBankAccount(/*instrument_id=*/1)); @@ -353,7 +347,7 @@ .WillOnce(testing::Return( optimization_guide::OptimizationGuideDecision::kTrue)); - manager_->OnPixCodeCopiedToClipboard( + pix_manager_->OnPixCodeCopiedToClipboard( url, "00020126370014br.gov.bcb.pix2515www.example.com6304EA3F", ukm::UkmRecorder::GetNewSourceID()); @@ -367,8 +361,7 @@ EXPECT_EQ(ukm_entries[0].metrics.at("PixCodeCopied"), true); } -TEST_F(FacilitatedPaymentsManagerTest, - CopyTrigger_UrlInAllowlist_PixValidationTriggered) { +TEST_F(PixManagerTest, CopyTrigger_UrlInAllowlist_PixValidationTriggered) { payments_data_manager_->AddMaskedBankAccountForTest( CreatePixBankAccount(/*instrument_id=*/1)); GURL url("https://example.com/"); @@ -387,7 +380,7 @@ // If Pix validation is run, then IsAvailable should get called once. EXPECT_CALL(GetApiClient(), IsAvailable(testing::_)); - manager_->OnPixCodeCopiedToClipboard( + pix_manager_->OnPixCodeCopiedToClipboard( url, "00020126370014br.gov.bcb.pix2515www.example.com6304EA3F", ukm::UkmRecorder::GetNewSourceID()); @@ -396,7 +389,7 @@ task_environment_.RunUntilIdle(); } -TEST_F(FacilitatedPaymentsManagerTest, +TEST_F(PixManagerTest, CopyTrigger_UrlNotInAllowlist_PixValidationNotTriggered) { payments_data_manager_->AddMaskedBankAccountForTest( CreatePixBankAccount(/*instrument_id=*/1)); @@ -417,7 +410,7 @@ // If Pix validation is not run, then IsAvailable shouldn't get called. EXPECT_CALL(GetApiClient(), IsAvailable(testing::_)).Times(0); - manager_->OnPixCodeCopiedToClipboard( + pix_manager_->OnPixCodeCopiedToClipboard( url, "00020126370014br.gov.bcb.pix2515www.example.com6304EA3F", ukm::UkmRecorder::GetNewSourceID()); // The DataDecoder (utility process) validates the Pix code string @@ -425,8 +418,7 @@ task_environment_.RunUntilIdle(); } -TEST_F(FacilitatedPaymentsManagerTest, - TestPayFlowCanBeTriggeredOnlyOncePerPageLoad) { +TEST_F(PixManagerTest, TestPayFlowCanBeTriggeredOnlyOncePerPageLoad) { payments_data_manager_->AddMaskedBankAccountForTest( CreatePixBankAccount(/*instrument_id=*/1)); GURL url("https://example.com/"); @@ -445,50 +437,48 @@ std::string pix_code = "00020126370014br.gov.bcb.pix2515www.example.com6304EA3F"; - manager_->OnPixCodeCopiedToClipboard(url, pix_code, - ukm::UkmRecorder::GetNewSourceID()); - manager_->OnPixCodeCopiedToClipboard(url, pix_code, - ukm::UkmRecorder::GetNewSourceID()); + pix_manager_->OnPixCodeCopiedToClipboard(url, pix_code, + ukm::UkmRecorder::GetNewSourceID()); + pix_manager_->OnPixCodeCopiedToClipboard(url, pix_code, + ukm::UkmRecorder::GetNewSourceID()); // The DataDecoder (utility process) validates the Pix code string // asynchronously. task_environment_.RunUntilIdle(); } // The manager checks for API availability after validating the Pix code. -TEST_F(FacilitatedPaymentsManagerTest, - ApiClientTriggeredAfterPixCodeValidation) { +TEST_F(PixManagerTest, ApiClientTriggeredAfterPixCodeValidation) { payments_data_manager_->AddMaskedBankAccountForTest( CreatePixBankAccount(/*instrument_id=*/1)); EXPECT_CALL(GetApiClient(), IsAvailable(testing::_)); - manager_->OnPixCodeValidated(/*pix_code=*/std::string(), - base::TimeTicks::Now(), - /*is_pix_code_valid=*/true); + pix_manager_->OnPixCodeValidated(/*pix_code=*/std::string(), + base::TimeTicks::Now(), + /*is_pix_code_valid=*/true); } // If the Pix code validation in the utility process has returned `false`, then // the manager does not check the API for availability. -TEST_F(FacilitatedPaymentsManagerTest, - PixCodeValidationFailed_NoApiClientTriggered) { +TEST_F(PixManagerTest, PixCodeValidationFailed_NoApiClientTriggered) { payments_data_manager_->AddMaskedBankAccountForTest( CreatePixBankAccount(/*instrument_id=*/1)); EXPECT_CALL(GetApiClient(), IsAvailable(testing::_)).Times(0); - manager_->OnPixCodeValidated(/*pix_code=*/std::string(), - base::TimeTicks::Now(), - /*is_pix_code_valid=*/false); + pix_manager_->OnPixCodeValidated(/*pix_code=*/std::string(), + base::TimeTicks::Now(), + /*is_pix_code_valid=*/false); } // If the Pix code validation in the utility process has returned `false`, then // the PayflowExitedReason histogram should be logged. -TEST_F(FacilitatedPaymentsManagerTest, PayflowExitedReason_InvalidCode) { +TEST_F(PixManagerTest, PayflowExitedReason_InvalidCode) { base::HistogramTester histogram_tester; - manager_->OnPixCodeValidated(/*pix_code=*/std::string(), - base::TimeTicks::Now(), - /*is_pix_code_valid=*/false); + pix_manager_->OnPixCodeValidated(/*pix_code=*/std::string(), + base::TimeTicks::Now(), + /*is_pix_code_valid=*/false); histogram_tester.ExpectUniqueSample( "FacilitatedPayments.Pix.PayflowExitedReason", @@ -498,15 +488,15 @@ // If the user has opted out of the Pix flow, the PayflowExitedReason // histogram should be logged. -TEST_F(FacilitatedPaymentsManagerTest, PayflowExitedReason_UserOptedOut) { +TEST_F(PixManagerTest, PayflowExitedReason_UserOptedOut) { base::HistogramTester histogram_tester; payments_data_manager_->AddMaskedBankAccountForTest( CreatePixBankAccount(/*instrument_id=*/1)); autofill::prefs::SetFacilitatedPaymentsPix(pref_service_.get(), false); - manager_->OnPixCodeValidated(/*pix_code=*/std::string(), - base::TimeTicks::Now(), - /*is_pix_code_valid=*/true); + pix_manager_->OnPixCodeValidated(/*pix_code=*/std::string(), + base::TimeTicks::Now(), + /*is_pix_code_valid=*/true); histogram_tester.ExpectUniqueSample( "FacilitatedPayments.Pix.PayflowExitedReason", @@ -516,12 +506,12 @@ // If the user doesn't have any linked Pix account, the PayflowExitedReason // histogram should be logged. -TEST_F(FacilitatedPaymentsManagerTest, PayflowExitedReason_NoLinkedAccount) { +TEST_F(PixManagerTest, PayflowExitedReason_NoLinkedAccount) { base::HistogramTester histogram_tester; - manager_->OnPixCodeValidated(/*pix_code=*/std::string(), - base::TimeTicks::Now(), - /*is_pix_code_valid=*/true); + pix_manager_->OnPixCodeValidated(/*pix_code=*/std::string(), + base::TimeTicks::Now(), + /*is_pix_code_valid=*/true); histogram_tester.ExpectUniqueSample( "FacilitatedPayments.Pix.PayflowExitedReason", @@ -532,14 +522,14 @@ // If the validation utility process has disconnected (e.g., due to a crash in // the validation code), then the manager does not check the API for // availability. -TEST_F(FacilitatedPaymentsManagerTest, +TEST_F(PixManagerTest, PixCodeValidatorTerminatedUnexpectedly_NoApiClientTriggered) { payments_data_manager_->AddMaskedBankAccountForTest( CreatePixBankAccount(/*instrument_id=*/1)); EXPECT_CALL(GetApiClient(), IsAvailable(testing::_)).Times(0); - manager_->OnPixCodeValidated( + pix_manager_->OnPixCodeValidated( /*pix_code=*/std::string(), base::TimeTicks::Now(), /*is_pix_code_valid=*/ base::unexpected("Data Decoder terminated unexpectedly")); @@ -548,11 +538,10 @@ // If the validation utility process has disconnected (e.g., due to a crash in // the validation code), then the PayflowExitedReason histogram should be // logged. -TEST_F(FacilitatedPaymentsManagerTest, - PayflowExitedReason_CodeValidatorFailed) { +TEST_F(PixManagerTest, PayflowExitedReason_CodeValidatorFailed) { base::HistogramTester histogram_tester; - manager_->OnPixCodeValidated( + pix_manager_->OnPixCodeValidated( /*pix_code=*/std::string(), base::TimeTicks::Now(), /*is_pix_code_valid=*/ base::unexpected("Data Decoder terminated unexpectedly")); @@ -565,7 +554,7 @@ // If the Pix payment user pref is turned off, the manager does not check // whether the facilitated payment API is available. -TEST_F(FacilitatedPaymentsManagerTest, PixPrefTurnedOff_NoApiClientTriggered) { +TEST_F(PixManagerTest, PixPrefTurnedOff_NoApiClientTriggered) { payments_data_manager_->AddMaskedBankAccountForTest( CreatePixBankAccount(/*instrument_id=*/1)); // Turn off Pix pref. @@ -573,25 +562,24 @@ EXPECT_CALL(GetApiClient(), IsAvailable(testing::_)).Times(0); - manager_->OnPixCodeValidated(/*pix_code=*/std::string(), - base::TimeTicks::Now(), - /*is_pix_code_valid=*/true); + pix_manager_->OnPixCodeValidated(/*pix_code=*/std::string(), + base::TimeTicks::Now(), + /*is_pix_code_valid=*/true); } // If the user doesn't have any linked Pix accounts, the manager does not check // whether the facilitated payment API is available. -TEST_F(FacilitatedPaymentsManagerTest, NoPixAccounts_NoApiClientTriggered) { +TEST_F(PixManagerTest, NoPixAccounts_NoApiClientTriggered) { EXPECT_CALL(GetApiClient(), IsAvailable(testing::_)).Times(0); - manager_->OnPixCodeValidated(/*pix_code=*/std::string(), - base::TimeTicks::Now(), - /*is_pix_code_valid=*/true); + pix_manager_->OnPixCodeValidated(/*pix_code=*/std::string(), + base::TimeTicks::Now(), + /*is_pix_code_valid=*/true); } // If payments data manager is unavailable, the manager does not check // whether the facilitated payment API is available. -TEST_F(FacilitatedPaymentsManagerTest, - NoPaymentsDataManager_NoApiClientTriggered) { +TEST_F(PixManagerTest, NoPaymentsDataManager_NoApiClientTriggered) { payments_data_manager_->AddMaskedBankAccountForTest( CreatePixBankAccount(/*instrument_id=*/1)); ON_CALL(*client_, GetPaymentsDataManager) @@ -599,19 +587,19 @@ EXPECT_CALL(GetApiClient(), IsAvailable(testing::_)).Times(0); - manager_->OnPixCodeValidated(/*pix_code=*/std::string(), - base::TimeTicks::Now(), - /*is_pix_code_valid=*/true); + pix_manager_->OnPixCodeValidated(/*pix_code=*/std::string(), + base::TimeTicks::Now(), + /*is_pix_code_valid=*/true); } // Test that SendInitiatePaymentRequest initiates payment using the // FacilitatedPaymentsNetworkInterface. -TEST_F(FacilitatedPaymentsManagerTest, SendInitiatePaymentRequest) { +TEST_F(PixManagerTest, SendInitiatePaymentRequest) { base::HistogramTester histogram_tester; EXPECT_CALL(payments_network_interface_, InitiatePayment(testing::_, testing::_, testing::_)); - manager_->SendInitiatePaymentRequest(); + pix_manager_->SendInitiatePaymentRequest(); histogram_tester.ExpectUniqueSample( "FacilitatedPayments.Pix.InitiatePayment.Attempt", @@ -622,10 +610,9 @@ // Test that if the response from // `FacilitatedPaymentsNetworkInterface::InitiatePayment` call has failure // result, purchase action is not invoked. Instead, an error message is shown. -TEST_F(FacilitatedPaymentsManagerTest, - OnInitiatePaymentResponseReceived_FailureResponse) { +TEST_F(PixManagerTest, OnInitiatePaymentResponseReceived_FailureResponse) { base::HistogramTester histogram_tester; - manager_->SendInitiatePaymentRequest(); + pix_manager_->SendInitiatePaymentRequest(); ON_CALL(*client_, GetCoreAccountInfo) .WillByDefault(testing::Return(CreateLoggedInAccountInfo())); @@ -637,7 +624,7 @@ response_details->action_token_ = std::vector<uint8_t>{'t', 'o', 'k', 'e', 'n'}; FastForwardBy(base::Seconds(2)); - manager_->OnInitiatePaymentResponseReceived( + pix_manager_->OnInitiatePaymentResponseReceived( autofill::payments::PaymentsAutofillClient::PaymentsRpcResult:: kPermanentFailure, std::move(response_details)); @@ -655,10 +642,10 @@ // Test that if the response from // `FacilitatedPaymentsNetworkInterface::InitiatePayment` has empty action // token, purchase action is not invoked. Instead, an error message is shown. -TEST_F(FacilitatedPaymentsManagerTest, +TEST_F(PixManagerTest, OnInitiatePaymentResponseReceived_NoActionToken_ErrorScreenShown) { base::HistogramTester histogram_tester; - manager_->SendInitiatePaymentRequest(); + pix_manager_->SendInitiatePaymentRequest(); ON_CALL(*client_, GetCoreAccountInfo) .WillByDefault(testing::Return(CreateLoggedInAccountInfo())); @@ -668,7 +655,7 @@ FastForwardBy(base::Seconds(2)); auto response_details = std::make_unique<FacilitatedPaymentsInitiatePaymentResponseDetails>(); - manager_->OnInitiatePaymentResponseReceived( + pix_manager_->OnInitiatePaymentResponseReceived( autofill::payments::PaymentsAutofillClient::PaymentsRpcResult::kSuccess, std::move(response_details)); @@ -684,10 +671,10 @@ // Test that if the core account is std::nullopt, purchase action is not // invoked. Instead, an error message is shown. -TEST_F(FacilitatedPaymentsManagerTest, +TEST_F(PixManagerTest, OnInitiatePaymentResponseReceived_NoCoreAccountInfo_ErrorScreenShown) { base::HistogramTester histogram_tester; - manager_->SendInitiatePaymentRequest(); + pix_manager_->SendInitiatePaymentRequest(); ON_CALL(*client_, GetCoreAccountInfo) .WillByDefault(testing::Return(std::nullopt)); @@ -699,7 +686,7 @@ std::make_unique<FacilitatedPaymentsInitiatePaymentResponseDetails>(); response_details->action_token_ = std::vector<uint8_t>{'t', 'o', 'k', 'e', 'n'}; - manager_->OnInitiatePaymentResponseReceived( + pix_manager_->OnInitiatePaymentResponseReceived( autofill::payments::PaymentsAutofillClient::PaymentsRpcResult::kSuccess, std::move(response_details)); @@ -715,10 +702,10 @@ // Test that if the user is logged out, purchase action is not invoked. Instead, // an error message is shown. -TEST_F(FacilitatedPaymentsManagerTest, +TEST_F(PixManagerTest, OnInitiatePaymentResponseReceived_LoggedOutProfile_ErrorScreenShown) { base::HistogramTester histogram_tester; - manager_->SendInitiatePaymentRequest(); + pix_manager_->SendInitiatePaymentRequest(); ON_CALL(*client_, GetCoreAccountInfo) .WillByDefault(testing::Return(CoreAccountInfo())); @@ -730,7 +717,7 @@ std::make_unique<FacilitatedPaymentsInitiatePaymentResponseDetails>(); response_details->action_token_ = std::vector<uint8_t>{'t', 'o', 'k', 'e', 'n'}; - manager_->OnInitiatePaymentResponseReceived( + pix_manager_->OnInitiatePaymentResponseReceived( autofill::payments::PaymentsAutofillClient::PaymentsRpcResult::kSuccess, std::move(response_details)); @@ -746,10 +733,10 @@ // Test that the puchase action is invoked after receiving a success response // from the `FacilitatedPaymentsNetworkInterface::InitiatePayment` call. -TEST_F(FacilitatedPaymentsManagerTest, +TEST_F(PixManagerTest, OnInitiatePaymentResponseReceived_InvokePurchaseActionTriggered) { base::HistogramTester histogram_tester; - manager_->SendInitiatePaymentRequest(); + pix_manager_->SendInitiatePaymentRequest(); ON_CALL(*client_, GetCoreAccountInfo) .WillByDefault(testing::Return(CreateLoggedInAccountInfo())); @@ -760,7 +747,7 @@ std::make_unique<FacilitatedPaymentsInitiatePaymentResponseDetails>(); response_details->action_token_ = std::vector<uint8_t>{'t', 'o', 'k', 'e', 'n'}; - manager_->OnInitiatePaymentResponseReceived( + pix_manager_->OnInitiatePaymentResponseReceived( autofill::payments::PaymentsAutofillClient::PaymentsRpcResult::kSuccess, std::move(response_details)); @@ -773,18 +760,17 @@ // The `IsAvailable` async call is made after a valid Pix code has been // detected. This test verifies that the result and latency are logged after the // async call is completed. -TEST_F(FacilitatedPaymentsManagerTest, - LogApiAvailabilityCheckResultAndLatency) { +TEST_F(PixManagerTest, LogApiAvailabilityCheckResultAndLatency) { base::HistogramTester histogram_tester; payments_data_manager_->AddMaskedBankAccountForTest( CreatePixBankAccount(/*instrument_id=*/1)); EXPECT_CALL(GetApiClient(), IsAvailable(testing::_)); - manager_->OnPixCodeValidated(/*pix_code=*/std::string(), - base::TimeTicks::Now(), - /*is_pix_code_valid=*/true); + pix_manager_->OnPixCodeValidated(/*pix_code=*/std::string(), + base::TimeTicks::Now(), + /*is_pix_code_valid=*/true); FastForwardBy(base::Seconds(2)); - manager_->OnApiAvailabilityReceived(true); + pix_manager_->OnApiAvailabilityReceived(true); histogram_tester.ExpectUniqueSample( "FacilitatedPayments.Pix.IsApiAvailable.Success.Latency", @@ -795,11 +781,10 @@ // The `IsAvailable` async call is made after a valid Pix code has been // detected. This test verifies that if the api available result is false, the // PayflowExitedReason histogram is logged. -TEST_F(FacilitatedPaymentsManagerTest, - PayflowExitedReason_ApiClientNotAvailable) { +TEST_F(PixManagerTest, PayflowExitedReason_ApiClientNotAvailable) { base::HistogramTester histogram_tester; - manager_->OnApiAvailabilityReceived(false); + pix_manager_->OnApiAvailabilityReceived(false); histogram_tester.ExpectUniqueSample( "FacilitatedPayments.Pix.PayflowExitedReason", @@ -809,13 +794,12 @@ // Test that when Chrome fails to invoke purchase action, the error screen is // shown. -TEST_F(FacilitatedPaymentsManagerTest, - OnPurchaseActionResult_CouldNotInvoke_ErrorScreenShown) { +TEST_F(PixManagerTest, OnPurchaseActionResult_CouldNotInvoke_ErrorScreenShown) { base::HistogramTester histogram_tester; EXPECT_CALL(*client_, ShowErrorScreen); - manager_->OnPurchaseActionResult(PurchaseActionResult::kCouldNotInvoke); + pix_manager_->OnPurchaseActionResult(PurchaseActionResult::kCouldNotInvoke); histogram_tester.ExpectUniqueSample( "FacilitatedPayments.Pix.PayflowExitedReason", @@ -825,29 +809,28 @@ // Test that when Chrome is successful in invoking the purchase action, the UI // screen is dismissed. -TEST_F(FacilitatedPaymentsManagerTest, - OnPurchaseActionResult_ResultOk_UiScreenDismissed) { +TEST_F(PixManagerTest, OnPurchaseActionResult_ResultOk_UiScreenDismissed) { // `DismissPrompt` is called once when the purchase action result is - // received, and again when the test fixture destroys the `manager_`. + // received, and again when the test fixture destroys the `pix_manager_`. EXPECT_CALL(*client_, DismissPrompt).Times(2); - manager_->OnPurchaseActionResult(PurchaseActionResult::kResultOk); + pix_manager_->OnPurchaseActionResult(PurchaseActionResult::kResultOk); } // Test that when Chrome is successful in invoking the purchase action, the UI // screen is dismissed. -TEST_F(FacilitatedPaymentsManagerTest, +TEST_F(PixManagerTest, OnPurchaseActionResult_ResultCanceled_UiScreenDismissed) { // `DismissPrompt` is called once when the purchase action result is - // received, and again when the test fixture destroys the `manager_`. + // received, and again when the test fixture destroys the `pix_manager_`. EXPECT_CALL(*client_, DismissPrompt).Times(2); - manager_->OnPurchaseActionResult(PurchaseActionResult::kResultCanceled); + pix_manager_->OnPurchaseActionResult(PurchaseActionResult::kResultCanceled); } // Test that when an InitiatePurchaseAction request is sent, the attempt is // logged. -TEST_F(FacilitatedPaymentsManagerTest, LogInitiatePurchaseActionAttempt) { +TEST_F(PixManagerTest, LogInitiatePurchaseActionAttempt) { base::HistogramTester histogram_tester; ON_CALL(*client_, GetCoreAccountInfo) .WillByDefault(testing::Return(CreateLoggedInAccountInfo())); @@ -856,7 +839,7 @@ std::make_unique<FacilitatedPaymentsInitiatePaymentResponseDetails>(); response_details->action_token_ = std::vector<uint8_t>{'t', 'o', 'k', 'e', 'n'}; - manager_->OnInitiatePaymentResponseReceived( + pix_manager_->OnInitiatePaymentResponseReceived( autofill::payments::PaymentsAutofillClient::PaymentsRpcResult::kSuccess, std::move(response_details)); @@ -868,8 +851,7 @@ // Test that when an InitiatePurchaseAction response is received, the result and // latency of the invoke purchase action is logged. -TEST_F(FacilitatedPaymentsManagerTest, - LogInitiatePurchaseActionResultAndLatency) { +TEST_F(PixManagerTest, LogInitiatePurchaseActionResultAndLatency) { size_t index = 0; for (PurchaseActionResult result : {PurchaseActionResult::kResultOk, PurchaseActionResult::kCouldNotInvoke, @@ -882,12 +864,12 @@ std::make_unique<FacilitatedPaymentsInitiatePaymentResponseDetails>(); response_details->action_token_ = std::vector<uint8_t>{'t', 'o', 'k', 'e', 'n'}; - manager_->OnInitiatePaymentResponseReceived( + pix_manager_->OnInitiatePaymentResponseReceived( autofill::payments::PaymentsAutofillClient::PaymentsRpcResult::kSuccess, std::move(response_details)); FastForwardBy(base::Seconds(2)); - manager_->OnPurchaseActionResult(result); + pix_manager_->OnPurchaseActionResult(result); std::string result_string; switch (result) { @@ -919,47 +901,45 @@ // Verify that the API client is initialized lazily, so it does not take up // space in memory unless it's being used. -TEST_F(FacilitatedPaymentsManagerTest, ApiClientInitializedLazily) { +TEST_F(PixManagerTest, ApiClientInitializedLazily) { payments_data_manager_->AddMaskedBankAccountForTest( CreatePixBankAccount(/*instrument_id=*/1)); - EXPECT_EQ(nullptr, manager_->api_client_.get()); + EXPECT_EQ(nullptr, pix_manager_->api_client_.get()); - manager_->OnPixCodeValidated(/*pix_code=*/std::string(), - base::TimeTicks::Now(), - /*is_pix_code_valid=*/true); + pix_manager_->OnPixCodeValidated(/*pix_code=*/std::string(), + base::TimeTicks::Now(), + /*is_pix_code_valid=*/true); - EXPECT_NE(nullptr, manager_->api_client_.get()); + EXPECT_NE(nullptr, pix_manager_->api_client_.get()); } // Verify that a failure to lazily initialize the API client is not fatal. -TEST_F(FacilitatedPaymentsManagerTest, - HandlesFailureToLazilyInitializeApiClient) { +TEST_F(PixManagerTest, HandlesFailureToLazilyInitializeApiClient) { payments_data_manager_->AddMaskedBankAccountForTest( CreatePixBankAccount(/*instrument_id=*/1)); - manager_->api_client_creator_.Reset(); + pix_manager_->api_client_creator_.Reset(); - EXPECT_EQ(nullptr, manager_->api_client_.get()); + EXPECT_EQ(nullptr, pix_manager_->api_client_.get()); - manager_->OnPixCodeValidated(/*pix_code=*/std::string(), - base::TimeTicks::Now(), - /*is_pix_code_valid=*/true); + pix_manager_->OnPixCodeValidated(/*pix_code=*/std::string(), + base::TimeTicks::Now(), + /*is_pix_code_valid=*/true); - EXPECT_EQ(nullptr, manager_->api_client_.get()); + EXPECT_EQ(nullptr, pix_manager_->api_client_.get()); } // Test class for devices being used in the landscape mode. -class FacilitatedPaymentsManagerTestInLandscapeMode - : public FacilitatedPaymentsManagerTest, - public testing::WithParamInterface<bool> { +class PixManagerTestInLandscapeMode : public PixManagerTest, + public testing::WithParamInterface<bool> { public: - FacilitatedPaymentsManagerTestInLandscapeMode() { + PixManagerTestInLandscapeMode() { scoped_feature_list_.InitWithFeatureState(kEnablePixPaymentsInLandscapeMode, GetParam()); } void SetUp() override { - FacilitatedPaymentsManagerTest::SetUp(); + PixManagerTest::SetUp(); ON_CALL(*client_, IsInLandscapeMode).WillByDefault(testing::Return(true)); } @@ -969,12 +949,9 @@ base::test::ScopedFeatureList scoped_feature_list_; }; -INSTANTIATE_TEST_SUITE_P(All, - FacilitatedPaymentsManagerTestInLandscapeMode, - testing::Bool()); +INSTANTIATE_TEST_SUITE_P(All, PixManagerTestInLandscapeMode, testing::Bool()); -TEST_P(FacilitatedPaymentsManagerTestInLandscapeMode, - PixPayflowBlockedWhenFlagDisabled) { +TEST_P(PixManagerTestInLandscapeMode, PixPayflowBlockedWhenFlagDisabled) { payments_data_manager_->AddMaskedBankAccountForTest( CreatePixBankAccount(/*instrument_id=*/1)); @@ -984,20 +961,20 @@ EXPECT_CALL(GetApiClient(), IsAvailable(testing::_)) .Times(IsPaymentEnabledInLandscapeMode() ? 1 : 0); - manager_->OnPixCodeValidated(/*pix_code=*/std::string(), - base::TimeTicks::Now(), - /*is_pix_code_valid=*/true); + pix_manager_->OnPixCodeValidated(/*pix_code=*/std::string(), + base::TimeTicks::Now(), + /*is_pix_code_valid=*/true); } -TEST_P(FacilitatedPaymentsManagerTestInLandscapeMode, +TEST_P(PixManagerTestInLandscapeMode, PayflowExitedReason_LandscapeScreenOrientation) { base::HistogramTester histogram_tester; payments_data_manager_->AddMaskedBankAccountForTest( CreatePixBankAccount(/*instrument_id=*/1)); - manager_->OnPixCodeValidated(/*pix_code=*/std::string(), - base::TimeTicks::Now(), - /*is_pix_code_valid=*/true); + pix_manager_->OnPixCodeValidated(/*pix_code=*/std::string(), + base::TimeTicks::Now(), + /*is_pix_code_valid=*/true); // In landscape mode, if the `EnablePixPaymentsInLandscapeMode` flag is // disabled, Pix payment is not offered, and a histogram should be logged. @@ -1007,9 +984,9 @@ /*expected_bucket_count=*/IsPaymentEnabledInLandscapeMode() ? 0 : 1); } -TEST_F(FacilitatedPaymentsManagerTest, ShowPixPaymentPrompt) { +TEST_F(PixManagerTest, ShowPixPaymentPrompt) { // Verify the default UI state. - EXPECT_EQ(manager_->ui_state_, UiState::kHidden); + EXPECT_EQ(pix_manager_->ui_state_, UiState::kHidden); // Verify that when the feature wants to show the payment prompt, it asks the // client. @@ -1017,66 +994,68 @@ const std::vector<autofill::BankAccount> bank_accounts = { autofill::test::CreatePixBankAccount(100L)}; - manager_->ShowPixPaymentPrompt(std::move(bank_accounts), base::DoNothing()); + pix_manager_->ShowPixPaymentPrompt(std::move(bank_accounts), + base::DoNothing()); // Verify that the UI state is updated. - EXPECT_EQ(manager_->ui_state_, UiState::kFopSelector); + EXPECT_EQ(pix_manager_->ui_state_, UiState::kFopSelector); } -TEST_F(FacilitatedPaymentsManagerTest, ShowProgressScreen) { +TEST_F(PixManagerTest, ShowProgressScreen) { // Verify the default UI state. - EXPECT_EQ(manager_->ui_state_, UiState::kHidden); + EXPECT_EQ(pix_manager_->ui_state_, UiState::kHidden); // Verify that when the feature wants to show the progress screen, it asks the // client. EXPECT_CALL(*client_, ShowProgressScreen); - manager_->ShowProgressScreen(); + pix_manager_->ShowProgressScreen(); // Verify that the UI state is updated. - EXPECT_EQ(manager_->ui_state_, UiState::kProgressScreen); + EXPECT_EQ(pix_manager_->ui_state_, UiState::kProgressScreen); } -TEST_F(FacilitatedPaymentsManagerTest, ShowErrorScreen) { +TEST_F(PixManagerTest, ShowErrorScreen) { // Verify the default UI state. - EXPECT_EQ(manager_->ui_state_, UiState::kHidden); + EXPECT_EQ(pix_manager_->ui_state_, UiState::kHidden); // Verify that when the feature wants to show the error screen, it asks the // client. EXPECT_CALL(*client_, ShowErrorScreen); - manager_->ShowErrorScreen(); + pix_manager_->ShowErrorScreen(); // Verify that the UI state is updated. - EXPECT_EQ(manager_->ui_state_, UiState::kErrorScreen); + EXPECT_EQ(pix_manager_->ui_state_, UiState::kErrorScreen); } -TEST_F(FacilitatedPaymentsManagerTest, DismissPrompt) { +TEST_F(PixManagerTest, DismissPrompt) { // Verify that when the feature wants to dismiss the UI screen, it asks the // client. The second call is from test teardown. EXPECT_CALL(*client_, DismissPrompt).Times(2); - manager_->DismissPrompt(); + pix_manager_->DismissPrompt(); // Verify that the UI state is updated. - EXPECT_EQ(manager_->ui_state_, UiState::kHidden); + EXPECT_EQ(pix_manager_->ui_state_, UiState::kHidden); } // Test that when the Pix FOP selector is shown, related Pix metrics are logged. -TEST_F(FacilitatedPaymentsManagerTest, PixFopSelectorShown_HistogramsLogged) { +TEST_F(PixManagerTest, PixFopSelectorShown_HistogramsLogged) { base::HistogramTester histogram_tester; // Simulate Pix code being copied. The latency is computed from this point. - manager_->OnPixCodeCopiedToClipboard(GURL("https://example.com/"), - std::string(), - ukm::UkmRecorder::GetNewSourceID()); + pix_manager_->OnPixCodeCopiedToClipboard(GURL("https://example.com/"), + std::string(), + ukm::UkmRecorder::GetNewSourceID()); // Fully mocked time, does not advance by itself. FastForwardBy(base::Seconds(2)); // Simulate that the FOP selector was shown successfully. std::vector<autofill::BankAccount> bank_accounts = { autofill::test::CreatePixBankAccount(100L)}; - manager_->ShowPixPaymentPrompt(std::move(bank_accounts), base::DoNothing()); - manager_->OnUiEvent(UiEvent::kNewScreenShown); + pix_manager_->ShowPixPaymentPrompt(std::move(bank_accounts), + base::DoNothing()); + pix_manager_->OnUiEvent(UiEvent::kNewScreenShown); // Verify that when the Pix FOP selector is shown, related metrics are // logged. @@ -1091,10 +1070,9 @@ EXPECT_EQ(ukm_entries[0].metrics.at("Shown"), true); } -TEST_F(FacilitatedPaymentsManagerTest, - ProgressScreenAutoDismissedAfterInvokingPurchaseAction) { +TEST_F(PixManagerTest, ProgressScreenAutoDismissedAfterInvokingPurchaseAction) { // When purchase action is invoked, the progress screen would be showing. - manager_->ShowProgressScreen(); + pix_manager_->ShowProgressScreen(); ON_CALL(*client_, GetCoreAccountInfo) .WillByDefault(testing::Return(CreateLoggedInAccountInfo())); @@ -1104,24 +1082,23 @@ std::make_unique<FacilitatedPaymentsInitiatePaymentResponseDetails>(); response_details->action_token_ = std::vector<uint8_t>{'t', 'o', 'k', 'e', 'n'}; - manager_->OnInitiatePaymentResponseReceived( + pix_manager_->OnInitiatePaymentResponseReceived( autofill::payments::PaymentsAutofillClient::PaymentsRpcResult::kSuccess, std::move(response_details)); // The progress screen is persisted for a short duration after invoking the // purchase action for a smooth transition to the platform screen. - EXPECT_EQ(manager_->ui_state_, UiState::kProgressScreen); + EXPECT_EQ(pix_manager_->ui_state_, UiState::kProgressScreen); FastForwardBy(base::Seconds(1)); // The progress screen should be dismissed after a short delay. - EXPECT_EQ(manager_->ui_state_, UiState::kHidden); + EXPECT_EQ(pix_manager_->ui_state_, UiState::kHidden); } -TEST_F(FacilitatedPaymentsManagerTest, - ErrorScreenNotAutoDismissedAfterInvokingPurchaseAction) { +TEST_F(PixManagerTest, ErrorScreenNotAutoDismissedAfterInvokingPurchaseAction) { // When purchase action is invoked, the progress screen would be showing. - manager_->ShowProgressScreen(); + pix_manager_->ShowProgressScreen(); ON_CALL(*client_, GetCoreAccountInfo) .WillByDefault(testing::Return(CreateLoggedInAccountInfo())); @@ -1131,42 +1108,41 @@ std::make_unique<FacilitatedPaymentsInitiatePaymentResponseDetails>(); response_details->action_token_ = std::vector<uint8_t>{'t', 'o', 'k', 'e', 'n'}; - manager_->OnInitiatePaymentResponseReceived( + pix_manager_->OnInitiatePaymentResponseReceived( autofill::payments::PaymentsAutofillClient::PaymentsRpcResult::kSuccess, std::move(response_details)); // If the purchase action could not be invoked, the `PurchaseActionResult` is // returned immediately. The error screen is shown. - manager_->OnPurchaseActionResult(PurchaseActionResult::kCouldNotInvoke); + pix_manager_->OnPurchaseActionResult(PurchaseActionResult::kCouldNotInvoke); FastForwardBy(base::Seconds(1)); // The error screen shouldn't be auto-dismissed. - EXPECT_EQ(manager_->ui_state_, UiState::kErrorScreen); + EXPECT_EQ(pix_manager_->ui_state_, UiState::kErrorScreen); } -class FacilitatedPaymentsManagerTestForUiScreens - : public FacilitatedPaymentsManagerTest, - public testing::WithParamInterface<UiState> { +class PixManagerTestForUiScreens : public PixManagerTest, + public testing::WithParamInterface<UiState> { public: void SetUp() override { - FacilitatedPaymentsManagerTest::SetUp(); + PixManagerTest::SetUp(); // Default state. - EXPECT_EQ(manager_->ui_state_, UiState::kHidden); + EXPECT_EQ(pix_manager_->ui_state_, UiState::kHidden); switch (GetParam()) { case UiState::kFopSelector: { const std::vector<autofill::BankAccount> bank_accounts = { autofill::test::CreatePixBankAccount(100L)}; - manager_->ShowPixPaymentPrompt(std::move(bank_accounts), - base::DoNothing()); + pix_manager_->ShowPixPaymentPrompt(std::move(bank_accounts), + base::DoNothing()); break; } case UiState::kProgressScreen: - manager_->ShowProgressScreen(); + pix_manager_->ShowProgressScreen(); break; case UiState::kErrorScreen: - manager_->ShowErrorScreen(); + pix_manager_->ShowErrorScreen(); break; case UiState::kHidden: NOTREACHED(); @@ -1176,22 +1152,22 @@ UiState ui_state() { return GetParam(); } }; -INSTANTIATE_TEST_SUITE_P(FacilitatedPaymentsManagerTest, - FacilitatedPaymentsManagerTestForUiScreens, +INSTANTIATE_TEST_SUITE_P(PixManagerTest, + PixManagerTestForUiScreens, testing::Values(UiState::kFopSelector, UiState::kProgressScreen, UiState::kErrorScreen)); // Test that when a new screen is shown, UI state reflects the current UI being // shown. -TEST_P(FacilitatedPaymentsManagerTestForUiScreens, NewScreenShown) { +TEST_P(PixManagerTestForUiScreens, NewScreenShown) { base::HistogramTester histogram_tester; // Simulate new screen was shown successfully. - manager_->OnUiEvent(UiEvent::kNewScreenShown); + pix_manager_->OnUiEvent(UiEvent::kNewScreenShown); // Verify feature has updated the UI state. - EXPECT_EQ(manager_->ui_state_, ui_state()); + EXPECT_EQ(pix_manager_->ui_state_, ui_state()); // Verify that the histogram is logged. histogram_tester.ExpectUniqueSample("FacilitatedPayments.Pix.UiScreenShown", /*sample=*/ui_state(), @@ -1206,14 +1182,14 @@ } // Test that when a new screen could not be shown, UI state is updated. -TEST_P(FacilitatedPaymentsManagerTestForUiScreens, NewScreenCouldNotBeShown) { +TEST_P(PixManagerTestForUiScreens, NewScreenCouldNotBeShown) { base::HistogramTester histogram_tester; // Simulate new screen could not be shown. - manager_->OnUiEvent(UiEvent::kScreenClosedNotByUser); + pix_manager_->OnUiEvent(UiEvent::kScreenClosedNotByUser); // Verify that the UI state is hidden. - EXPECT_EQ(manager_->ui_state_, UiState::kHidden); + EXPECT_EQ(pix_manager_->ui_state_, UiState::kHidden); // Verify that the payflow exited histogram is logged. histogram_tester.ExpectUniqueSample( "FacilitatedPayments.Pix.PayflowExitedReason", @@ -1223,16 +1199,16 @@ // Test that when the UI screen is closed, but it was not due to a user action, // the feature updates the UI state. -TEST_P(FacilitatedPaymentsManagerTestForUiScreens, ScreenClosedNotByUser) { +TEST_P(PixManagerTestForUiScreens, ScreenClosedNotByUser) { base::HistogramTester histogram_tester; // Simulate new screen was shown successfully. - manager_->OnUiEvent(UiEvent::kNewScreenShown); + pix_manager_->OnUiEvent(UiEvent::kNewScreenShown); // Simulate UI screen was closed, but it was not due to a user action. - manager_->OnUiEvent(UiEvent::kScreenClosedNotByUser); + pix_manager_->OnUiEvent(UiEvent::kScreenClosedNotByUser); // Verify that the UI state is hidden. - EXPECT_EQ(manager_->ui_state_, UiState::kHidden); + EXPECT_EQ(pix_manager_->ui_state_, UiState::kHidden); // Verify that the payflow exited histogram is logged. histogram_tester.ExpectUniqueSample( "FacilitatedPayments.Pix.PayflowExitedReason", @@ -1242,16 +1218,16 @@ // Test that when the UI screen is closed by the user, the feature updates the // UI state. -TEST_P(FacilitatedPaymentsManagerTestForUiScreens, ScreenClosedByUser) { +TEST_P(PixManagerTestForUiScreens, ScreenClosedByUser) { base::HistogramTester histogram_tester; // Simulate new screen was shown successfully. - manager_->OnUiEvent(UiEvent::kNewScreenShown); + pix_manager_->OnUiEvent(UiEvent::kNewScreenShown); // Simulate UI screen was closed by the user. - manager_->OnUiEvent(UiEvent::kScreenClosedByUser); + pix_manager_->OnUiEvent(UiEvent::kScreenClosedByUser); // Verify that the UI state is hidden. - EXPECT_EQ(manager_->ui_state_, UiState::kHidden); + EXPECT_EQ(pix_manager_->ui_state_, UiState::kHidden); // Verify that the payflow exited histogram is logged. histogram_tester.ExpectUniqueSample( "FacilitatedPayments.Pix.PayflowExitedReason",
diff --git a/components/feedback/feedback_constants.h b/components/feedback/feedback_constants.h index bd0a8b8..b8ef9cd 100644 --- a/components/feedback/feedback_constants.h +++ b/components/feedback/feedback_constants.h
@@ -20,6 +20,7 @@ inline constexpr int kOrcaFeedbackProductId = 5314436; inline constexpr int kMahiFeedbackProductId = 5329991; inline constexpr int kLobsterFeedbackProductId = 5342213; +inline constexpr int kScannerFeedbackProductId = 5349584; } // namespace feedback
diff --git a/components/history_embeddings/history_embeddings_service.cc b/components/history_embeddings/history_embeddings_service.cc index 97d6d6a5..82344dc 100644 --- a/components/history_embeddings/history_embeddings_service.cc +++ b/components/history_embeddings/history_embeddings_service.cc
@@ -413,7 +413,7 @@ std::vector<Embedding> query_embeddings, passage_embeddings::ComputeEmbeddingsStatus status) { bool succeeded = - status == passage_embeddings::ComputeEmbeddingsStatus::KSuccess; + status == passage_embeddings::ComputeEmbeddingsStatus::kSuccess; base::UmaHistogramBoolean("History.Embeddings.QueryEmbeddingSucceeded", succeeded);
diff --git a/components/history_embeddings/history_embeddings_service_unittest.cc b/components/history_embeddings/history_embeddings_service_unittest.cc index d4cc186..75a87af5 100644 --- a/components/history_embeddings/history_embeddings_service_unittest.cc +++ b/components/history_embeddings/history_embeddings_service_unittest.cc
@@ -240,15 +240,15 @@ Embedding(std::vector<float>(768, 1.0f)), Embedding(std::vector<float>(768, 1.0f))}; OnPassagesEmbeddingsComputed(url_passages, passages, passages_embeddings, - ComputeEmbeddingsStatus::KSuccess); + ComputeEmbeddingsStatus::kSuccess); url_passages.url_id = 2; url_passages.visit_id = 2; OnPassagesEmbeddingsComputed(url_passages, passages, passages_embeddings, - ComputeEmbeddingsStatus::KSuccess); + ComputeEmbeddingsStatus::kSuccess); url_passages.url_id = 3; url_passages.visit_id = 3; OnPassagesEmbeddingsComputed(url_passages, passages, passages_embeddings, - ComputeEmbeddingsStatus::KSuccess); + ComputeEmbeddingsStatus::kSuccess); // Verify that we find all three passages initially. EXPECT_EQ(CountEmbeddingsRows(), 3U); @@ -493,17 +493,17 @@ {"test passage 1", "test passage 2"}, {Embedding(std::vector<float>(768, 1.0f)), Embedding(std::vector<float>(768, 1.0f))}, - ComputeEmbeddingsStatus::KSuccess); + ComputeEmbeddingsStatus::kSuccess); OnPassagesEmbeddingsComputed(UrlData(2, 2, base::Time::Now()), {"test passage 3", "test passage 4"}, {Embedding(std::vector<float>(768, -1.0f)), Embedding(std::vector<float>(768, -1.0f))}, - ComputeEmbeddingsStatus::KSuccess); + ComputeEmbeddingsStatus::kSuccess); OnPassagesEmbeddingsComputed(UrlData(3, 3, base::Time::Now()), {"test passage 5", "test passage 6"}, {Embedding(std::vector<float>(768, 1.0f)), Embedding(std::vector<float>(768, 1.0f))}, - ComputeEmbeddingsStatus::KSuccess); + ComputeEmbeddingsStatus::kSuccess); // Search base::test::TestFuture<SearchResult> future; @@ -559,7 +559,7 @@ Embedding(std::vector<float>(768, 1.0f)), Embedding(std::vector<float>(768, 1.0f)), Embedding(std::vector<float>(768, 1.0f))}, - ComputeEmbeddingsStatus::KSuccess); + ComputeEmbeddingsStatus::kSuccess); OverrideVisibilityScoresForTesting({ {"query without terms", 0.99}, {"query with inexact spe'cial in the middle", 0.99}, @@ -711,7 +711,7 @@ {"test passage 1", "test passage 2"}, {Embedding(std::vector<float>(768, 1.0f)), Embedding(std::vector<float>(768, 1.0f))}, - ComputeEmbeddingsStatus::KSuccess); + ComputeEmbeddingsStatus::kSuccess); { base::test::TestFuture<SearchResult> future; service_->Search(/*previous_search_result=*/nullptr, "boosted test query", @@ -760,7 +760,7 @@ {"test passage one", "test passage two"}, {Embedding(std::vector<float>(768, 1.0f)), Embedding(std::vector<float>(768, 1.0f))}, - ComputeEmbeddingsStatus::KSuccess); + ComputeEmbeddingsStatus::kSuccess); { set_ratio(0.3f); base::test::TestFuture<SearchResult> future; @@ -849,17 +849,17 @@ {"test passage 1", "test passage 2"}, {Embedding(std::vector<float>(768, 1.0f)), Embedding(std::vector<float>(768, 1.0f))}, - ComputeEmbeddingsStatus::KSuccess); + ComputeEmbeddingsStatus::kSuccess); OnPassagesEmbeddingsComputed(UrlData(2, 2, base::Time::Now()), {"test passage 1", "test passage 2"}, {Embedding(std::vector<float>(768, 0.9f)), Embedding(std::vector<float>(768, 0.9f))}, - ComputeEmbeddingsStatus::KSuccess); + ComputeEmbeddingsStatus::kSuccess); OnPassagesEmbeddingsComputed(UrlData(3, 3, base::Time::Now()), {"test passage 1", "test passage 2"}, {Embedding(std::vector<float>(768, 0.9f)), Embedding(std::vector<float>(768, 0.9f))}, - ComputeEmbeddingsStatus::KSuccess); + ComputeEmbeddingsStatus::kSuccess); base::test::TestFuture<SearchResult> future; service_->Search(/*previous_search_result=*/nullptr, "boosted test query", {}, @@ -886,7 +886,7 @@ {"test passage 1", "test passage 2"}, {Embedding(std::vector<float>(768, 1.0f)), Embedding(std::vector<float>(768, 1.0f))}, - ComputeEmbeddingsStatus::KSuccess); + ComputeEmbeddingsStatus::kSuccess); { base::test::TestFuture<std::optional<UrlData>> future; service_->GetUrlData(1, future.GetCallback()); @@ -921,22 +921,22 @@ {"test passage 1", "test passage 2"}, {Embedding(std::vector<float>(768, 1.0f)), Embedding(std::vector<float>(768, 1.0f))}, - ComputeEmbeddingsStatus::KSuccess); + ComputeEmbeddingsStatus::kSuccess); OnPassagesEmbeddingsComputed(UrlData(2, 2, now + base::Hours(1)), {"test passage 3", "test passage 4"}, {Embedding(std::vector<float>(768, 1.0f)), Embedding(std::vector<float>(768, 1.0f))}, - ComputeEmbeddingsStatus::KSuccess); + ComputeEmbeddingsStatus::kSuccess); OnPassagesEmbeddingsComputed(UrlData(3, 3, now + base::Minutes(1)), {"test passage 5", "test passage 6"}, {Embedding(std::vector<float>(768, 1.0f)), Embedding(std::vector<float>(768, 1.0f))}, - ComputeEmbeddingsStatus::KSuccess); + ComputeEmbeddingsStatus::kSuccess); OnPassagesEmbeddingsComputed(UrlData(4, 4, now), {"test passage 7", "test passage 8"}, {Embedding(std::vector<float>(768, 1.0f)), Embedding(std::vector<float>(768, 1.0f))}, - ComputeEmbeddingsStatus::KSuccess); + ComputeEmbeddingsStatus::kSuccess); { base::test::TestFuture<std::vector<UrlData>> future; service_->GetUrlDataInTimeRange(now, now + base::Days(1), 8, 0, @@ -1060,12 +1060,12 @@ {"test passage 1", "test passage 2"}, {Embedding(std::vector<float>(768, 1.0f)), Embedding(std::vector<float>(768, 1.0f))}, - ComputeEmbeddingsStatus::KSuccess); + ComputeEmbeddingsStatus::kSuccess); OnPassagesEmbeddingsComputed(UrlData(2, 2, base::Time::Now()), {"test passage 1", "test passage 2"}, {Embedding(std::vector<float>(768, 0.9f)), Embedding(std::vector<float>(768, 0.9f))}, - ComputeEmbeddingsStatus::KSuccess); + ComputeEmbeddingsStatus::kSuccess); base::test::TestFuture<SearchResult> future; OverrideVisibilityScoresForTesting({{"my query", 0.99}});
diff --git a/components/history_embeddings/ml_embedder_unittest.cc b/components/history_embeddings/ml_embedder_unittest.cc index c0e4420..1ac9992 100644 --- a/components/history_embeddings/ml_embedder_unittest.cc +++ b/components/history_embeddings/ml_embedder_unittest.cc
@@ -336,7 +336,7 @@ PassageKind::PAGE_VISIT_PASSAGE, {"foo", "bar"}, future.GetCallback()); auto [passages, embeddings, status] = future.Get(); - EXPECT_EQ(status, ComputeEmbeddingsStatus::KSuccess); + EXPECT_EQ(status, ComputeEmbeddingsStatus::kSuccess); EXPECT_EQ(passages[0], "foo"); EXPECT_EQ(passages[1], "bar"); EXPECT_EQ(embeddings[0].Dimensions(), kEmbeddingsModelOutputSize); @@ -353,7 +353,7 @@ PassageKind::PAGE_VISIT_PASSAGE, {"foo", "bar"}, future.GetCallback()); auto [passages, embeddings, status] = future.Get(); - EXPECT_EQ(status, ComputeEmbeddingsStatus::KSuccess); + EXPECT_EQ(status, ComputeEmbeddingsStatus::kSuccess); EXPECT_EQ(passages[0], "foo"); EXPECT_EQ(passages[1], "bar"); EXPECT_EQ(embeddings[0].Dimensions(), kEmbeddingsModelOutputSize); @@ -370,7 +370,7 @@ PassageKind::PAGE_VISIT_PASSAGE, {"foo", "bar"}, future.GetCallback()); auto [passages, embeddings, status] = future.Get(); - EXPECT_EQ(status, ComputeEmbeddingsStatus::KSuccess); + EXPECT_EQ(status, ComputeEmbeddingsStatus::kSuccess); EXPECT_EQ(passages[0], "foo"); EXPECT_EQ(passages[1], "bar"); EXPECT_EQ(embeddings[0].Dimensions(), kEmbeddingsModelOutputSize); @@ -394,7 +394,7 @@ {"foo", "bar"}, future.GetCallback()); auto [passages, embeddings, status] = future.Get(); - EXPECT_EQ(status, ComputeEmbeddingsStatus::KModelUnavailable); + EXPECT_EQ(status, ComputeEmbeddingsStatus::kModelUnavailable); EXPECT_TRUE(passages.empty()); EXPECT_TRUE(embeddings.empty()); histogram_tester_.ExpectTotalCount(kModelInfoMetricName, 1);
diff --git a/components/history_embeddings/mock_embedder.cc b/components/history_embeddings/mock_embedder.cc index 23e2d8e2..a6c27dee 100644 --- a/components/history_embeddings/mock_embedder.cc +++ b/components/history_embeddings/mock_embedder.cc
@@ -41,7 +41,7 @@ FROM_HERE, base::BindOnce(std::move(callback), std::move(passages), ComputeEmbeddingsForPassages(passages), - passage_embeddings::ComputeEmbeddingsStatus::KSuccess)); + passage_embeddings::ComputeEmbeddingsStatus::kSuccess)); } void MockEmbedder::SetOnEmbedderReady(OnEmbedderReadyCallback callback) {
diff --git a/components/history_embeddings/scheduling_embedder.cc b/components/history_embeddings/scheduling_embedder.cc index 83406ef..cc189c4 100644 --- a/components/history_embeddings/scheduling_embedder.cc +++ b/components/history_embeddings/scheduling_embedder.cc
@@ -45,7 +45,7 @@ if (passages.empty()) { std::move(callback).Run( /*passages=*/{}, /*embeddings=*/{}, - passage_embeddings::ComputeEmbeddingsStatus::KSuccess); + passage_embeddings::ComputeEmbeddingsStatus::kSuccess); return; } @@ -83,7 +83,7 @@ VLOG(2) << "Dropped pending query '" << jobs_.front().passages[0] << "'. Next query: '" << jobs_.at(1).passages[0] << "'"; std::move(jobs_.front().callback) - .Run({}, {}, passage_embeddings::ComputeEmbeddingsStatus::KSkipped); + .Run({}, {}, passage_embeddings::ComputeEmbeddingsStatus::kSkipped); jobs_.pop_front(); } }
diff --git a/components/management/resources/BUILD.gn b/components/management/resources/BUILD.gn new file mode 100644 index 0000000..c50b6d9 --- /dev/null +++ b/components/management/resources/BUILD.gn
@@ -0,0 +1,19 @@ +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//ui/webui/resources/tools/build_webui.gni") + +build_webui("build") { + grd_prefix = "management" + + static_files = [ + "images/enterprise_icon.svg", + "management.css", + "management.html", + ] + + non_web_component_files = [ "management.js" ] + + grit_output_dir = "$root_gen_dir/components" +}
diff --git a/components/messages/android/internal/java/src/org/chromium/components/messages/ScopeChangeController.java b/components/messages/android/internal/java/src/org/chromium/components/messages/ScopeChangeController.java index 3a0a06b..1df37ba 100644 --- a/components/messages/android/internal/java/src/org/chromium/components/messages/ScopeChangeController.java +++ b/components/messages/android/internal/java/src/org/chromium/components/messages/ScopeChangeController.java
@@ -134,9 +134,7 @@ } @Override - public void destroy() { - super.destroy(); - // #destroy will remove the observers. + public void onDestroy() { mDelegate.onScopeChange( new MessageScopeChange(mScopeKey.scopeType, mScopeKey, ChangeType.DESTROY)); mIsActive = false;
diff --git a/components/messages/android/internal/java/src/org/chromium/components/messages/ScopeChangeControllerTest.java b/components/messages/android/internal/java/src/org/chromium/components/messages/ScopeChangeControllerTest.java index 40a6ad9..2f47f84 100644 --- a/components/messages/android/internal/java/src/org/chromium/components/messages/ScopeChangeControllerTest.java +++ b/components/messages/android/internal/java/src/org/chromium/components/messages/ScopeChangeControllerTest.java
@@ -136,6 +136,31 @@ "Scope type should be destroy when navigated to another page", ChangeType.DESTROY, captor.getValue().changeType); + } + + @Test + @SmallTest + public void testScopeChange_WindowChanged() { + ScopeChangeController.Delegate delegate = + Mockito.mock(ScopeChangeController.Delegate.class); + ScopeChangeController controller = new ScopeChangeController(delegate); + + MockWebContents webContents = mock(MockWebContents.class); + + int expectedOnScopeChangeCalls = 0; + ScopeKey key = new ScopeKey(MessageScopeType.NAVIGATION, webContents); + controller.firstMessageEnqueued(key); + + final ArgumentCaptor<WebContentsObserver> runnableCaptor = + ArgumentCaptor.forClass(WebContentsObserver.class); + verify(webContents).addObserver(runnableCaptor.capture()); + + WebContentsObserver observer = runnableCaptor.getValue(); + + // Default visibility of web contents is invisible. + expectedOnScopeChangeCalls++; + ArgumentCaptor<MessageScopeChange> captor = + ArgumentCaptor.forClass(MessageScopeChange.class); observer.onTopLevelNativeWindowChanged(null); expectedOnScopeChangeCalls++; @@ -301,20 +326,6 @@ "Scope type should be destroy when navigated to another domain", ChangeType.DESTROY, captor.getValue().changeType); - - observer.onTopLevelNativeWindowChanged(null); - expectedOnScopeChangeCalls++; - verify( - delegate, - times(expectedOnScopeChangeCalls) - .description( - "Delegate should be called when top level native window" - + " changes")) - .onScopeChange(captor.capture()); - Assert.assertEquals( - "Scope type should be destroy when top level native window changes", - ChangeType.DESTROY, - captor.getValue().changeType); } private NavigationHandle createNavigationHandle(
diff --git a/components/no_state_prefetch/browser/no_state_prefetch_contents.cc b/components/no_state_prefetch/browser/no_state_prefetch_contents.cc index 0aff9a64..3b485b0b 100644 --- a/components/no_state_prefetch/browser/no_state_prefetch_contents.cc +++ b/components/no_state_prefetch/browser/no_state_prefetch_contents.cc
@@ -72,8 +72,9 @@ void SetPreloadingTriggeringOutcome( content::PreloadingAttempt* attempt, content::PreloadingTriggeringOutcome outcome) { - if (!attempt) + if (!attempt) { return; + } attempt->SetTriggeringOutcome(outcome); } @@ -148,8 +149,9 @@ RenderFrameHost* render_frame_host) override { auto* client = paint_preview::PaintPreviewClient::FromWebContents(web_contents); - if (client) + if (client) { client->CaptureSubframePaintPreview(guid, rect, render_frame_host); + } } private: @@ -205,8 +207,9 @@ } void NoStatePrefetchContents::SetPreloadingFailureReason(FinalStatus status) { - if (!attempt_) + if (!attempt_) { return; + } switch (status) { case FINAL_STATUS_USED: @@ -266,8 +269,9 @@ DCHECK(!no_state_prefetch_contents_); DCHECK_EQ(1U, alias_urls_.size()); - if (session_storage_namespace) + if (session_storage_namespace) { session_storage_namespace_id_ = session_storage_namespace->id(); + } bounds_ = bounds; DCHECK(load_start_time_.is_null()); @@ -358,8 +362,9 @@ void NoStatePrefetchContents::NotifyPrefetchStart() { DCHECK_EQ(FINAL_STATUS_UNKNOWN, final_status_); - for (Observer& observer : observer_list_) + for (Observer& observer : observer_list_) { observer.OnPrefetchStart(this); + } } void NoStatePrefetchContents::NotifyPrefetchStopLoading() { @@ -368,14 +373,16 @@ // later on or not. kReady doesn't mean it is a success. SetPreloadingTriggeringOutcome(attempt_.get(), content::PreloadingTriggeringOutcome::kReady); - for (Observer& observer : observer_list_) + for (Observer& observer : observer_list_) { observer.OnPrefetchStopLoading(this); + } } void NoStatePrefetchContents::NotifyPrefetchStop() { DCHECK_NE(FINAL_STATUS_UNKNOWN, final_status_); - for (Observer& observer : observer_list_) + for (Observer& observer : observer_list_) { observer.OnPrefetchStop(this); + } observer_list_.Clear(); } @@ -392,8 +399,9 @@ } bool NoStatePrefetchContents::AddAliasURL(const GURL& url) { - if (!CheckURL(url)) + if (!CheckURL(url)) { return false; + } alias_urls_.push_back(url); return true; @@ -447,8 +455,9 @@ return; } - if (!CheckURL(navigation_handle->GetURL())) + if (!CheckURL(navigation_handle->GetURL())) { return; + } // Usually, this event fires if the user clicks or enters a new URL. // Neither of these can happen in the case of an invisible prerender. @@ -460,8 +469,9 @@ void NoStatePrefetchContents::DidRedirectNavigation( content::NavigationHandle* navigation_handle) { - if (!navigation_handle->IsInPrimaryMainFrame()) + if (!navigation_handle->IsInPrimaryMainFrame()) { return; + } // If it's a redirect on the top-level resource, the name needs to be // remembered for future matching, and if it redirects to an https resource, @@ -472,8 +482,9 @@ void NoStatePrefetchContents::DidFinishLoad( content::RenderFrameHost* render_frame_host, const GURL& validated_url) { - if (render_frame_host->IsInPrimaryMainFrame()) + if (render_frame_host->IsInPrimaryMainFrame()) { has_finished_loading_ = true; + } } void NoStatePrefetchContents::DidFinishNavigation( @@ -499,8 +510,9 @@ // TODO(davidben): We do not correctly patch up history for renderer-initated // navigations which add history entries. http://crbug.com/305660. for (const auto& redirect : navigation_handle->GetRedirectChain()) { - if (!AddAliasURL(redirect)) + if (!AddAliasURL(redirect)) { return; + } } } @@ -527,22 +539,26 @@ void NoStatePrefetchContents::DestroyWhenUsingTooManyResources() { if (process_pid_ == base::kNullProcessId) { RenderFrameHost* rfh = GetPrimaryMainFrame(); - if (!rfh) + if (!rfh) { return; + } content::RenderProcessHost* rph = rfh->GetProcess(); - if (!rph) + if (!rph) { return; + } base::ProcessHandle handle = rph->GetProcess().Handle(); - if (handle == base::kNullProcessHandle) + if (handle == base::kNullProcessHandle) { return; + } process_pid_ = rph->GetProcess().Pid(); } - if (process_pid_ == base::kNullProcessId) + if (process_pid_ == base::kNullProcessId) { return; + } memory_instrumentation::MemoryInstrumentation::GetInstance() ->RequestPrivateMemoryFootprint( @@ -554,13 +570,15 @@ void NoStatePrefetchContents::DidGetMemoryUsage( bool success, std::unique_ptr<memory_instrumentation::GlobalMemoryDump> global_dump) { - if (!success) + if (!success) { return; + } for (const memory_instrumentation::GlobalMemoryDump::ProcessDump& dump : global_dump->process_dumps()) { - if (dump.pid() != process_pid_) + if (dump.pid() != process_pid_) { continue; + } // If |final_status_| == |FINAL_STATUS_USED|, then destruction will be // handled by the entity that set final_status_. @@ -580,8 +598,9 @@ } std::optional<base::Value::Dict> NoStatePrefetchContents::GetAsDict() const { - if (!no_state_prefetch_contents_) + if (!no_state_prefetch_contents_) { return std::nullopt; + } base::Value::Dict dict; dict.Set("url", prefetch_url_.spec()); base::TimeTicks current_time = base::TimeTicks::Now();
diff --git a/components/no_state_prefetch/browser/no_state_prefetch_handle.cc b/components/no_state_prefetch/browser/no_state_prefetch_handle.cc index ec1d291..16d419c 100644 --- a/components/no_state_prefetch/browser/no_state_prefetch_handle.cc +++ b/components/no_state_prefetch/browser/no_state_prefetch_handle.cc
@@ -32,14 +32,16 @@ void NoStatePrefetchHandle::OnNavigateAway() { DCHECK_CURRENTLY_ON(BrowserThread::UI); - if (prefetch_data_) + if (prefetch_data_) { prefetch_data_->OnHandleNavigatedAway(this); + } } void NoStatePrefetchHandle::OnCancel() { DCHECK_CURRENTLY_ON(BrowserThread::UI); - if (prefetch_data_) + if (prefetch_data_) { prefetch_data_->OnHandleCanceled(this); + } } bool NoStatePrefetchHandle::IsPrefetching() const { @@ -71,8 +73,9 @@ void NoStatePrefetchHandle::OnPrefetchStop( NoStatePrefetchContents* no_state_prefetch_contents) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - if (observer_) + if (observer_) { observer_->OnPrefetchStop(this); + } } bool NoStatePrefetchHandle::RepresentingSamePrefetchAs(
diff --git a/components/no_state_prefetch/browser/no_state_prefetch_link_manager.cc b/components/no_state_prefetch/browser/no_state_prefetch_link_manager.cc index 566bd802..310b97cb 100644 --- a/components/no_state_prefetch/browser/no_state_prefetch_link_manager.cc +++ b/components/no_state_prefetch/browser/no_state_prefetch_link_manager.cc
@@ -99,8 +99,9 @@ launcher_render_process_id, launcher_render_frame_id); // Guests inside <webview> do not support cross-process navigation and so we // do not allow guests to prerender content. - if (guest_view::GuestViewBase::IsGuest(rfh)) + if (guest_view::GuestViewBase::IsGuest(rfh)) { return std::nullopt; + } #endif // Check if the launcher is itself an unswapped prerender. @@ -125,28 +126,32 @@ triggers_.push_back(std::move(trigger)); - if (!no_state_prefetch_contents) + if (!no_state_prefetch_contents) { StartLinkTriggers(); + } // Check if the trigger we added is still at the end of the list. It // may have been discarded by StartLinkTriggers(). - if (!triggers_.empty() && triggers_.back().get() == trigger_ptr) + if (!triggers_.empty() && triggers_.back().get() == trigger_ptr) { return trigger_ptr->link_trigger_id; + } return std::nullopt; } void NoStatePrefetchLinkManager::OnCancelLinkTrigger(int link_trigger_id) { LinkTrigger* trigger = FindByLinkTriggerId(link_trigger_id); - if (!trigger) + if (!trigger) { return; + } CancelLinkTrigger(trigger); StartLinkTriggers(); } void NoStatePrefetchLinkManager::OnAbandonLinkTrigger(int link_trigger_id) { LinkTrigger* trigger = FindByLinkTriggerId(link_trigger_id); - if (!trigger) + if (!trigger) { return; + } if (!trigger->handle) { RemoveLinkTrigger(trigger); @@ -160,8 +165,9 @@ // If the prefetcher is not running, remove it from the list so it does not // leak. If it is running, it will send a cancel event when it stops which // will remove it. - if (!trigger->handle->IsPrefetching()) + if (!trigger->handle->IsPrefetching()) { RemoveLinkTrigger(trigger); + } } bool NoStatePrefetchLinkManager::IsEmpty() const { @@ -181,8 +187,9 @@ } void NoStatePrefetchLinkManager::StartLinkTriggers() { - if (has_shutdown_) + if (has_shutdown_) { return; + } size_t total_started_trigger_count = 0; std::list<LinkTrigger*> abandoned_triggers; @@ -195,8 +202,9 @@ for (auto it = triggers_.begin(); it != triggers_.end(); ++it) { std::unique_ptr<LinkTrigger>& trigger = *it; // Skip triggers launched by a trigger. - if (trigger->deferred_launcher) + if (trigger->deferred_launcher) { continue; + } if (!trigger->handle) { pending_triggers.push_back(it); } else { @@ -251,8 +259,9 @@ total_started_trigger_count >= triggers_.size()) { // The system is already at its prerender concurrency limit. Try removing // an abandoned trigger, if one exists, to make room. - if (abandoned_triggers.empty()) + if (abandoned_triggers.empty()) { return; + } CancelLinkTrigger(abandoned_triggers.front()); --total_started_trigger_count; @@ -289,8 +298,9 @@ NoStatePrefetchHandle* no_state_prefetch_handle) { DCHECK(no_state_prefetch_handle); for (auto& trigger : triggers_) { - if (trigger->handle.get() == no_state_prefetch_handle) + if (trigger->handle.get() == no_state_prefetch_handle) { return trigger.get(); + } } return nullptr; } @@ -298,8 +308,9 @@ NoStatePrefetchLinkManager::LinkTrigger* NoStatePrefetchLinkManager::FindByLinkTriggerId(int link_trigger_id) { for (auto& trigger : triggers_) { - if (trigger->link_trigger_id == link_trigger_id) + if (trigger->link_trigger_id == link_trigger_id) { return trigger.get(); + } } return nullptr; } @@ -324,8 +335,9 @@ std::unique_ptr<NoStatePrefetchHandle> own_handle = std::move(trigger->handle); triggers_.erase(it); - if (own_handle) + if (own_handle) { own_handle->OnCancel(); + } return; } } @@ -339,8 +351,9 @@ void NoStatePrefetchLinkManager::OnPrefetchStop( NoStatePrefetchHandle* no_state_prefetch_handle) { LinkTrigger* trigger = FindByNoStatePrefetchHandle(no_state_prefetch_handle); - if (!trigger) + if (!trigger) { return; + } RemoveLinkTrigger(trigger); StartLinkTriggers(); }
diff --git a/components/no_state_prefetch/browser/no_state_prefetch_manager.cc b/components/no_state_prefetch/browser/no_state_prefetch_manager.cc index 0d72f3a..895416d 100644 --- a/components/no_state_prefetch/browser/no_state_prefetch_manager.cc +++ b/components/no_state_prefetch/browser/no_state_prefetch_manager.cc
@@ -94,16 +94,18 @@ void SetPreloadingTriggeringOutcome(PreloadingAttempt* attempt, PreloadingTriggeringOutcome outcome) { - if (!attempt) + if (!attempt) { return; + } attempt->SetTriggeringOutcome(outcome); } void SetPreloadingEligibility(PreloadingAttempt* attempt, PreloadingEligibility eligibility) { - if (!attempt) + if (!attempt) { return; + } attempt->SetEligibility(eligibility); } @@ -222,12 +224,14 @@ if (process_id != -1) { RenderViewHost* source_render_view_host = RenderViewHost::FromID(process_id, route_id); - if (!source_render_view_host) + if (!source_render_view_host) { return nullptr; + } WebContents* source_web_contents = WebContents::FromRenderViewHost(source_render_view_host); - if (!source_web_contents) + if (!source_web_contents) { return nullptr; + } if (origin == ORIGIN_LINK_REL_PRERENDER_CROSSDOMAIN && source_web_contents->GetVisibleURL().host_piece() == url.host_piece()) { origin = ORIGIN_LINK_REL_PRERENDER_SAMEDOMAIN; @@ -351,8 +355,9 @@ for (const auto& prefetch : active_prefetches_) { WebContents* contents = prefetch->contents()->no_state_prefetch_contents(); - if (contents) + if (contents) { result.push_back(contents); + } } return result; @@ -365,8 +370,9 @@ CleanUpOldNavigations(&navigations_, base::Milliseconds(kNavigationRecordWindowMs)); for (const NavigationRecord& navigation : base::Reversed(navigations_)) { - if (navigation.url == url) + if (navigation.url == url) { return true; + } } return false; @@ -387,11 +393,13 @@ void NoStatePrefetchManager::ClearData(int clear_flags) { DCHECK_GE(clear_flags, 0); DCHECK_LT(clear_flags, CLEAR_MAX); - if (clear_flags & CLEAR_PRERENDER_CONTENTS) + if (clear_flags & CLEAR_PRERENDER_CONTENTS) { DestroyAllContents(FINAL_STATUS_CACHE_OR_HISTORY_CLEARED); + } // This has to be second, since destroying prerenders can add to the history. - if (clear_flags & CLEAR_PRERENDER_HISTORY) + if (clear_flags & CLEAR_PRERENDER_HISTORY) { prefetch_history_->Clear(); + } } void NoStatePrefetchManager::RecordFinalStatus(Origin origin, @@ -709,8 +717,9 @@ void NoStatePrefetchManager::StartSchedulingPeriodicCleanups() { DCHECK_CURRENTLY_ON(BrowserThread::UI); - if (repeating_timer_.IsRunning()) + if (repeating_timer_.IsRunning()) { return; + } repeating_timer_.Start(FROM_HERE, kPeriodicCleanupInterval, this, &NoStatePrefetchManager::PeriodicCleanup); @@ -730,20 +739,23 @@ // will not interfere with potential deletions of the list. std::vector<NoStatePrefetchContents*> prefetch_contents; prefetch_contents.reserve(active_prefetches_.size()); - for (auto& prefetch : active_prefetches_) + for (auto& prefetch : active_prefetches_) { prefetch_contents.push_back(prefetch->contents()); + } // And now check for prerenders using too much memory. - for (auto* contents : prefetch_contents) + for (auto* contents : prefetch_contents) { contents->DestroyWhenUsingTooManyResources(); + } base::ElapsedTimer cleanup_timer; // Perform deferred cleanup work. DeleteOldWebContents(); DeleteOldEntries(); - if (active_prefetches_.empty()) + if (active_prefetches_.empty()) { StopSchedulingPeriodicCleanups(); + } DeleteToDeletePrerenders(); @@ -774,8 +786,9 @@ DCHECK(prefetch_data); DCHECK(prefetch_data->contents()); - if (prefetch_data->expiry_time() > GetCurrentTimeTicks()) + if (prefetch_data->expiry_time() > GetCurrentTimeTicks()) { return; + } prefetch_data->contents()->Destroy(FINAL_STATUS_TIMED_OUT); } } @@ -834,8 +847,9 @@ SessionStorageNamespace* session_storage_namespace) { for (const auto& prefetch : active_prefetches_) { NoStatePrefetchContents* contents = prefetch->contents(); - if (contents->Matches(url, session_storage_namespace)) + if (contents->Matches(url, session_storage_namespace)) { return prefetch.get(); + } } return nullptr; } @@ -845,8 +859,9 @@ NoStatePrefetchContents* no_state_prefetch_contents) { for (auto it = active_prefetches_.begin(); it != active_prefetches_.end(); ++it) { - if ((*it)->contents() == no_state_prefetch_contents) + if ((*it)->contents() == no_state_prefetch_contents) { return it; + } } return active_prefetches_.end(); } @@ -855,12 +870,14 @@ DCHECK_CURRENTLY_ON(BrowserThread::UI); // Allow navigation predictor to manage its own rate limit. - if (origin == ORIGIN_NAVIGATION_PREDICTOR) + if (origin == ORIGIN_NAVIGATION_PREDICTOR) { return true; + } base::TimeDelta elapsed_time = GetCurrentTimeTicks() - last_prefetch_start_time_; - if (!config_.rate_limit_enabled) + if (!config_.rate_limit_enabled) { return true; + } return elapsed_time >= base::Milliseconds(kMinTimeBetweenPrefetchesMs); } @@ -875,21 +892,27 @@ Origin* origin) { CleanUpOldNavigations(&prefetches_, base::Minutes(30)); - if (prefetch_age) + if (prefetch_age) { *prefetch_age = base::TimeDelta(); - if (final_status) + } + if (final_status) { *final_status = FINAL_STATUS_MAX; - if (origin) + } + if (origin) { *origin = ORIGIN_NONE; + } for (const NavigationRecord& prefetch : base::Reversed(prefetches_)) { if (prefetch.url == url) { - if (prefetch_age) + if (prefetch_age) { *prefetch_age = GetCurrentTimeTicks() - prefetch.time; - if (final_status) + } + if (final_status) { *final_status = prefetch.final_status; - if (origin) + } + if (origin) { *origin = prefetch.origin; + } return true; } } @@ -923,8 +946,9 @@ base::TimeTicks cutoff = GetCurrentTimeTicks() - max_age; auto it = navigations->begin(); for (; it != navigations->end(); ++it) { - if (it->time > cutoff) + if (it->time > cutoff) { break; + } } navigations->erase(navigations->begin(), it); } @@ -938,8 +962,9 @@ old_web_contents_list_.push_back(std::move(tab)); PostCleanupTask(); - if (!deleter) + if (!deleter) { return; + } for (auto it = on_close_web_contents_deleters_.begin(); it != on_close_web_contents_deleters_.end(); ++it) { @@ -985,8 +1010,9 @@ return; } - if (origin == ORIGIN_LINK_REL_NEXT) + if (origin == ORIGIN_LINK_REL_NEXT) { return; + } if (final_status == FINAL_STATUS_LOW_END_DEVICE || final_status == FINAL_STATUS_DUPLICATE ||
diff --git a/components/no_state_prefetch/browser/no_state_prefetch_processor_impl.cc b/components/no_state_prefetch/browser/no_state_prefetch_processor_impl.cc index 9a4597c7..3b1783a2 100644 --- a/components/no_state_prefetch/browser/no_state_prefetch_processor_impl.cc +++ b/components/no_state_prefetch/browser/no_state_prefetch_processor_impl.cc
@@ -76,12 +76,14 @@ auto* render_frame_host = content::RenderFrameHost::FromID(render_process_id_, render_frame_id_); - if (!render_frame_host) + if (!render_frame_host) { return; + } auto* link_manager = GetNoStatePrefetchLinkManager(); - if (!link_manager) + if (!link_manager) { return; + } DCHECK(!link_trigger_id_); link_trigger_id_ = link_manager->OnStartLinkTrigger( @@ -91,18 +93,21 @@ } void NoStatePrefetchProcessorImpl::Cancel() { - if (!link_trigger_id_) + if (!link_trigger_id_) { return; + } auto* link_manager = GetNoStatePrefetchLinkManager(); - if (link_manager) + if (link_manager) { link_manager->OnCancelLinkTrigger(*link_trigger_id_); + } } void NoStatePrefetchProcessorImpl::Abandon() { if (link_trigger_id_) { auto* link_manager = GetNoStatePrefetchLinkManager(); - if (link_manager) + if (link_manager) { link_manager->OnAbandonLinkTrigger(*link_trigger_id_); + } } delete this; } @@ -111,8 +116,9 @@ NoStatePrefetchProcessorImpl::GetNoStatePrefetchLinkManager() { auto* render_frame_host = content::RenderFrameHost::FromID(render_process_id_, render_frame_id_); - if (!render_frame_host) + if (!render_frame_host) { return nullptr; + } return delegate_->GetNoStatePrefetchLinkManager( render_frame_host->GetProcess()->GetBrowserContext()); }
diff --git a/components/no_state_prefetch/browser/no_state_prefetch_utils.cc b/components/no_state_prefetch/browser/no_state_prefetch_utils.cc index beb67b6..b3a7b48f 100644 --- a/components/no_state_prefetch/browser/no_state_prefetch_utils.cc +++ b/components/no_state_prefetch/browser/no_state_prefetch_utils.cc
@@ -53,13 +53,15 @@ nostate_prefetch_entry_found = no_state_prefetch_manager->GetPrefetchInformation( url, &prefetch_age, &final_status, &prefetch_origin); - if (nostate_prefetch_entry_found) + if (nostate_prefetch_entry_found) { break; + } } } - if (!nostate_prefetch_entry_found) + if (!nostate_prefetch_entry_found) { return; + } ukm::builders::NoStatePrefetch builder(source_id); builder.SetPrefetchedRecently_PrefetchAge(
diff --git a/components/no_state_prefetch/common/no_state_prefetch_url_loader_throttle.cc b/components/no_state_prefetch/common/no_state_prefetch_url_loader_throttle.cc index d8a3f66..08f4cb1 100644 --- a/components/no_state_prefetch/common/no_state_prefetch_url_loader_throttle.cc +++ b/components/no_state_prefetch/common/no_state_prefetch_url_loader_throttle.cc
@@ -39,8 +39,9 @@ } NoStatePrefetchURLLoaderThrottle::~NoStatePrefetchURLLoaderThrottle() { - if (destruction_closure_) + if (destruction_closure_) { std::move(destruction_closure_).Run(); + } } void NoStatePrefetchURLLoaderThrottle::DetachFromCurrentSequence() { @@ -122,7 +123,6 @@ std::vector<std::string>* /* to_be_removed_headers */, net::HttpRequestHeaders* /* modified_headers */, net::HttpRequestHeaders* /* modified_cors_exempt_headers */) { - std::string follow_only_when_prerender_shown_header; if (response_head.headers) { follow_only_when_prerender_shown_header =
diff --git a/components/no_state_prefetch/common/no_state_prefetch_url_loader_throttle_unittest.cc b/components/no_state_prefetch/common/no_state_prefetch_url_loader_throttle_unittest.cc index 27a92d56..829bc72 100644 --- a/components/no_state_prefetch/common/no_state_prefetch_url_loader_throttle_unittest.cc +++ b/components/no_state_prefetch/common/no_state_prefetch_url_loader_throttle_unittest.cc
@@ -66,11 +66,10 @@ scoped_refptr<base::SequencedTaskRunner> current_task_runner = base::SequencedTaskRunner::GetCurrentDefault(); no_state_prefetch_throttle->set_destruction_closure( - base::BindLambdaForTesting( - [&]() { - EXPECT_TRUE(current_task_runner->RunsTasksInCurrentSequence()); - run_loop.Quit(); - })); + base::BindLambdaForTesting([&]() { + EXPECT_TRUE(current_task_runner->RunsTasksInCurrentSequence()); + run_loop.Quit(); + })); std::unique_ptr<blink::URLLoaderThrottle> throttle = std::move(no_state_prefetch_throttle);
diff --git a/components/no_state_prefetch/common/no_state_prefetch_utils.cc b/components/no_state_prefetch/common/no_state_prefetch_utils.cc index e440777..b05817d 100644 --- a/components/no_state_prefetch/common/no_state_prefetch_utils.cc +++ b/components/no_state_prefetch/common/no_state_prefetch_utils.cc
@@ -49,16 +49,18 @@ // compare them. DCHECK_EQ(method, base::ToUpperASCII(method)); for (auto* valid_method : kValidHttpMethods) { - if (method == valid_method) + if (method == valid_method) { return true; + } } return false; } std::string ComposeHistogramName(const std::string& prefix_type, const std::string& name) { - if (prefix_type.empty()) + if (prefix_type.empty()) { return std::string("Prerender.") + name; + } return std::string("Prerender.") + prefix_type + std::string("_") + name; }
diff --git a/components/no_state_prefetch/renderer/no_state_prefetch_client.cc b/components/no_state_prefetch/renderer/no_state_prefetch_client.cc index 71fd1c0..4f343642 100644 --- a/components/no_state_prefetch/renderer/no_state_prefetch_client.cc +++ b/components/no_state_prefetch/renderer/no_state_prefetch_client.cc
@@ -23,8 +23,9 @@ bool NoStatePrefetchClient::IsPrefetchOnly() { blink::WebFrame* main_frame = GetWebView()->MainFrame(); - if (!main_frame->IsWebLocalFrame()) + if (!main_frame->IsWebLocalFrame()) { return false; + } return NoStatePrefetchHelper::IsPrefetching( content::RenderFrame::FromWebFrame(main_frame->ToWebLocalFrame())); }
diff --git a/components/no_state_prefetch/renderer/no_state_prefetch_helper.cc b/components/no_state_prefetch/renderer/no_state_prefetch_helper.cc index f57a234..42c19fa 100644 --- a/components/no_state_prefetch/renderer/no_state_prefetch_helper.cc +++ b/components/no_state_prefetch/renderer/no_state_prefetch_helper.cc
@@ -43,8 +43,9 @@ render_frame ? NoStatePrefetchHelper::Get(render_frame->GetMainRenderFrame()) : nullptr; - if (!helper) + if (!helper) { return nullptr; + } mojo::PendingRemote<mojom::NoStatePrefetchCanceler> canceler; render_frame->GetBrowserInterfaceBroker().GetInterface( @@ -64,8 +65,9 @@ void NoStatePrefetchHelper::DidDispatchDOMContentLoadedEvent() { prefetch_finished_ = true; - if (prefetch_count_ == 0) + if (prefetch_count_ == 0) { SendPrefetchFinished(); + } } void NoStatePrefetchHelper::OnDestruct() {
diff --git a/components/no_state_prefetch/renderer/no_state_prefetch_utils.cc b/components/no_state_prefetch/renderer/no_state_prefetch_utils.cc index d76dd69..5e64ee2f 100644 --- a/components/no_state_prefetch/renderer/no_state_prefetch_utils.cc +++ b/components/no_state_prefetch/renderer/no_state_prefetch_utils.cc
@@ -78,8 +78,9 @@ void OnDestruct() override { delete this; } void OnPageVisibilityChanged( content::PageVisibilityState visibility_state) override { - if (visibility_state != content::PageVisibilityState::kVisible) + if (visibility_state != content::PageVisibilityState::kVisible) { return; + } std::move(continue_loading_cb_).Run(); delete this; }
diff --git a/components/omnibox/browser/autocomplete_controller.cc b/components/omnibox/browser/autocomplete_controller.cc index 59dfa85d..df95091 100644 --- a/components/omnibox/browser/autocomplete_controller.cc +++ b/components/omnibox/browser/autocomplete_controller.cc
@@ -1589,83 +1589,69 @@ if (!keyword_provider_) return; - // Determine if the user's input is an exact keyword match. - std::u16string exact_keyword = - keyword_provider_->GetKeywordForText(input_.text()); + // The keyword matching the user's input. + std::u16string input_text_keyword = keyword_provider_->GetKeywordForText( + input_.text(), template_url_service_); + TemplateURL* input_text_keyword_turl = + template_url_service_->GetTemplateURLForKeyword(input_text_keyword); + // Cache added keywords to avoid showing duplicate keywords. std::set<std::u16string> keywords; + + auto add_keyword = [&](AutocompleteMatch& match, + const std::u16string& keyword_text, + const std::u16string& keyword) { + // There shouldn't be duplicate keywords. + CHECK(!keywords.count(keyword)); + keywords.insert(keyword); + match.associated_keyword = std::make_unique<AutocompleteMatch>( + keyword_provider_->CreateVerbatimMatch(keyword_text, keyword, input_)); + }; + for (AutocompleteMatch& match : *result) { - std::u16string keyword( + // Clear any keyword the match may have from previous passes. + match.associated_keyword.reset(); + + // If this match is in keyword mode (e.g. the user tabbed into a keyword + // then continued typing), don't attach a keyword chip to it. + std::u16string explicit_keyword( match.GetSubstitutingExplicitlyInvokedKeyword(template_url_service_)); - if (!keyword.empty()) { - keywords.insert(keyword); + if (!explicit_keyword.empty() && !keywords.count(explicit_keyword)) { + // Also prevent other matches showing a keyword chip for the keyword the + // user is already in. + keywords.insert(explicit_keyword); continue; } - // When the user has typed an exact keyword, we want tab-to-search on the - // default match to select that keyword, even if the match - // inline-autocompletes to a different keyword. (This prevents inline - // autocompletions from blocking a user's attempts to use an explicitly-set - // keyword of their own creation.) So use |exact_keyword| if it's - // available. - if (!exact_keyword.empty() && !keywords.count(exact_keyword)) { - // Prevent starter-pack keywords from attaching to non-starter-pack - // matches. Those will have a dedicated UI with an explicit match - // selection to enter keyword mode. - if (kIsDesktop && match.type != AutocompleteMatchType::STARTER_PACK) { - TemplateURL* turl = - template_url_service_->GetTemplateURLForKeyword(exact_keyword); - // Note, starter pack matches that removed the '@' from the beginning of - // the keyword are still allowed to attach because those don't get the - // special UX, by design. - if (turl && turl->starter_pack_id() != 0 && - turl->keyword().starts_with(u'@')) { - continue; - } - } - - keywords.insert(exact_keyword); - // If the match has an answer, it will look strange to try to display - // it along with a keyword hint. Prefer the keyword hint, and revert - // to a typical search. - match.answer_template.reset(); - match.answer_type = omnibox::ANSWER_TYPE_UNSPECIFIED; - match.associated_keyword = std::make_unique<AutocompleteMatch>( - keyword_provider_->CreateVerbatimMatch(exact_keyword, exact_keyword, - input_)); -#if BUILDFLAG(IS_ANDROID) - match.UpdateJavaAnswer(); -#endif + // When the input text matches a keyword, tab-to-search on the default + // match should select that keyword, even if the match inline-autocompletes + // to a different keyword. + if (!input_text_keyword.empty() && !keywords.count(input_text_keyword) && + input_text_keyword_turl->starter_pack_id() == 0 && + !input_text_keyword_turl->featured_by_policy()) { + add_keyword(match, input_text_keyword, input_text_keyword); continue; } - // Otherwise, set a match's associated keyword based on the match's - // fill_into_edit, which should take inline autocompletions into account. - keyword = keyword_provider_->GetKeywordForText(match.fill_into_edit); + // The keyword for the match text. + std::u16string match_text_keyword = keyword_provider_->GetKeywordForText( + match.fill_into_edit, template_url_service_); + TemplateURL* match_text_keyword_turl = + template_url_service_->GetTemplateURLForKeyword(match_text_keyword); - if (!keyword.empty()) { - // Prevent starter-pack keywords from attaching to non-starter-pack - // matches. - if (kIsDesktop && match.type != AutocompleteMatchType::STARTER_PACK) { - TemplateURL* turl = - template_url_service_->GetTemplateURLForKeyword(keyword); - if (turl && turl->starter_pack_id() != 0 && - turl->keyword().starts_with(u'@')) { - continue; - } - } + // Featured keyword matches should always have their corresponding keyword + // or they won't work. + if (AutocompleteMatch::IsFeaturedSearchType(match.type)) { + CHECK(!match_text_keyword.empty()); + add_keyword(match, match.fill_into_edit, match_text_keyword); + continue; + } - // Only add the keyword if the match does not have a duplicate keyword - // with a more relevant match. - if (!keywords.count(keyword) || - (kIsDesktop && AutocompleteMatch::IsFeaturedSearchType(match.type))) { - keywords.insert(keyword); - match.associated_keyword = std::make_unique<AutocompleteMatch>( - keyword_provider_->CreateVerbatimMatch(match.fill_into_edit, - keyword, input_)); - } else { - match.associated_keyword.reset(); - } + // Add keyword hints for typical matches. + if (!match_text_keyword.empty() && !keywords.count(match_text_keyword) && + match_text_keyword_turl->starter_pack_id() == 0 && + !match_text_keyword_turl->featured_by_policy()) { + add_keyword(match, match.fill_into_edit, match_text_keyword); } } }
diff --git a/components/omnibox/browser/autocomplete_controller_unittest.cc b/components/omnibox/browser/autocomplete_controller_unittest.cc index bb415202..8fb0cf0 100644 --- a/components/omnibox/browser/autocomplete_controller_unittest.cc +++ b/components/omnibox/browser/autocomplete_controller_unittest.cc
@@ -26,6 +26,7 @@ #include "components/omnibox/browser/fake_autocomplete_provider.h" #include "components/omnibox/browser/fake_autocomplete_provider_client.h" #include "components/omnibox/browser/fake_tab_matcher.h" +#include "components/omnibox/browser/keyword_provider.h" #include "components/omnibox/browser/omnibox_field_trial.h" #include "components/omnibox/browser/test_scheme_classifier.h" #include "components/omnibox/common/omnibox_feature_configs.h" @@ -2415,3 +2416,117 @@ controller_.internal_result_.match_at(2)->has_tab_match.value_or(false)); } #endif + +TEST_F(AutocompleteControllerTest, UpdateAssociatedKeywords) { + controller_.keyword_provider_ = + new KeywordProvider(provider_client(), nullptr); + controller_.providers_.push_back(controller_.keyword_provider_.get()); + + auto add_keyword = [&](std::u16string keyword, bool is_starter_pack = false, + bool is_featured_enterprise_search = false) { + TemplateURLData turl_data; + turl_data.SetShortName(u"name"); + turl_data.SetURL("https://google.com/search?q={searchTerms}"); + turl_data.is_active = TemplateURLData::ActiveStatus::kTrue; + turl_data.SetKeyword(keyword); + if (is_starter_pack) { + turl_data.starter_pack_id = 1; + } else if (is_featured_enterprise_search) { + turl_data.featured_by_policy = true; + } + controller_.template_url_service_->Add( + std::make_unique<TemplateURL>(turl_data)); + }; + + struct MatchData { + std::u16string fill_into_edit; + AutocompleteMatchType::Type type; + }; + + auto test = [&](const std::u16string input_text, + const std::u16string input_keyword, + std::vector<MatchData> match_datas) { + controller_.input_ = FakeAutocompleteController::CreateInput(input_text); + AutocompleteResult result; + for (const auto& match_data : match_datas) { + AutocompleteMatch match; + match.fill_into_edit = match_data.fill_into_edit; + match.type = match_data.type; + result.AppendMatches({match}); + } + if (!input_keyword.empty()) { + result.match_at(0)->keyword = input_keyword; + result.match_at(0)->transition = ui::PAGE_TRANSITION_KEYWORD; + } + controller_.UpdateAssociatedKeywords(&result); + + std::vector<std::u16string> attached_keywords; + for (const auto& match : result) { + attached_keywords.push_back( + match.associated_keyword ? match.associated_keyword->keyword : u""); + } + return attached_keywords; + }; + + add_keyword(u"keyword_0"); + add_keyword(u"keyword_1"); + add_keyword(u"keyword_starter_pack", true); + add_keyword(u"keyword_featured_enterprise_search", false, true); + + // When the input text's 1st word matches a keyword, the keyword hint is added + // to the 1st match regardless of which match is similar to the keyword. Only + // 1 keyword is added even if there's another match matching the keyword. + EXPECT_THAT(test(u"keyword_0", u"", {{u"bing.com"}, {u"keyword_0"}}), + testing::ElementsAreArray({u"keyword_0", u""})); + EXPECT_THAT( + test(u"keyword_0 more words", u"", {{u"bing.com"}, {u"keyword_0"}}), + testing::ElementsAreArray({u"keyword_0", u""})); + + // Only 1 keyword is added even if there're 2 non-exact matches matching the + // keyword. + EXPECT_THAT( + test(u"input", u"", {{u"bing.com"}, {u"keyword_0"}, {u"keyword_0"}}), + testing::ElementsAreArray({u"", u"keyword_0", u""})); + + // When the user is in a keyword mode, don't show keyword hints for that + // keyword, but do still show other keywords. + EXPECT_THAT(test(u"keyword_0", u"keyword_0", + {{u"keyword_0"}, {u"keyword_0"}, {u"keyword_1"}}), + testing::ElementsAreArray({u"", u"", u"keyword_1"})); + + // Starter pack and featured enterprise matches should always have keywords, + // regardless of the input or the match position. + EXPECT_THAT(test(u"input", u"", + {{u"keyword_starter_pack", + AutocompleteMatchType::Type::STARTER_PACK}, + {u"keyword_featured_enterprise_search", + AutocompleteMatchType::Type::FEATURED_ENTERPRISE_SEARCH}, + {u"keyword_0"}, + {u"keywo"}}), + testing::ElementsAreArray({u"keyword_starter_pack", + u"keyword_featured_enterprise_search", + u"keyword_0", u""})); + + // Normal matches should not have keyword hints for starter pack or featured + // enterprise keywords. + EXPECT_THAT(test(u"input", u"", + {{u"keyword_starter_pack"}, + {u"keyword_featured_enterprise_search"}}), + testing::ElementsAreArray({u"", u""})); + + // Normal matches should not have keyword hints for starter pack or featured + // enterprise keywords, even if the input is an exact keyword match. + EXPECT_THAT(test(u"keyword_starter_pack", u"", {{u"keyword_starter_pack"}}), + testing::ElementsAreArray({u""})); + EXPECT_THAT(test(u"keyword_featured_enterprise_search", u"", + {{u"keyword_featured_enterprise_search"}}), + testing::ElementsAreArray({u""})); + + // Keywords are added if the 1st word of the match text matches, even if the + // match text has more non-matching words after. Keywords are not added if the + // 1st word of the match text is a prefix of or prefixed by the keyword. + EXPECT_THAT( + test(u"input", u"", + {{u"keywo"}, {u"keyword_0_underscore"}, {u"keyword_0 space"}}), + testing::ElementsAreArray({u"", u"", u"keyword_0"})); +}
diff --git a/components/omnibox/browser/autocomplete_match.cc b/components/omnibox/browser/autocomplete_match.cc index f380999..e4e8a0c 100644 --- a/components/omnibox/browser/autocomplete_match.cc +++ b/components/omnibox/browser/autocomplete_match.cc
@@ -133,28 +133,28 @@ const AutocompleteProvider::Type type = provider->type(); constexpr auto kProviderPrefMap = - base::MakeFixedFlatMap<AutocompleteProvider::Type, int>({ - // Prefer live document suggestions. We check provider type instead - // of match type in order to distinguish live suggestions from the - // document provider from stale suggestions from the shortcuts - // providers, because the latter omits changing metadata such as last - // access date. - {AutocompleteProvider::TYPE_DOCUMENT, 2}, - // Prefer bookmark suggestions, as: - // 1) Their titles may be explicitly set. - // 2) They may display enhanced information such as the bookmark - // folders path. - {AutocompleteProvider::TYPE_BOOKMARK, 1}, - // Don't let bookmarks override builtins, as that interferes with - // starter pack matches when user has bookmarked their destination. - {AutocompleteProvider::TYPE_BUILTIN, kIsDesktop ? 1 : 0}, - // Prefer non-shorcut matches over shortcuts, the latter of which may - // have stale or missing URL titles (the latter from what-you-typed - // matches). - {AutocompleteProvider::TYPE_SHORTCUTS, -1}, - // Prefer non-fuzzy matches over fuzzy matches. - {AutocompleteProvider::TYPE_HISTORY_FUZZY, -2}, - }); + base::MakeFixedFlatMap<AutocompleteProvider::Type, int>({ + // Prefer live document suggestions. We check provider type instead + // of match type in order to distinguish live suggestions from the + // document provider from stale suggestions from the shortcuts + // providers, because the latter omits changing metadata such as last + // access date. + {AutocompleteProvider::TYPE_DOCUMENT, 2}, + // Prefer bookmark suggestions, as: + // 1) Their titles may be explicitly set. + // 2) They may display enhanced information such as the bookmark + // folders path. + {AutocompleteProvider::TYPE_BOOKMARK, 1}, + // Don't let bookmarks override builtins, as that interferes with + // starter pack matches when user has bookmarked their destination. + {AutocompleteProvider::TYPE_BUILTIN, kIsDesktop ? 1 : 0}, + // Prefer non-shorcut matches over shortcuts, the latter of which may + // have stale or missing URL titles (the latter from what-you-typed + // matches). + {AutocompleteProvider::TYPE_SHORTCUTS, -1}, + // Prefer non-fuzzy matches over fuzzy matches. + {AutocompleteProvider::TYPE_HISTORY_FUZZY, -2}, + }); const auto it = kProviderPrefMap.find(type); return it != kProviderPrefMap.end() ? it->second : 0; } @@ -1237,13 +1237,7 @@ } TemplateURL* turl = associated_keyword->GetTemplateURL(template_url_service, false); - if (!turl) { - return false; - } - // Note, starter pack keywords with '@' prefix removed do not get - // the special instant keyword UX, by design. - return (turl->starter_pack_id() != 0 || turl->featured_by_policy()) && - turl->keyword().starts_with(u'@'); + return turl && (turl->starter_pack_id() != 0 || turl->featured_by_policy()); } void AutocompleteMatch::GetKeywordUIState(
diff --git a/components/omnibox/browser/fake_autocomplete_controller.h b/components/omnibox/browser/fake_autocomplete_controller.h index 26746802..3f4da4ad 100644 --- a/components/omnibox/browser/fake_autocomplete_controller.h +++ b/components/omnibox/browser/fake_autocomplete_controller.h
@@ -99,11 +99,13 @@ // AutocompleteController (methods): using AutocompleteController::MaybeRemoveCompanyEntityImages; using AutocompleteController::ShouldRunProvider; + using AutocompleteController::UpdateAssociatedKeywords; using AutocompleteController::UpdateResult; // AutocompleteController (fields): using AutocompleteController::input_; using AutocompleteController::internal_result_; + using AutocompleteController::keyword_provider_; using AutocompleteController::last_update_type_; using AutocompleteController::metrics_; using AutocompleteController::providers_;
diff --git a/components/omnibox/browser/featured_search_provider.cc b/components/omnibox/browser/featured_search_provider.cc index db94377..5955ce6d 100644 --- a/components/omnibox/browser/featured_search_provider.cc +++ b/components/omnibox/browser/featured_search_provider.cc
@@ -198,21 +198,21 @@ size_t enterprise_count = 0; if (input.GetFeaturedKeywordMode() != AutocompleteInput::FeaturedKeywordMode::kFalse) { - TemplateURLService::TemplateURLVector matches; - template_url_service_->AddMatchingKeywords(input.text(), false, &matches); - for (TemplateURL* match : matches) { - if (match->starter_pack_id() > 0 && - match->is_active() == TemplateURLData::ActiveStatus::kTrue) { + TemplateURLService::TemplateURLVector turls; + template_url_service_->AddMatchingKeywords(input.text(), false, &turls); + for (TemplateURL* turl : turls) { + if (turl->starter_pack_id() > 0 && + turl->is_active() == TemplateURLData::ActiveStatus::kTrue) { // Don't add the expanded set of starter pack engines unless the feature // is enabled. if (!OmniboxFieldTrial::IsStarterPackExpansionEnabled() && - match->starter_pack_id() > TemplateURLStarterPackData::kTabs) { + turl->starter_pack_id() > TemplateURLStarterPackData::kTabs) { continue; } - AddStarterPackMatch(*match, input); - } else if (match->featured_by_policy() && + AddStarterPackMatch(*turl, input); + } else if (turl->featured_by_policy() && enterprise_count < kMaxEnterpriseSuggestions) { - AddFeaturedEnterpriseSearchMatch(*match, input); + AddFeaturedEnterpriseSearchMatch(*turl, input); enterprise_count++; } }
diff --git a/components/omnibox/browser/keyword_provider.cc b/components/omnibox/browser/keyword_provider.cc index 4c9e38b..f95cb8d2 100644 --- a/components/omnibox/browser/keyword_provider.cc +++ b/components/omnibox/browser/keyword_provider.cc
@@ -91,15 +91,12 @@ } std::u16string KeywordProvider::GetKeywordForText( - const std::u16string& text) const { - TemplateURLService* url_service = GetTemplateURLService(); - if (!url_service) - return std::u16string(); - + const std::u16string& text, + TemplateURLService* template_url_service) const { // We want the Search button to persist as long as the input begins with a // keyword. This is found by taking the input until the first white space. std::u16string keyword = AutocompleteInput::CleanUserInputKeyword( - url_service, + template_url_service, AutocompleteInput::SplitKeywordFromInput(text, true, nullptr)); if (keyword.empty()) @@ -107,9 +104,9 @@ // Don't provide a keyword if it doesn't support replacement. const TemplateURL* const template_url = - url_service->GetTemplateURLForKeyword(keyword); - if (!template_url || - !template_url->SupportsReplacement(url_service->search_terms_data())) { + template_url_service->GetTemplateURLForKeyword(keyword); + if (!template_url || !template_url->SupportsReplacement( + template_url_service->search_terms_data())) { return std::u16string(); }
diff --git a/components/omnibox/browser/keyword_provider.h b/components/omnibox/browser/keyword_provider.h index c75e163..4583abf 100644 --- a/components/omnibox/browser/keyword_provider.h +++ b/components/omnibox/browser/keyword_provider.h
@@ -61,7 +61,9 @@ // If `text` corresponds to an enabled, substituting keyword, returns that // keyword; returns the empty string otherwise. - std::u16string GetKeywordForText(const std::u16string& text) const; + std::u16string GetKeywordForText( + const std::u16string& text, + TemplateURLService* template_url_service) const; // Creates a fully marked-up AutocompleteMatch for a specific keyword. AutocompleteMatch CreateVerbatimMatch(const std::u16string& text,
diff --git a/components/omnibox/browser/keyword_provider_unittest.cc b/components/omnibox/browser/keyword_provider_unittest.cc index 9810ab3..ee328fe 100644 --- a/components/omnibox/browser/keyword_provider_unittest.cc +++ b/components/omnibox/browser/keyword_provider_unittest.cc
@@ -127,10 +127,10 @@ kw_provider_ = new KeywordProvider(client_.get(), nullptr); } -template<class ResultType> +template <class ResultType> void KeywordProviderTest::RunTest(TestData<ResultType>* keyword_cases, int num_cases, - ResultType AutocompleteMatch::* member) { + ResultType AutocompleteMatch::*member) { ACMatches matches; for (int i = 0; i < num_cases; ++i) { SCOPED_TRACE(keyword_cases[i].input); @@ -226,7 +226,7 @@ } TEST_F(KeywordProviderTest, URL) { - const MatchType<GURL> kEmptyMatch = { GURL(), false }; + const MatchType<GURL> kEmptyMatch = {GURL(), false}; TestData<GURL> url_cases[] = { // No query input -> empty destination URL. {u"z", 1, {{GURL(), true}, kEmptyMatch, kEmptyMatch}}, @@ -325,41 +325,58 @@ } TEST_F(KeywordProviderTest, GetKeywordForInput) { - EXPECT_EQ(u"aa", kw_provider_->GetKeywordForText(u"aa")); - EXPECT_EQ(std::u16string(), kw_provider_->GetKeywordForText(u"aafoo")); - EXPECT_EQ(u"aa", kw_provider_->GetKeywordForText(u"aa foo")); + TemplateURLService* template_url_service = client_->GetTemplateURLService(); + EXPECT_EQ(u"aa", + kw_provider_->GetKeywordForText(u"aa", template_url_service)); + EXPECT_EQ(std::u16string(), + kw_provider_->GetKeywordForText(u"aafoo", template_url_service)); + EXPECT_EQ(u"aa", + kw_provider_->GetKeywordForText(u"aa foo", template_url_service)); EXPECT_EQ(u"cleantestv1.com", - kw_provider_->GetKeywordForText(u"http://cleantestv1.com")); + kw_provider_->GetKeywordForText(u"http://cleantestv1.com", + template_url_service)); EXPECT_EQ(u"cleantestv1.com", - kw_provider_->GetKeywordForText(u"www.cleantestv1.com")); + kw_provider_->GetKeywordForText(u"www.cleantestv1.com", + template_url_service)); + EXPECT_EQ(u"cleantestv1.com", kw_provider_->GetKeywordForText( + u"cleantestv1.com/", template_url_service)); EXPECT_EQ(u"cleantestv1.com", - kw_provider_->GetKeywordForText(u"cleantestv1.com/")); - EXPECT_EQ(u"cleantestv1.com", - kw_provider_->GetKeywordForText(u"https://www.cleantestv1.com/")); - EXPECT_EQ(u"cleantestv2.com", - kw_provider_->GetKeywordForText(u"cleantestv2.com")); + kw_provider_->GetKeywordForText(u"https://www.cleantestv1.com/", + template_url_service)); + EXPECT_EQ(u"cleantestv2.com", kw_provider_->GetKeywordForText( + u"cleantestv2.com", template_url_service)); EXPECT_EQ(u"www.cleantestv2.com", - kw_provider_->GetKeywordForText(u"www.cleantestv2.com")); - EXPECT_EQ(u"cleantestv2.com", - kw_provider_->GetKeywordForText(u"cleantestv2.com/")); + kw_provider_->GetKeywordForText(u"www.cleantestv2.com", + template_url_service)); + EXPECT_EQ(u"cleantestv2.com", kw_provider_->GetKeywordForText( + u"cleantestv2.com/", template_url_service)); EXPECT_EQ(u"www.cleantestv3.com", - kw_provider_->GetKeywordForText(u"www.cleantestv3.com")); - EXPECT_EQ(std::u16string(), - kw_provider_->GetKeywordForText(u"cleantestv3.com")); + kw_provider_->GetKeywordForText(u"www.cleantestv3.com", + template_url_service)); + EXPECT_EQ(std::u16string(), kw_provider_->GetKeywordForText( + u"cleantestv3.com", template_url_service)); EXPECT_EQ(u"http://cleantestv4.com", - kw_provider_->GetKeywordForText(u"http://cleantestv4.com")); - EXPECT_EQ(std::u16string(), - kw_provider_->GetKeywordForText(u"cleantestv4.com")); - EXPECT_EQ(u"cleantestv5.com", - kw_provider_->GetKeywordForText(u"cleantestv5.com")); + kw_provider_->GetKeywordForText(u"http://cleantestv4.com", + template_url_service)); + EXPECT_EQ(std::u16string(), kw_provider_->GetKeywordForText( + u"cleantestv4.com", template_url_service)); + EXPECT_EQ(u"cleantestv5.com", kw_provider_->GetKeywordForText( + u"cleantestv5.com", template_url_service)); EXPECT_EQ(u"http://cleantestv5.com", - kw_provider_->GetKeywordForText(u"http://cleantestv5.com")); - EXPECT_EQ(u"cleantestv6:", kw_provider_->GetKeywordForText(u"cleantestv6:")); - EXPECT_EQ(std::u16string(), kw_provider_->GetKeywordForText(u"cleantestv6")); - EXPECT_EQ(u"cleantestv7/", kw_provider_->GetKeywordForText(u"cleantestv7/")); - EXPECT_EQ(std::u16string(), kw_provider_->GetKeywordForText(u"cleantestv7")); - EXPECT_EQ(u"cleantestv8/", kw_provider_->GetKeywordForText(u"cleantestv8/")); - EXPECT_EQ(u"cleantestv8", kw_provider_->GetKeywordForText(u"cleantestv8")); + kw_provider_->GetKeywordForText(u"http://cleantestv5.com", + template_url_service)); + EXPECT_EQ(u"cleantestv6:", kw_provider_->GetKeywordForText( + u"cleantestv6:", template_url_service)); + EXPECT_EQ(std::u16string(), kw_provider_->GetKeywordForText( + u"cleantestv6", template_url_service)); + EXPECT_EQ(u"cleantestv7/", kw_provider_->GetKeywordForText( + u"cleantestv7/", template_url_service)); + EXPECT_EQ(std::u16string(), kw_provider_->GetKeywordForText( + u"cleantestv7", template_url_service)); + EXPECT_EQ(u"cleantestv8/", kw_provider_->GetKeywordForText( + u"cleantestv8/", template_url_service)); + EXPECT_EQ(u"cleantestv8", kw_provider_->GetKeywordForText( + u"cleantestv8", template_url_service)); } TEST_F(KeywordProviderTest, GetSubstitutingTemplateURLForInput) {
diff --git a/components/omnibox/browser/omnibox_edit_model.cc b/components/omnibox/browser/omnibox_edit_model.cc index ae456a4..3c047f8 100644 --- a/components/omnibox/browser/omnibox_edit_model.cc +++ b/components/omnibox/browser/omnibox_edit_model.cc
@@ -2754,10 +2754,12 @@ std::u16string keyword; base::TrimWhitespace(new_text.substr(0, space_position), base::TRIM_LEADING, &keyword); - return !keyword.empty() && !autocomplete_controller() - ->keyword_provider() - ->GetKeywordForText(keyword) - .empty(); + return !keyword.empty() && + !autocomplete_controller() + ->keyword_provider() + ->GetKeywordForText( + keyword, controller_->client()->GetTemplateURLService()) + .empty(); } // static
diff --git a/components/optimization_guide/core/model_execution/feature_keys.h b/components/optimization_guide/core/model_execution/feature_keys.h index c2b480d..6638044 100644 --- a/components/optimization_guide/core/model_execution/feature_keys.h +++ b/components/optimization_guide/core/model_execution/feature_keys.h
@@ -42,6 +42,8 @@ proto::ModelExecutionFeature::MODEL_EXECUTION_FEATURE_SCAM_DETECTION, kPermissionsAi = proto::ModelExecutionFeature::MODEL_EXECUTION_FEATURE_PERMISSIONS_AI, + kWritingAssistanceApi = proto::ModelExecutionFeature:: + MODEL_EXECUTION_FEATURE_WRITING_ASSISTANCE_API, }; inline std::ostream& operator<<(std::ostream& out, @@ -77,11 +79,13 @@ return out << "ScamDetection"; case ModelBasedCapabilityKey::kPermissionsAi: return out << "PermissionsAi"; + case ModelBasedCapabilityKey::kWritingAssistanceApi: + return out << "WritingAssistanceApi"; } return out; } -inline constexpr std::array<ModelBasedCapabilityKey, 14> +inline constexpr std::array<ModelBasedCapabilityKey, 16> kAllModelBasedCapabilityKeys = { ModelBasedCapabilityKey::kCompose, ModelBasedCapabilityKey::kTabOrganization, @@ -97,6 +101,8 @@ ModelBasedCapabilityKey::kBlingPrototyping, ModelBasedCapabilityKey::kPasswordChangeSubmission, ModelBasedCapabilityKey::kScamDetection, + ModelBasedCapabilityKey::kPermissionsAi, + ModelBasedCapabilityKey::kWritingAssistanceApi, }; // A "real" feature implemented by a model-based capability. @@ -165,11 +171,14 @@ return ModelBasedCapabilityKey::kBlingPrototyping; case proto::ModelExecutionFeature:: MODEL_EXECUTION_FEATURE_PASSWORD_CHANGE_SUBMISSION: - return ModelBasedCapabilityKey::kPasswordChangeSubmission; + return ModelBasedCapabilityKey::kPasswordChangeSubmission; case proto::ModelExecutionFeature::MODEL_EXECUTION_FEATURE_SCAM_DETECTION: return ModelBasedCapabilityKey::kScamDetection; case proto::ModelExecutionFeature::MODEL_EXECUTION_FEATURE_PERMISSIONS_AI: return ModelBasedCapabilityKey::kPermissionsAi; + case proto::ModelExecutionFeature:: + MODEL_EXECUTION_FEATURE_WRITING_ASSISTANCE_API: + return ModelBasedCapabilityKey::kWritingAssistanceApi; case proto::ModelExecutionFeature::MODEL_EXECUTION_FEATURE_UNSPECIFIED: NOTREACHED() << "Invalid feature"; } @@ -218,6 +227,9 @@ case ModelBasedCapabilityKey::kPermissionsAi: return proto::ModelExecutionFeature:: MODEL_EXECUTION_FEATURE_PERMISSIONS_AI; + case ModelBasedCapabilityKey::kWritingAssistanceApi: + return proto::ModelExecutionFeature:: + MODEL_EXECUTION_FEATURE_WRITING_ASSISTANCE_API; } }
diff --git a/components/optimization_guide/core/model_execution/model_execution_features.cc b/components/optimization_guide/core/model_execution/model_execution_features.cc index 295b08fa..7c47d83 100644 --- a/components/optimization_guide/core/model_execution/model_execution_features.cc +++ b/components/optimization_guide/core/model_execution/model_execution_features.cc
@@ -155,6 +155,9 @@ return proto::OPTIMIZATION_TARGET_MODEL_EXECUTION_FEATURE_SCAM_DETECTION; case ModelBasedCapabilityKey::kPermissionsAi: return proto::OPTIMIZATION_TARGET_MODEL_EXECUTION_FEATURE_PERMISSIONS_AI; + case ModelBasedCapabilityKey::kWritingAssistanceApi: + return proto:: + OPTIMIZATION_TARGET_MODEL_EXECUTION_FEATURE_WRITING_ASSISTANCE_API; // The below capabilities never support on-device execution. case ModelBasedCapabilityKey::kFormsAnnotations: case ModelBasedCapabilityKey::kFormsPredictions:
diff --git a/components/optimization_guide/core/model_execution/model_execution_fetcher.cc b/components/optimization_guide/core/model_execution/model_execution_fetcher.cc index feacdff3..8b4d873b0 100644 --- a/components/optimization_guide/core/model_execution/model_execution_fetcher.cc +++ b/components/optimization_guide/core/model_execution/model_execution_fetcher.cc
@@ -225,6 +225,7 @@ case ModelBasedCapabilityKey::kScamDetection: case ModelBasedCapabilityKey::kPermissionsAi: case ModelBasedCapabilityKey::kSummarize: + case ModelBasedCapabilityKey::kWritingAssistanceApi: // On-device only feature. NOTREACHED(); }
diff --git a/components/optimization_guide/core/model_execution/model_execution_util.cc b/components/optimization_guide/core/model_execution/model_execution_util.cc index e5914e6..5936c211 100644 --- a/components/optimization_guide/core/model_execution/model_execution_util.cc +++ b/components/optimization_guide/core/model_execution/model_execution_util.cc
@@ -57,6 +57,7 @@ case ModelBasedCapabilityKey::kPasswordChangeSubmission: case ModelBasedCapabilityKey::kScamDetection: case ModelBasedCapabilityKey::kPermissionsAi: + case ModelBasedCapabilityKey::kWritingAssistanceApi: // Do not log requests for these features. return; } @@ -101,6 +102,7 @@ case ModelBasedCapabilityKey::kPasswordChangeSubmission: case ModelBasedCapabilityKey::kPermissionsAi: case ModelBasedCapabilityKey::kScamDetection: + case ModelBasedCapabilityKey::kWritingAssistanceApi: // Do not log responses for these features. return; }
diff --git a/components/optimization_guide/core/model_util.cc b/components/optimization_guide/core/model_util.cc index 630d0491..7306cee 100644 --- a/components/optimization_guide/core/model_util.cc +++ b/components/optimization_guide/core/model_util.cc
@@ -140,6 +140,9 @@ return "ModelExecutionFeatureScamDetection"; case proto::OPTIMIZATION_TARGET_MODEL_EXECUTION_FEATURE_PERMISSIONS_AI: return "ModelExecutionFeaturePermissionsAi"; + case proto:: + OPTIMIZATION_TARGET_MODEL_EXECUTION_FEATURE_WRITING_ASSISTANCE_API: + return "ModelExecutionFeatureWritingAssistanceApi"; case proto::OPTIMIZATION_TARGET_EXPERIMENTAL_EMBEDDER: return "ExperimentalEmbedder"; case proto::OPTIMIZATION_TARGET_SEGMENTATION_FEDCM_USER:
diff --git a/components/optimization_guide/core/optimization_guide_util.cc b/components/optimization_guide/core/optimization_guide_util.cc index bb70bdd..82a7640a 100644 --- a/components/optimization_guide/core/optimization_guide_util.cc +++ b/components/optimization_guide/core/optimization_guide_util.cc
@@ -102,6 +102,9 @@ return "ScamDetection"; case proto::ModelExecutionFeature::MODEL_EXECUTION_FEATURE_PERMISSIONS_AI: return "PermissionsAi"; + case proto::ModelExecutionFeature:: + MODEL_EXECUTION_FEATURE_WRITING_ASSISTANCE_API: + return "WritingAssistanceApi"; case proto::ModelExecutionFeature::MODEL_EXECUTION_FEATURE_UNSPECIFIED: return "Unknown"; // Must be in sync with the ModelExecutionFeature variant in
diff --git a/components/optimization_guide/proto/BUILD.gn b/components/optimization_guide/proto/BUILD.gn index d5707c5..f188937 100644 --- a/components/optimization_guide/proto/BUILD.gn +++ b/components/optimization_guide/proto/BUILD.gn
@@ -36,6 +36,7 @@ "features/tab_organization.proto", "features/text_safety.proto", "features/wallpaper_search.proto", + "features/writing_assistance_api.proto", "hint_cache.proto", "hints.proto", "history_query_intent_model_metadata.proto",
diff --git a/components/optimization_guide/proto/features/feature_proto_registry.proto b/components/optimization_guide/proto/features/feature_proto_registry.proto index 8f2b791a..25d560d 100644 --- a/components/optimization_guide/proto/features/feature_proto_registry.proto +++ b/components/optimization_guide/proto/features/feature_proto_registry.proto
@@ -19,6 +19,7 @@ import public "components/optimization_guide/proto/features/scam_detection.proto"; import public "components/optimization_guide/proto/features/summarize.proto"; import public "components/optimization_guide/proto/features/tab_organization.proto"; +import public "components/optimization_guide/proto/features/writing_assistance_api.proto"; // Extra LoggingData message for using the Test capability on-device. message TestLoggingData { @@ -43,4 +44,5 @@ SummarizeLoggingData f = 6; optimization_guide.proto.TabOrganizationLoggingData g = 7; optimization_guide.proto.ScamDetectionLoggingData h = 8; + optimization_guide.proto.WritingAssistanceApiLoggingData i = 9; }
diff --git a/components/optimization_guide/proto/model_execution.proto b/components/optimization_guide/proto/model_execution.proto index 1601509..85e98aa 100644 --- a/components/optimization_guide/proto/model_execution.proto +++ b/components/optimization_guide/proto/model_execution.proto
@@ -76,4 +76,5 @@ MODEL_EXECUTION_FEATURE_PASSWORD_CHANGE_SUBMISSION = 14; MODEL_EXECUTION_FEATURE_SCAM_DETECTION = 15; MODEL_EXECUTION_FEATURE_PERMISSIONS_AI = 17; + MODEL_EXECUTION_FEATURE_WRITING_ASSISTANCE_API = 18; }
diff --git a/components/optimization_guide/proto/models.proto b/components/optimization_guide/proto/models.proto index 9063d3b..db48b03 100644 --- a/components/optimization_guide/proto/models.proto +++ b/components/optimization_guide/proto/models.proto
@@ -244,6 +244,8 @@ OPTIMIZATION_TARGET_EXPERIMENTAL_EMBEDDER = 57; // Target for segmentation: FedCM user. OPTIMIZATION_TARGET_SEGMENTATION_FEDCM_USER = 58; + // Target for Writing Assistance APIs (Writer and Rewriter). + OPTIMIZATION_TARGET_MODEL_EXECUTION_FEATURE_WRITING_ASSISTANCE_API = 59; } // The model engine versions that can be used to do model inference.
diff --git a/components/page_info/android/java/src/org/chromium/components/page_info/ConnectionInfoView.java b/components/page_info/android/java/src/org/chromium/components/page_info/ConnectionInfoView.java index faa10d7..96d0823 100644 --- a/components/page_info/android/java/src/org/chromium/components/page_info/ConnectionInfoView.java +++ b/components/page_info/android/java/src/org/chromium/components/page_info/ConnectionInfoView.java
@@ -246,8 +246,7 @@ } @Override - public void destroy() { - super.destroy(); + public void onDestroy() { dismiss(DialogDismissalCause.UNKNOWN); } };
diff --git a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoController.java b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoController.java index 08467ae..41cabf3 100644 --- a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoController.java +++ b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoController.java
@@ -324,8 +324,7 @@ } @Override - public void destroy() { - super.destroy(); + public void onDestroy() { // Force the dialog to close immediately in case the destroy was from Chrome // quitting. PageInfoController.this.destroy();
diff --git a/components/passage_embeddings/passage_embeddings_service_controller.cc b/components/passage_embeddings/passage_embeddings_service_controller.cc index db47563..cc7bfbe 100644 --- a/components/passage_embeddings/passage_embeddings_service_controller.cc +++ b/components/passage_embeddings/passage_embeddings_service_controller.cc
@@ -59,6 +59,11 @@ bool PassageEmbeddingsServiceController::MaybeUpdateModelInfo( base::optional_ref<const optimization_guide::ModelInfo> model_info) { + // Got the same version again. Do not run through rest of logic. + if (model_info && model_version_ == model_info->GetVersion()) { + return true; + } + // Reset everything, so if the model info is invalid, the service controller // would stop accepting requests. embeddings_model_path_.clear(); @@ -143,7 +148,7 @@ if (!EmbedderReady()) { VLOG(1) << "Missing model path: embeddings='" << embeddings_model_path_ << "'; sp='" << sp_model_path_ << "'"; - std::move(callback).Run({}, ComputeEmbeddingsStatus::KModelUnavailable); + std::move(callback).Run({}, ComputeEmbeddingsStatus::kModelUnavailable); return; } @@ -176,7 +181,7 @@ std::vector<mojom::PassageEmbeddingsResultPtr> results) { auto status = results.empty() ? ComputeEmbeddingsStatus::kExecutionFailure - : ComputeEmbeddingsStatus::KSuccess; + : ComputeEmbeddingsStatus::kSuccess; std::move(callback).Run(std::move(results), status); }, std::move(callback)));
diff --git a/components/passage_embeddings/passage_embeddings_types.h b/components/passage_embeddings/passage_embeddings_types.h index c7e5c435..8593b49b 100644 --- a/components/passage_embeddings/passage_embeddings_types.h +++ b/components/passage_embeddings/passage_embeddings_types.h
@@ -51,10 +51,10 @@ // The status of an embeddings generation attempt. enum class ComputeEmbeddingsStatus { // Embeddings are generated successfully. - KSuccess = 0, + kSuccess = 0, // The model files required for generation are not available. - KModelUnavailable = 1, + kModelUnavailable = 1, // Failure occurred during model execution. kExecutionFailure = 2, @@ -62,7 +62,7 @@ // The generation request was skipped. This could happen if the embeddings // request for a user query, which may have been obsolete (by a newer user // query) by the time the embedder is free. - KSkipped = 3, + kSkipped = 3, }; } // namespace passage_embeddings
diff --git a/components/permissions/features.cc b/components/permissions/features.cc index f4cfbcd..9ea175d 100644 --- a/components/permissions/features.cc +++ b/components/permissions/features.cc
@@ -49,6 +49,10 @@ "PermissionPredictionsV3", base::FEATURE_ENABLED_BY_DEFAULT); +BASE_FEATURE(kPermissionsAIv1, + "PermissionsAIv1", + base::FEATURE_DISABLED_BY_DEFAULT); + // Controls whether to trigger showing a HaTS survey, with the given // `probability` and `trigger_id`. The `probability` parameter is defined and // handled by the HatsService itself. If the parameter
diff --git a/components/permissions/features.h b/components/permissions/features.h index 9d77982..f982994 100644 --- a/components/permissions/features.h +++ b/components/permissions/features.h
@@ -40,6 +40,9 @@ BASE_DECLARE_FEATURE(kPermissionPredictionsV3); COMPONENT_EXPORT(PERMISSIONS_COMMON) +BASE_DECLARE_FEATURE(kPermissionsAIv1); + +COMPONENT_EXPORT(PERMISSIONS_COMMON) BASE_DECLARE_FEATURE(kPermissionsPromptSurvey); COMPONENT_EXPORT(PERMISSIONS_COMMON)
diff --git a/components/resources/BUILD.gn b/components/resources/BUILD.gn index 66d60e9..2865192 100644 --- a/components/resources/BUILD.gn +++ b/components/resources/BUILD.gn
@@ -42,6 +42,10 @@ "../user_actions_ui/resources:resources", "../version_ui/resources:resources", ] + + if (is_ios) { + public_deps += [ "../management/resources:resources" ] + } } grit("components_resources") {
diff --git a/components/resources/components_resources.grd b/components/resources/components_resources.grd index aab3659..274286a 100644 --- a/components/resources/components_resources.grd +++ b/components/resources/components_resources.grd
@@ -16,7 +16,6 @@ <part file="about_ui_resources.grdp" /> <part file="commerce_resources.grdp" /> <part file="dom_distiller_resources.grdp" /> - <part file="management_resources.grdp" /> <part file="neterror_resources.grdp" /> <part file="ntp_tiles_resources.grdp" /> <part file="pdf_resources.grdp" />
diff --git a/components/resources/management_resources.grdp b/components/resources/management_resources.grdp deleted file mode 100644 index 4bbf388..0000000 --- a/components/resources/management_resources.grdp +++ /dev/null
@@ -1,6 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<grit-part> - <include name="IDR_MOBILE_MANAGEMENT_CSS" file="../management/resources/management.css" preprocess="true" type="BINDATA" /> - <include name="IDR_MOBILE_MANAGEMENT_HTML" file="../management/resources/management.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" /> - <include name="IDR_MOBILE_MANAGEMENT_JS" file="../management/resources/management.js" type="BINDATA" compress="gzip" /> -</grit-part>
diff --git a/components/services/storage/dom_storage/local_storage_impl_unittest.cc b/components/services/storage/dom_storage/local_storage_impl_unittest.cc index 7c8c7939..3b442cb 100644 --- a/components/services/storage/dom_storage/local_storage_impl_unittest.cc +++ b/components/services/storage/dom_storage/local_storage_impl_unittest.cc
@@ -1017,13 +1017,7 @@ EXPECT_EQ(value, result); } -// TODO(crbug.com/388544206): Flaky on Mac13. -#if BUILDFLAG(IS_MAC) -#define MAYBE_RecreateOnCommitFailure DISABLED_RecreateOnCommitFailure -#else -#define MAYBE_RecreateOnCommitFailure RecreateOnCommitFailure -#endif -TEST_F(LocalStorageImplTest, MAYBE_RecreateOnCommitFailure) { +TEST_F(LocalStorageImplTest, RecreateOnCommitFailure) { std::optional<base::RunLoop> open_loop; std::optional<base::RunLoop> destruction_loop; size_t num_database_open_requests = 0; @@ -1096,12 +1090,14 @@ size_t values_written = 0; while (area1.is_connected()) { // Every write needs to be different to make sure there actually is a + // change to commit. value[0]++; - area1->Put(key, value, std::nullopt, "source", base::DoNothing()); - // Can't rely on the return callback for `Put()` since there should be an - // error. + area1->Put(key, value, std::nullopt, "source", + base::BindLambdaForTesting([&](bool success) { + EXPECT_TRUE(success); + values_written++; + })); area1.FlushForTesting(); - ++values_written; // And we need to flush after every change. Otherwise changes get batched up // and only one commit is done some time later. context()->FlushStorageKeyForTesting(blink::StorageKey(
diff --git a/components/variations/BUILD.gn b/components/variations/BUILD.gn index 6e23d913..2eb17c3 100644 --- a/components/variations/BUILD.gn +++ b/components/variations/BUILD.gn
@@ -114,6 +114,14 @@ ] } + if (is_android) { + sources += [ + "android/variations_associated_data_android.cc", + "android/variations_seed_bridge.cc", + "android/variations_seed_bridge.h", + ] + } + if (is_chromeos) { sources += [ "variations_crash_keys_chromeos.cc", @@ -140,11 +148,7 @@ ] if (is_android) { - sources += [ - "android/variations_seed_bridge.cc", - "android/variations_seed_bridge.h", - ] - deps += [ "//components/variations/android:variations_seed_jni" ] + deps += [ "//components/variations/android:variations_jni" ] } if (is_chromeos) { @@ -156,15 +160,6 @@ } if (is_android) { - static_library("variations_associated_data") { - sources = [ "android/variations_associated_data_android.cc" ] - deps = [ - ":variations", - "//components/variations/android:variations_data_jni", - "//components/variations/net", - ] - } - java_cpp_strings("java_switches_srcjar") { # External code should depend on ":variations_java" instead. visibility = [ ":*" ]
diff --git a/components/variations/android/BUILD.gn b/components/variations/android/BUILD.gn index 6dbdd640..8fb1ab1 100644 --- a/components/variations/android/BUILD.gn +++ b/components/variations/android/BUILD.gn
@@ -5,13 +5,10 @@ import("//build/config/android/rules.gni") import("//third_party/jni_zero/jni_zero.gni") -generate_jni("variations_seed_jni") { - sources = [ "java/src/org/chromium/components/variations/firstrun/VariationsSeedBridge.java" ] -} - -generate_jni("variations_data_jni") { +generate_jni("variations_jni") { sources = [ "java/src/org/chromium/components/variations/VariationsAssociatedData.java", + "java/src/org/chromium/components/variations/firstrun/VariationsSeedBridge.java", ] } @@ -27,10 +24,7 @@ "//third_party/jni_zero:jni_zero_java", ] - srcjar_deps = [ - ":variations_data_jni", - ":variations_seed_jni", - ] + srcjar_deps = [ ":variations_jni" ] sources = [ "java/src/org/chromium/components/variations/NormalizedMurmurHashEntropyProvider.java", "java/src/org/chromium/components/variations/VariationsAssociatedData.java",
diff --git a/components/variations/android/java/src/org/chromium/components/variations/VariationsAssociatedData.java b/components/variations/android/java/src/org/chromium/components/variations/VariationsAssociatedData.java index bfbb226..fdbd299d 100644 --- a/components/variations/android/java/src/org/chromium/components/variations/VariationsAssociatedData.java +++ b/components/variations/android/java/src/org/chromium/components/variations/VariationsAssociatedData.java
@@ -28,14 +28,6 @@ return VariationsAssociatedDataJni.get().getVariationParamValue(trialName, paramName); } - /** - * Get a HashMap with the value of a space-separated string containing the list of current - * active variations (as would be reported in the |variation_id| repeated field of the - * ClientVariations proto) for a given ID collection. See more at - * `VariationsIdsProvider::GetVariationsString()`. - * - * @return A HashMap with value containing the current active variations. - */ public static HashMap<String, String> getFeedbackMap() { HashMap<String, String> map = new HashMap<String, String>(); map.put("Chrome Variations", VariationsAssociatedDataJni.get().getFeedbackVariations()); @@ -43,24 +35,11 @@ } /** - * Get the encrypted variations state. Variations state is the commandline variations that a - * person can pass in to Chrome, which specifies Chrome features' on or off states. See more at - * `VariationsCommandLine::EncryptToString()` - * - * @return A HashMap with value containing the encrypted variations state. - */ - public static HashMap<String, String> getVariationsStateFeedbackMap() { - HashMap<String, String> map = new HashMap<String, String>(); - map.put("Chrome Variations State", VariationsAssociatedDataJni.get().getVariationsState()); - return map; - } - - /** * Returns the list of Google App variations from active finch field trials. - * - * @return A space separated list of ids with leading and trailing space. e.g. " 123 456 ". - * IMPORTANT: This string is only approved for integrations with the Android Google App and - * must receive a privacy review before extending to other apps. + * @return A space separated list of ids with leading and trailing space. + * For example, " 123 456 ". + * IMPORTANT: This string is only approved for integrations with the Android + * Google App and must receive a privacy review before extending to other apps. */ public static String getGoogleAppVariations() { String variations = VariationsAssociatedDataJni.get().getGoogleAppVariations(); @@ -73,8 +52,6 @@ String getFeedbackVariations(); - String getVariationsState(); - String getGoogleAppVariations(); } }
diff --git a/components/variations/android/variations_associated_data_android.cc b/components/variations/android/variations_associated_data_android.cc index f9ce88e3..3b81de1 100644 --- a/components/variations/android/variations_associated_data_android.cc +++ b/components/variations/android/variations_associated_data_android.cc
@@ -5,14 +5,12 @@ #include <string> #include "base/android/jni_string.h" -#include "base/base64.h" #include "base/metrics/field_trial_params.h" -#include "base/metrics/histogram_functions.h" -#include "components/variations/net/variations_command_line.h" +#include "components/variations/variations_associated_data.h" #include "components/variations/variations_ids_provider.h" // Must come after all headers that specialize FromJniType() / ToJniType(). -#include "components/variations/android/variations_data_jni/VariationsAssociatedData_jni.h" +#include "components/variations/android/variations_jni/VariationsAssociatedData_jni.h" using base::android::ConvertJavaStringToUTF8; using base::android::ConvertUTF8ToJavaString; @@ -40,24 +38,6 @@ return ConvertUTF8ToJavaString(env, values); } -ScopedJavaLocalRef<jstring> JNI_VariationsAssociatedData_GetVariationsState( - JNIEnv* env) { - if (!base::FeatureList::IsEnabled(variations::kFeedbackIncludeVariations)) { - return nullptr; - } - std::vector<uint8_t> ciphertext; - const auto status = - variations::VariationsCommandLine::GetForCurrentProcess().EncryptToString( - &ciphertext); - base::UmaHistogramEnumeration("Variations.VariationsStateEncryptionStatus", - status); - if (status != variations::VariationsStateEncryptionStatus::kSuccess) { - return nullptr; - } - std::string value = base::Base64Encode(ciphertext); - return ConvertUTF8ToJavaString(env, value); -} - ScopedJavaLocalRef<jstring> JNI_VariationsAssociatedData_GetGoogleAppVariations( JNIEnv* env) { const std::string values =
diff --git a/components/variations/android/variations_seed_bridge.cc b/components/variations/android/variations_seed_bridge.cc index 9240ddd..39db2c3 100644 --- a/components/variations/android/variations_seed_bridge.cc +++ b/components/variations/android/variations_seed_bridge.cc
@@ -14,7 +14,7 @@ #include "base/time/time.h" // Must come after all headers that specialize FromJniType() / ToJniType(). -#include "components/variations/android/variations_seed_jni/VariationsSeedBridge_jni.h" +#include "components/variations/android/variations_jni/VariationsSeedBridge_jni.h" using base::android::AttachCurrentThread; using base::android::ConvertJavaStringToUTF8;
diff --git a/components/viz/common/DEPS b/components/viz/common/DEPS index 0f19adf..1e1ae64 100644 --- a/components/viz/common/DEPS +++ b/components/viz/common/DEPS
@@ -35,6 +35,7 @@ "+gpu/ipc/gl_in_process_context.h", ], "features.cc" : [ + "+gpu/config/gpu_driver_bug_workaround_type.h", "+gpu/config/gpu_finch_features.h", "+gpu/config/gpu_switches.h", "+media/media_buildflags.h",
diff --git a/components/viz/common/features.cc b/components/viz/common/features.cc index f8b31e1..c75501a 100644 --- a/components/viz/common/features.cc +++ b/components/viz/common/features.cc
@@ -17,6 +17,7 @@ #include "build/build_config.h" #include "components/viz/common/switches.h" #include "components/viz/common/viz_utils.h" +#include "gpu/config/gpu_driver_bug_workaround_type.h" #include "gpu/config/gpu_finch_features.h" #include "gpu/config/gpu_switches.h" #include "media/media_buildflags.h" @@ -25,6 +26,10 @@ #include "base/android/build_info.h" #endif +#if BUILDFLAG(IS_WIN) +#include "base/win/windows_version.h" +#endif // BUILDFLAG(IS_WIN) + namespace features { #if BUILDFLAG(IS_ANDROID) @@ -129,9 +134,16 @@ // If enabled, Chromium will utilize DXGI SwapChains and DComp visuals as the // software output device rather than GDI bit block transfer to the redirection -// surface. -BASE_FEATURE(kUseSwapChainForSoftwareRendering, - "UseSwapChainForSoftwareRendering", +// bitmap. Additionally, the redirection bitmap will be removed and replaced +// with the native acrylic background effect on Win11. Since the browser window +// appears before the GPU process is able to draw content into it, the acrylic +// effect gives the user feedback that a window is present and content is +// coming. Without the acrylic effect a transparent window will appear with a 1 +// pixel border that eats all mouse clicks; not a good user experience. Further, +// the acylic effect will appear in uncovered regions of the window when the +// user resizes the window. +BASE_FEATURE(kRemoveRedirectionBitmap, + "RemoveRedirectionBitmap", base::FEATURE_DISABLED_BY_DEFAULT); #endif @@ -674,6 +686,23 @@ } return base::FeatureList::IsEnabled(kDCompSurfacesForDelegatedInk); } + +bool ShouldRemoveRedirectionBitmap() { + // Redirection bitmap should not be removed if Direct Composition is + // disabled. On devices with DComp disabled, ANGLE draws to the redirection + // bitmap via a blit swap chain. DWM_SYSTEMBACKDROP_TYPE is only available + // on Win11 22H2+, therefore limit the bitmap removal to those versions or + // higher so that an appropriate background replacement is available. + // Note: the DISABLE_DIRECT_COMPOSITION command line check is a workaround for + // https://crbug.com/40276881. Additionally, Direct Composition is only + // blocklisted for Windows 10 so this feature would not be enabled at the same + // time. + return base::win::GetVersion() >= base::win::Version::WIN11_22H2 && + !base::CommandLine::ForCurrentProcess()->HasSwitch( + gpu::GpuDriverBugWorkaroundTypeToString( + gpu::DISABLE_DIRECT_COMPOSITION)) && + base::FeatureList::IsEnabled(kRemoveRedirectionBitmap); +} #endif #if BUILDFLAG(IS_ANDROID)
diff --git a/components/viz/common/features.h b/components/viz/common/features.h index db2b37a..0618c36 100644 --- a/components/viz/common/features.h +++ b/components/viz/common/features.h
@@ -50,7 +50,7 @@ #if BUILDFLAG(IS_WIN) VIZ_COMMON_EXPORT BASE_DECLARE_FEATURE(kDCompSurfacesForDelegatedInk); -VIZ_COMMON_EXPORT BASE_DECLARE_FEATURE(kUseSwapChainForSoftwareRendering); +VIZ_COMMON_EXPORT BASE_DECLARE_FEATURE(kRemoveRedirectionBitmap); #endif VIZ_COMMON_EXPORT BASE_DECLARE_FEATURE(kRenderPassDrawnRect); VIZ_COMMON_EXPORT BASE_DECLARE_FEATURE(kRecordSkPicture); @@ -156,6 +156,7 @@ VIZ_COMMON_EXPORT bool IsDelegatedCompositingEnabled(); #if BUILDFLAG(IS_WIN) VIZ_COMMON_EXPORT bool ShouldUseDCompSurfacesForDelegatedInk(); +VIZ_COMMON_EXPORT bool ShouldRemoveRedirectionBitmap(); #endif VIZ_COMMON_EXPORT bool IsUsingVizFrameSubmissionForWebView(); VIZ_COMMON_EXPORT bool IsUsingPreferredIntervalForVideo();
diff --git a/components/viz/service/display_embedder/software_output_device_win.cc b/components/viz/service/display_embedder/software_output_device_win.cc index ac6fe5e..4d6cc977 100644 --- a/components/viz/service/display_embedder/software_output_device_win.cc +++ b/components/viz/service/display_embedder/software_output_device_win.cc
@@ -176,8 +176,7 @@ HWND& child_hwnd) { child_hwnd = NULL; - if (base::FeatureList::IsEnabled( - features::kUseSwapChainForSoftwareRendering)) { + if (features::ShouldRemoveRedirectionBitmap()) { return std::make_unique<SoftwareOutputDeviceWinSwapChain>(hwnd, child_hwnd, backing); }
diff --git a/content/app_shim_remote_cocoa/web_menu_runner_mac.mm b/content/app_shim_remote_cocoa/web_menu_runner_mac.mm index 7741906..1d6d809c 100644 --- a/content/app_shim_remote_cocoa/web_menu_runner_mac.mm +++ b/content/app_shim_remote_cocoa/web_menu_runner_mac.mm
@@ -7,6 +7,7 @@ #include <stddef.h> #include "base/base64.h" +#include "base/mac/mac_util.h" #include "base/strings/sys_string_conversions.h" @interface WebMenuRunner (PrivateAPI) @@ -177,15 +178,21 @@ [_menu cancelTrackingWithoutAnimation]; // Starting with macOS 14, menus were reimplemented with Cocoa (rather than - // with the old Carbon). However, with that reimplementation came a bug - // whereupon using -cancelTrackingWithoutAnimation does not consistently - // immediately cancel the tracking, and leaves associated state remaining - // uncleared for an indeterminate amount of time. If a new tracking session is - // begun before that state is cleared, an NSInternalInconsistencyException is - // thrown. See the discussion on https://crbug.com/1497774 and FB13320260. - // Therefore, on macOS 14+, clear out that state so that a new tracking - // session can begin immediately. - if (@available(macOS 14, *)) { + // with the old Carbon). However, in macOS 14, with that reimplementation came + // a bug whereupon using -cancelTrackingWithoutAnimation did not consistently + // immediately cancel the tracking, and left associated state remaining + // uncleared for an indeterminate amount of time. If a new tracking session + // began before that state was cleared, an NSInternalInconsistencyException + // was thrown. See the discussion on https://crbug.com/40939221 and + // FB13320260. + // + // On macOS 14, therefore, when cancelling synchronously, clear out that state + // so that a new tracking session can begin immediately. + // + // With macOS 15, these global state methods moved from being class methods on + // NSPopupMenuWindow to being instance methods on NSMenuTrackingSession, so + // this workaround is inapplicable. + if (base::mac::MacOSMajorVersion() == 14) { // When running a menu tracking session, the instances of // NSMenuTrackingSession make calls to class methods of NSPopupMenuWindow: //
diff --git a/content/browser/android/web_contents_observer_proxy.cc b/content/browser/android/web_contents_observer_proxy.cc index 6d66969..765f71d 100644 --- a/content/browser/android/web_contents_observer_proxy.cc +++ b/content/browser/android/web_contents_observer_proxy.cc
@@ -70,7 +70,7 @@ void WebContentsObserverProxy::WebContentsDestroyed() { JNIEnv* env = AttachCurrentThread(); // The java side will destroy |this| - Java_WebContentsObserverProxy_destroy(env, java_observer_); + Java_WebContentsObserverProxy_webContentsDestroyed(env, java_observer_); } void WebContentsObserverProxy::RenderFrameCreated(
diff --git a/content/browser/child_process_security_policy_impl.cc b/content/browser/child_process_security_policy_impl.cc index 01dab09..24b8576 100644 --- a/content/browser/child_process_security_policy_impl.cc +++ b/content/browser/child_process_security_policy_impl.cc
@@ -1136,8 +1136,20 @@ } // When the child process has been commanded to request a file:// URL, - // then we grant it the capability for that URL only. - state->second->GrantRequestOfSpecificFile(path); + // then we grant it the capability for that URL only. Canonicalize the path + // via roundtrip to file:// URL so it will match the incoming URL we validate + // against (crbug.com/382645162), except android content:// URLs. +#if BUILDFLAG(IS_ANDROID) + if (path.IsContentUri()) { + state->second->GrantRequestOfSpecificFile(path); + return; + } +#endif + GURL url = net::FilePathToFileURL(path); + base::FilePath canonical_path; + if (net::FileURLToFilePath(url, &canonical_path)) { + state->second->GrantRequestOfSpecificFile(canonical_path); + } } void ChildProcessSecurityPolicyImpl::GrantReadFile(int child_id,
diff --git a/content/browser/private_aggregation/private_aggregation_host.cc b/content/browser/private_aggregation/private_aggregation_host.cc index 1e0dde0..7afc26a 100644 --- a/content/browser/private_aggregation/private_aggregation_host.cc +++ b/content/browser/private_aggregation/private_aggregation_host.cc
@@ -193,8 +193,7 @@ switches::kPrivateAggregationDeveloperMode)), on_report_request_details_received_( std::move(on_report_request_details_received)), - browser_context_(*browser_context) { - CHECK(browser_context); + browser_context_(CHECK_DEREF(browser_context)) { CHECK(!on_report_request_details_received_.is_null()); // `base::Unretained()` is safe as `receiver_set_` is owned by `this`. @@ -292,18 +291,15 @@ if (timeout) { CHECK(timeout->is_positive()); - ReceiverContext* receiver_context_raw_ptr = receiver_set_.GetContext(id); - CHECK(receiver_context_raw_ptr); - - receiver_context_raw_ptr->timeout_timer = - std::make_unique<base::OneShotTimer>(); - - // Passing `base::Unretained(this)` is safe as `this` owns the receiver - // context and the receiver context owns the timer. - receiver_context_raw_ptr->timeout_timer->Start( + ReceiverContext& context = CHECK_DEREF(receiver_set_.GetContext(id)); + context.timeout_timer = std::make_unique<base::OneShotTimer>(); + context.timeout_timer->Start( FROM_HERE, *timeout, - base::BindOnce(&PrivateAggregationHost::OnTimeoutBeforeDisconnect, - base::Unretained(this), id)); + base::BindOnce( + &PrivateAggregationHost::OnTimeoutBeforeDisconnect, + // Passing `base::Unretained(this)` is safe as `this` owns the + // receiver context and the receiver context owns the timer. + base::Unretained(this), id)); } return true; @@ -523,10 +519,8 @@ } void PrivateAggregationHost::OnTimeoutBeforeDisconnect(mojo::ReceiverId id) { - ReceiverContext* receiver_context = receiver_set_.GetContext(id); - CHECK(receiver_context); - - SendReportOnTimeoutOrDisconnect(*receiver_context, + ReceiverContext& receiver_context = CHECK_DEREF(receiver_set_.GetContext(id)); + SendReportOnTimeoutOrDisconnect(receiver_context, /*remaining_timeout=*/base::TimeDelta()); RecordTimeoutResultHistogram(
diff --git a/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java b/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java index 5c0c67d..ff4ac77c 100644 --- a/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java +++ b/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java
@@ -286,7 +286,7 @@ public void clearJavaWebContentsObservers() { // Clear all the Android specific observers. if (mObserverProxy != null) { - mObserverProxy.destroy(); + mObserverProxy.webContentsDestroyed(); mObserverProxy = null; } }
diff --git a/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsObserverProxy.java b/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsObserverProxy.java index c41e825..8a692f5 100644 --- a/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsObserverProxy.java +++ b/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsObserverProxy.java
@@ -505,12 +505,8 @@ finishObserverCall(); } - @Override @CalledByNative - public void destroy() { - // Super destruction semantics (removing the observer from the - // Java-based WebContents) are quite different, so we explicitly avoid - // calling it here. + protected void webContentsDestroyed() { ThreadUtils.assertOnUiThread(); RewindableIterator<WebContentsObserver> observersIterator = mObservers.rewindableIterator(); for (; observersIterator.hasNext(); ) {
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/WebContentsObserver.java b/content/public/android/java/src/org/chromium/content_public/browser/WebContentsObserver.java index 8997018..7ccf89e 100644 --- a/content/public/android/java/src/org/chromium/content_public/browser/WebContentsObserver.java +++ b/content/public/android/java/src/org/chromium/content_public/browser/WebContentsObserver.java
@@ -5,6 +5,7 @@ package org.chromium.content_public.browser; import androidx.annotation.IntDef; +import androidx.annotation.NonNull; import org.chromium.base.TerminationStatus; import org.chromium.blink.mojom.ViewportFit; @@ -24,10 +25,10 @@ @NullMarked public abstract class WebContentsObserver { private @Nullable WebContents mWebContents; + private boolean mHasBeenDestroyed; - public WebContentsObserver(WebContents webContents) { - mWebContents = webContents; - webContents.addObserver(this); + public WebContentsObserver(@NonNull WebContents webContents) { + observe(webContents); } /** Return the web contents associated with the observer. */ @@ -243,12 +244,46 @@ /** Called when a MediaSession is created for the WebContents. */ public void mediaSessionCreated(MediaSession mediaSession) {} - /** Stop observing the web contents and clean up associated references. */ - public void destroy() { - if (mWebContents == null) return; - final WebContents webContents = mWebContents; - mWebContents = null; - webContents.removeObserver(this); + /** + * Notified when {@link #destroy()} has been triggered. This can be the result of the {@link + * #getWebContents()} being destroyed, or because an embedder has triggered {@link #onDestroy()} + * manually. + * + * <p>As an embedder, this method should be overridden and not called directly. + */ + protected void onDestroy() {} + + /** + * To be called when this object should no longer observe any WebContents and also to carry out + * any cleanup handled in {@link #onDestroy}. + * + * <p>Only the first call to {@link #destroy()}} will trigger {@link #onDestroy()} and + * unregister this observer from the linked {@link #getWebContents()} (if one had been + * registered). + */ + public final void destroy() { + if (mHasBeenDestroyed) return; + mHasBeenDestroyed = true; + + onDestroy(); + + observe(null); + } + + /** + * Updates the {@link WebContents} that this class is observing, and if null, stops observing + * any updates. + * + * @param webContents The WebContents to observe (or null to stop observing). + */ + public final void observe(@Nullable WebContents webContents) { + if (mWebContents == webContents) return; + if (mWebContents != null) mWebContents.removeObserver(this); + mWebContents = webContents; + if (mWebContents != null) { + assert !mHasBeenDestroyed; + mWebContents.addObserver(this); + } } protected WebContentsObserver() {}
diff --git a/extensions/browser/extension_registrar.cc b/extensions/browser/extension_registrar.cc index dde230b..1559ee2 100644 --- a/extensions/browser/extension_registrar.cc +++ b/extensions/browser/extension_registrar.cc
@@ -10,6 +10,7 @@ #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" #include "base/metrics/histogram_functions.h" +#include "base/metrics/histogram_macros.h" #include "base/notreached.h" #include "build/chromeos_buildflags.h" #include "content/public/browser/browser_context.h" @@ -467,6 +468,81 @@ delegate_->LoadExtensionForReload(extension_id, path, load_error_behavior); } +bool ExtensionRegistrar::UninstallExtension( + // "transient" because the process of uninstalling may cause the reference + // to become invalid. Instead, use |extension->id()|. + const std::string& transient_extension_id, + UninstallReason reason, + std::u16string* error, + base::OnceClosure done_callback) { + CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + + scoped_refptr<const Extension> extension = + registry_->GetInstalledExtension(transient_extension_id); + + // Callers should not send us nonexistent extensions. + CHECK(extension.get()); + + ManagementPolicy* by_policy = extension_system_->management_policy(); + // Policy change which triggers an uninstall will always set + // |external_uninstall| to true so this is the only way to uninstall + // managed extensions. + // Shared modules being uninstalled will also set |external_uninstall| to true + // so that we can guarantee users don't uninstall a shared module. + // (crbug.com/273300) + // TODO(rdevlin.cronin): This is probably not right. We should do something + // else, like include an enum IS_INTERNAL_UNINSTALL or IS_USER_UNINSTALL so + // we don't do this. + bool external_uninstall = + (reason == UNINSTALL_REASON_INTERNAL_MANAGEMENT) || + (reason == UNINSTALL_REASON_COMPONENT_REMOVED) || + (reason == UNINSTALL_REASON_MIGRATED) || + (reason == UNINSTALL_REASON_REINSTALL) || + (reason == UNINSTALL_REASON_ORPHANED_EXTERNAL_EXTENSION) || + (reason == UNINSTALL_REASON_ORPHANED_SHARED_MODULE); + if (!external_uninstall && + (!by_policy->UserMayModifySettings(extension.get(), error) || + by_policy->MustRemainInstalled(extension.get(), error))) { + registry_->TriggerOnUninstallationDenied(extension.get()); + return false; + } + + // Prepare to uninstall the extension. + delegate_->PreUninstallExtension(extension.get()); + + UMA_HISTOGRAM_ENUMERATION("Extensions.UninstallType", extension->GetType(), + 100); + + // Unload before doing more cleanup to ensure that nothing is hanging on to + // any of these resources. + RemoveExtension(extension->id(), UnloadedExtensionReason::UNINSTALL); + + // `UnloadExtension` ignores extensions that are `BLOCKLISTED` or `BLOCKED` + if (registry_->blocklisted_extensions().Contains(extension->id())) { + registry_->RemoveBlocklisted(extension->id()); + } + if (registry_->blocked_extensions().Contains(extension->id())) { + registry_->RemoveBlocked(extension->id()); + } + + // Perform the necessary clean up after the extension is un-registered. + delegate_->PostUninstallExtension(extension, std::move(done_callback)); + + UntrackTerminatedExtension(extension->id()); + + // Notify interested parties that we've uninstalled this extension. + registry_->TriggerOnUninstalled(extension.get(), reason); + + // Perform the necessary clean up work after extension un-installation event + // has been notified to all observers. + delegate_->PostNotifyUninstallExtension(extension.get()); + + extension_prefs_->OnExtensionUninstalled( + extension->id(), extension->location(), external_uninstall); + + return true; +} + bool ExtensionRegistrar::CanBlockExtension(const Extension* extension) const { DCHECK(extension); return extension->location() != ManifestLocation::kComponent &&
diff --git a/extensions/browser/extension_registrar.h b/extensions/browser/extension_registrar.h index fc66656..0960ab6 100644 --- a/extensions/browser/extension_registrar.h +++ b/extensions/browser/extension_registrar.h
@@ -76,6 +76,22 @@ virtual void PostDeactivateExtension( scoped_refptr<const Extension> extension) = 0; + // Called before |extension| is uninstalled. Performs the operations + // necessary before |extension| is uninstalled. + virtual void PreUninstallExtension( + scoped_refptr<const Extension> extension) = 0; + + // Called after |extension| is uninstalled. Performs the operations to + // clean up the extensions files, etc. + virtual void PostUninstallExtension( + scoped_refptr<const Extension> extension, + base::OnceClosure done_callback) = 0; + + // Called after |extension| un-installation event has been notified to + // all observers. + virtual void PostNotifyUninstallExtension( + scoped_refptr<const Extension> extension) = 0; + // Given an extension ID and/or path, loads that extension as a reload. virtual void LoadExtensionForReload( const ExtensionId& extension_id, @@ -158,6 +174,24 @@ void ReloadExtension(const ExtensionId extension_id, LoadErrorBehavior load_error_behavior); + // Uninstalls the specified extension. Callers should only call this method + // with extensions that exist. |reason| lets the caller specify why the + // extension is uninstalled. + // Note: this method synchronously removes the extension from the + // set of installed extensions stored in the ExtensionRegistry, but will + // asynchronously remove site-related data and the files stored on disk. + // Returns true if an uninstall was successfully triggered; this can fail if + // the extension cannot be uninstalled (such as a policy force-installed + // extension). + // |done_callback| is synchronously invoked once the site-related data and the + // files stored on disk are removed. If such a callback is not needed, pass in + // a null callback (base::NullCallback()). + bool UninstallExtension( + const std::string& extension_id, + UninstallReason reason, + std::u16string* error, + base::OnceClosure done_callback = base::NullCallback()); + // TODO(michaelpg): Add methods for blocklisting and blocking extensions. // Helper method to determine if an extension can be blocked.
diff --git a/extensions/browser/extension_registrar_unittest.cc b/extensions/browser/extension_registrar_unittest.cc index b616f5e..dfd7d09 100644 --- a/extensions/browser/extension_registrar_unittest.cc +++ b/extensions/browser/extension_registrar_unittest.cc
@@ -73,6 +73,13 @@ void(scoped_refptr<const Extension> extension)); MOCK_METHOD1(PostDeactivateExtension, void(scoped_refptr<const Extension> extension)); + MOCK_METHOD1(PreUninstallExtension, + void(scoped_refptr<const Extension> extension)); + MOCK_METHOD2(PostUninstallExtension, + void(scoped_refptr<const Extension> extension, + base::OnceClosure done_callback)); + MOCK_METHOD1(PostNotifyUninstallExtension, + void(scoped_refptr<const Extension> extension)); MOCK_METHOD3(LoadExtensionForReload, void(const ExtensionId& extension_id, const base::FilePath& path,
diff --git a/extensions/shell/browser/shell_extension_loader.cc b/extensions/shell/browser/shell_extension_loader.cc index 853beb01..6d212b2 100644 --- a/extensions/shell/browser/shell_extension_loader.cc +++ b/extensions/shell/browser/shell_extension_loader.cc
@@ -148,6 +148,16 @@ void ShellExtensionLoader::PostDeactivateExtension( scoped_refptr<const Extension> extension) {} +void ShellExtensionLoader::PreUninstallExtension( + scoped_refptr<const Extension> extension) {} + +void ShellExtensionLoader::PostUninstallExtension( + scoped_refptr<const Extension> extension, + base::OnceClosure done_callback) {} + +void ShellExtensionLoader::PostNotifyUninstallExtension( + scoped_refptr<const Extension> extension) {} + void ShellExtensionLoader::LoadExtensionForReload( const ExtensionId& extension_id, const base::FilePath& path,
diff --git a/extensions/shell/browser/shell_extension_loader.h b/extensions/shell/browser/shell_extension_loader.h index bc59ef60..3c3a70b 100644 --- a/extensions/shell/browser/shell_extension_loader.h +++ b/extensions/shell/browser/shell_extension_loader.h
@@ -58,6 +58,11 @@ void PostActivateExtension(scoped_refptr<const Extension> extension) override; void PostDeactivateExtension( scoped_refptr<const Extension> extension) override; + void PreUninstallExtension(scoped_refptr<const Extension> extension) override; + void PostUninstallExtension(scoped_refptr<const Extension> extension, + base::OnceClosure done_callback) override; + void PostNotifyUninstallExtension( + scoped_refptr<const Extension> extension) override; void LoadExtensionForReload( const ExtensionId& extension_id, const base::FilePath& path,
diff --git a/gin/v8_initializer.cc b/gin/v8_initializer.cc index 7fdb3ae..cfbb1bb 100644 --- a/gin/v8_initializer.cc +++ b/gin/v8_initializer.cc
@@ -503,6 +503,7 @@ "--no-js-duplicate-named-groups"); SetV8FlagsIfOverridden(features::kJavaScriptPromiseTry, "--js-promise-try", "--no-js-promise-try"); + SetV8Flags("--js-explicit-resource-management"); if (IsolateHolder::kStrictMode == mode) { SetV8Flags("--use_strict");
diff --git a/gpu/command_buffer/client/DEPS b/gpu/command_buffer/client/DEPS index df80219..0e93d2b2 100644 --- a/gpu/command_buffer/client/DEPS +++ b/gpu/command_buffer/client/DEPS
@@ -6,6 +6,7 @@ "+components/miracle_parameter", "+components/viz/common/resources/shared_image_format.h", "+components/viz/common/resources/shared_image_format_utils.h", + "+mojo/public/cpp/bindings/pending_remote.h", ] specific_include_rules = {
diff --git a/gpu/command_buffer/client/shared_image_interface.cc b/gpu/command_buffer/client/shared_image_interface.cc index 8cd91d29..977a241 100644 --- a/gpu/command_buffer/client/shared_image_interface.cc +++ b/gpu/command_buffer/client/shared_image_interface.cc
@@ -180,6 +180,17 @@ } #endif // BUILDFLAG(IS_WIN) +void SharedImageInterface::CreateSharedImagePool( + const SharedImagePoolId& pool_id, + mojo::PendingRemote<mojom::SharedImagePoolClientInterface> client_remote) { + NOTREACHED(); +} + +void SharedImageInterface::DestroySharedImagePool( + const SharedImagePoolId& pool_id) { + NOTREACHED(); +} + SharedImageInterface::SharedImageMapping::SharedImageMapping() = default; SharedImageInterface::SharedImageMapping::SharedImageMapping( SharedImageInterface::SharedImageMapping&& mapped) = default;
diff --git a/gpu/command_buffer/client/shared_image_interface.h b/gpu/command_buffer/client/shared_image_interface.h index 32e1aa0..5a3f12a 100644 --- a/gpu/command_buffer/client/shared_image_interface.h +++ b/gpu/command_buffer/client/shared_image_interface.h
@@ -18,7 +18,9 @@ #include "gpu/command_buffer/common/shared_image_usage.h" #include "gpu/command_buffer/common/sync_token.h" #include "gpu/gpu_export.h" +#include "gpu/ipc/common/shared_image_pool_client_interface.mojom.h" #include "gpu/ipc/common/surface_handle.h" +#include "mojo/public/cpp/bindings/pending_remote.h" #include "third_party/skia/include/core/SkImageInfo.h" #include "third_party/skia/include/gpu/ganesh/GrTypes.h" #include "ui/gfx/buffer_types.h" @@ -411,6 +413,18 @@ void Release() const; + // Used by client side shared image pool aka SharedImagePool to + // create a service side pool. It also creates a new mojo IPC connection + // between the client and the service side pool so that service side pool + // can communicate with client side pool when needed. + virtual void CreateSharedImagePool( + const SharedImagePoolId& pool_id, + mojo::PendingRemote<mojom::SharedImagePoolClientInterface> client_remote); + + // Called when client side SharedImagePool is destroyed. It will + // in turn destroy the corresponding GPU service side SharedImagePool. + virtual void DestroySharedImagePool(const SharedImagePoolId& pool_id); + protected: friend class base::RefCountedThreadSafe<SharedImageInterface>; virtual ~SharedImageInterface();
diff --git a/gpu/command_buffer/service/shared_image/shared_image_backing.cc b/gpu/command_buffer/service/shared_image/shared_image_backing.cc index 15e3af61..300afb4 100644 --- a/gpu/command_buffer/service/shared_image/shared_image_backing.cc +++ b/gpu/command_buffer/service/shared_image/shared_image_backing.cc
@@ -400,19 +400,6 @@ return !refs_.empty(); } -void SharedImageBacking::OnReadSucceeded() { - AutoLock auto_lock(this); - if (scoped_write_uma_) { - scoped_write_uma_->SetConsumed(); - scoped_write_uma_.reset(); - } -} - -void SharedImageBacking::OnWriteSucceeded() { - AutoLock auto_lock(this); - scoped_write_uma_.emplace(); -} - size_t SharedImageBacking::GetEstimatedSize() const { AutoLock auto_lock(this); return estimated_size_;
diff --git a/gpu/command_buffer/service/shared_image/shared_image_backing.h b/gpu/command_buffer/service/shared_image/shared_image_backing.h index f4d7688..d05801f3 100644 --- a/gpu/command_buffer/service/shared_image/shared_image_backing.h +++ b/gpu/command_buffer/service/shared_image/shared_image_backing.h
@@ -163,11 +163,6 @@ // Returns the memory tracker this backing is registering memory with. const MemoryTracker* GetMemoryTracker() const; - // Notify backing a read access is succeeded - void OnReadSucceeded(); - // Notify backing a write access is succeeded. - void OnWriteSucceeded(); - // This factory is registered when creating backing to help // create intermediate interop backing buffer // and share resource from gl backing buffer to dawn. @@ -392,25 +387,6 @@ mutable std::optional<base::Lock> lock_; private: - class ScopedWriteUMA { - public: - ScopedWriteUMA() = default; - - ScopedWriteUMA(const ScopedWriteUMA&) = delete; - ScopedWriteUMA& operator=(const ScopedWriteUMA&) = delete; - - ~ScopedWriteUMA() { - UMA_HISTOGRAM_BOOLEAN("GPU.SharedImage.ContentConsumed", - content_consumed_); - } - - bool content_consumed() const { return content_consumed_; } - void SetConsumed() { content_consumed_ = true; } - - private: - bool content_consumed_ = false; - }; - const Mailbox mailbox_; const viz::SharedImageFormat format_; const gfx::Size size_; @@ -440,9 +416,6 @@ bool have_context_ GUARDED_BY(lock_) = true; - // A scoped object for recording write UMA. - std::optional<ScopedWriteUMA> scoped_write_uma_ GUARDED_BY(lock_); - // A vector of SharedImageRepresentations which hold references to this // backing. The first reference is considered the owner, and the vector is // ordered by the order in which references were taken.
diff --git a/gpu/command_buffer/service/shared_image/shared_image_factory.cc b/gpu/command_buffer/service/shared_image/shared_image_factory.cc index 1c2ecd2..e33b70e3e 100644 --- a/gpu/command_buffer/service/shared_image/shared_image_factory.cc +++ b/gpu/command_buffer/service/shared_image/shared_image_factory.cc
@@ -493,7 +493,6 @@ << "] size=" << size.ToString() << " usage=" << CreateLabelForSharedImageUsage(usage) << " format=" << format.ToString(); - backing->OnWriteSucceeded(); } } } @@ -531,8 +530,6 @@ << "] with pixels size=" << size.ToString() << " usage=" << CreateLabelForSharedImageUsage(usage) << " format=" << format.ToString(); - - backing->OnWriteSucceeded(); } return RegisterBacking(std::move(backing)); } @@ -589,8 +586,6 @@ << " usage=" << CreateLabelForSharedImageUsage(usage) << " format=" << format.ToString() << " gmb_type=" << GmbTypeToString(gmb_type); - - backing->OnWriteSucceeded(); } return RegisterBacking(std::move(backing), std::move(pool_id)); }
diff --git a/gpu/command_buffer/service/shared_image/shared_image_representation.cc b/gpu/command_buffer/service/shared_image/shared_image_representation.cc index 668b2e6..7205941 100644 --- a/gpu/command_buffer/service/shared_image/shared_image_representation.cc +++ b/gpu/command_buffer/service/shared_image/shared_image_representation.cc
@@ -84,10 +84,8 @@ AccessMode access_mode; if (mode == kReadAccessMode) { access_mode = AccessMode::kRead; - backing()->OnReadSucceeded(); } else { access_mode = AccessMode::kWrite; - backing()->OnWriteSucceeded(); } return std::make_unique<ScopedAccess>( @@ -338,8 +336,6 @@ return nullptr; } - backing()->OnWriteSucceeded(); - return std::make_unique<ScopedGaneshWriteAccess>( base::PassKey<SkiaGaneshImageRepresentation>(), this, std::move(surfaces), std::move(end_state)); @@ -351,8 +347,6 @@ return nullptr; } - backing()->OnWriteSucceeded(); - return std::make_unique<ScopedGaneshWriteAccess>( base::PassKey<SkiaGaneshImageRepresentation>(), this, std::move(promise_image_textures), std::move(end_state)); @@ -509,8 +503,6 @@ return nullptr; } - backing()->OnReadSucceeded(); - return std::make_unique<ScopedGaneshReadAccess>( base::PassKey<SkiaGaneshImageRepresentation>(), this, std::move(promise_image_textures), std::move(end_state)); @@ -590,8 +582,6 @@ return nullptr; } - backing()->OnWriteSucceeded(); - return std::make_unique<ScopedGraphiteWriteAccess>( base::PassKey<SkiaGraphiteImageRepresentation>(), this, std::move(surfaces)); @@ -603,8 +593,6 @@ return nullptr; } - backing()->OnWriteSucceeded(); - return std::make_unique<ScopedGraphiteWriteAccess>( base::PassKey<SkiaGraphiteImageRepresentation>(), this, graphite_textures); @@ -732,8 +720,6 @@ return nullptr; } - backing()->OnReadSucceeded(); - return std::make_unique<ScopedGraphiteReadAccess>( base::PassKey<SkiaGraphiteImageRepresentation>(), this, graphite_textures); @@ -804,8 +790,6 @@ return nullptr; } - backing()->OnReadSucceeded(); - return std::make_unique<ScopedReadAccess>( base::PassKey<OverlayImageRepresentation>(), this, std::move(acquire_fence)); @@ -870,10 +854,8 @@ AccessMode access_mode; if (usage & kWriteUsage) { access_mode = AccessMode::kWrite; - backing()->OnWriteSucceeded(); } else { access_mode = AccessMode::kRead; - backing()->OnReadSucceeded(); } return std::make_unique<ScopedAccess>(
diff --git a/gpu/command_buffer/service/shared_image/shared_image_representation.h b/gpu/command_buffer/service/shared_image/shared_image_representation.h index 1109ba2e..a887278 100644 --- a/gpu/command_buffer/service/shared_image/shared_image_representation.h +++ b/gpu/command_buffer/service/shared_image/shared_image_representation.h
@@ -192,7 +192,6 @@ const Mailbox& mailbox() const { return backing()->mailbox(); } void Update(std::unique_ptr<gfx::GpuFence> in_fence) { backing()->Update(std::move(in_fence)); - backing()->OnWriteSucceeded(); } void SetPurgeable(bool purgeable) { backing()->SetPurgeable(purgeable); } bool CopyToGpuMemoryBuffer() { return backing()->CopyToGpuMemoryBuffer(); }
diff --git a/gpu/ipc/common/BUILD.gn b/gpu/ipc/common/BUILD.gn index d3f2d2d..2a1f8b0 100644 --- a/gpu/ipc/common/BUILD.gn +++ b/gpu/ipc/common/BUILD.gn
@@ -125,6 +125,7 @@ ":gpu_peak_memory", ":interfaces_cpp_sources", ":memory_stats_sources", + ":shared_image_pool_client_interface", ":surface_handle_type", ":vulkan_ycbcr_info", "//ipc", @@ -306,6 +307,19 @@ ] } +mojom("shared_image_pool_client_interface") { + generate_java = true + visibility = [ + "//gpu/*", + "//services/*", + ] + sources = [ "shared_image_pool_client_interface.mojom" ] + deps = [ "//mojo/public/mojom/base" ] + export_class_attribute = "GPU_EXPORT" + export_header = "gpu/gpu_export.h" + cpp_configs = [ "//gpu:gpu_implementation" ] +} + mojom("surface_handle") { generate_java = true sources = [ "surface_handle.mojom" ]
diff --git a/gpu/ipc/common/shared_image_pool_client_interface.mojom b/gpu/ipc/common/shared_image_pool_client_interface.mojom new file mode 100644 index 0000000..efbd87c3 --- /dev/null +++ b/gpu/ipc/common/shared_image_pool_client_interface.mojom
@@ -0,0 +1,12 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module gpu.mojom; + +// Interface used by the GPU process to notify the client/renderer side +// SharedImagePool instance to clear/purge the pool. +interface SharedImagePoolClientInterface { + // Currently empty and methods will be added in future CLs along with its + // implementations. +};
diff --git a/gpu/vulkan/BUILD.gn b/gpu/vulkan/BUILD.gn index 2ad0ac4..5ec048f7 100644 --- a/gpu/vulkan/BUILD.gn +++ b/gpu/vulkan/BUILD.gn
@@ -121,6 +121,7 @@ deps = [ ":buildflags", "//base", + "//build:android_buildflags", "//build:chromeos_buildflags", "//components/crash/core/common:crash_key", "//gpu/ipc/common:vulkan_ycbcr_info",
diff --git a/gpu/vulkan/vulkan_util.cc b/gpu/vulkan/vulkan_util.cc index f6ffe2cf..ead69ed 100644 --- a/gpu/vulkan/vulkan_util.cc +++ b/gpu/vulkan/vulkan_util.cc
@@ -29,6 +29,7 @@ #if BUILDFLAG(IS_ANDROID) #include "base/android/build_info.h" +#include "build/android_buildflags.h" #endif #if BUILDFLAG(IS_CHROMEOS_ASH) @@ -317,6 +318,11 @@ return true; } +bool SkipVulkanBlocklist() { + // Expectation is for all desktop android devices to use vulkan + return BUILDFLAG(IS_DESKTOP_ANDROID); +} + #endif } // namespace @@ -480,6 +486,10 @@ return true; #endif #else // BUILDFLAG(IS_ANDROID) + if (SkipVulkanBlocklist()) { + return true; + } + if (IsBlockedByBuildInfo() && !ShouldBypassMediatekBlock(gpu_info)) { return false; }
diff --git a/infra/config/generated/builders/ci/android-10-x86-fyi-rel/targets/chromium.android.fyi.json b/infra/config/generated/builders/ci/android-10-x86-fyi-rel/targets/chromium.android.fyi.json index 2ba0a2e..c28a9ada 100644 --- a/infra/config/generated/builders/ci/android-10-x86-fyi-rel/targets/chromium.android.fyi.json +++ b/infra/config/generated/builders/ci/android-10-x86-fyi-rel/targets/chromium.android.fyi.json
@@ -3305,8 +3305,7 @@ "isolated_scripts": [ { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -3324,17 +3323,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "android_webview_junit_tests", @@ -3342,8 +3330,7 @@ }, { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -3361,17 +3348,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "base_junit_tests", @@ -3379,8 +3355,7 @@ }, { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -3398,17 +3373,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "build_junit_tests", @@ -3416,8 +3380,7 @@ }, { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -3435,17 +3398,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "chrome_java_test_pagecontroller_junit_tests", @@ -3453,8 +3405,7 @@ }, { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -3472,17 +3423,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "chrome_junit_tests", @@ -3490,8 +3430,7 @@ }, { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -3509,17 +3448,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "components_junit_tests", @@ -3570,8 +3498,7 @@ }, { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -3589,17 +3516,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "content_junit_tests", @@ -3647,8 +3563,7 @@ }, { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -3666,17 +3581,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "device_junit_tests", @@ -3684,8 +3588,7 @@ }, { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -3703,17 +3606,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "junit_unit_tests", @@ -3721,8 +3613,7 @@ }, { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -3740,17 +3631,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "keyboard_accessory_junit_tests", @@ -3758,8 +3638,7 @@ }, { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -3777,17 +3656,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "media_base_junit_tests", @@ -3795,8 +3663,7 @@ }, { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -3814,17 +3681,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "module_installer_junit_tests", @@ -3873,8 +3729,7 @@ }, { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -3892,17 +3747,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "net_junit_tests", @@ -3910,8 +3754,7 @@ }, { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -3929,17 +3772,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "paint_preview_junit_tests", @@ -3947,8 +3779,7 @@ }, { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -3966,17 +3797,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "password_check_junit_tests", @@ -3984,8 +3804,7 @@ }, { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -4003,17 +3822,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "password_manager_junit_tests", @@ -4021,8 +3829,7 @@ }, { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -4040,17 +3847,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "services_junit_tests", @@ -4188,8 +3984,7 @@ }, { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -4207,17 +4002,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "touch_to_fill_junit_tests", @@ -4225,8 +4009,7 @@ }, { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -4244,17 +4027,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "ui_junit_tests", @@ -4262,8 +4034,7 @@ }, { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -4281,17 +4052,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "webapk_client_junit_tests", @@ -4299,8 +4059,7 @@ }, { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -4318,17 +4077,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "webapk_shell_apk_h2o_junit_tests", @@ -4336,8 +4084,7 @@ }, { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -4355,17 +4102,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "webapk_shell_apk_junit_tests",
diff --git a/infra/config/generated/builders/try/android-10-x86-fyi-rel/targets/chromium.android.fyi.json b/infra/config/generated/builders/try/android-10-x86-fyi-rel/targets/chromium.android.fyi.json index 2ba0a2e..c28a9ada 100644 --- a/infra/config/generated/builders/try/android-10-x86-fyi-rel/targets/chromium.android.fyi.json +++ b/infra/config/generated/builders/try/android-10-x86-fyi-rel/targets/chromium.android.fyi.json
@@ -3305,8 +3305,7 @@ "isolated_scripts": [ { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -3324,17 +3323,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "android_webview_junit_tests", @@ -3342,8 +3330,7 @@ }, { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -3361,17 +3348,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "base_junit_tests", @@ -3379,8 +3355,7 @@ }, { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -3398,17 +3373,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "build_junit_tests", @@ -3416,8 +3380,7 @@ }, { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -3435,17 +3398,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "chrome_java_test_pagecontroller_junit_tests", @@ -3453,8 +3405,7 @@ }, { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -3472,17 +3423,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "chrome_junit_tests", @@ -3490,8 +3430,7 @@ }, { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -3509,17 +3448,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "components_junit_tests", @@ -3570,8 +3498,7 @@ }, { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -3589,17 +3516,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "content_junit_tests", @@ -3647,8 +3563,7 @@ }, { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -3666,17 +3581,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "device_junit_tests", @@ -3684,8 +3588,7 @@ }, { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -3703,17 +3606,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "junit_unit_tests", @@ -3721,8 +3613,7 @@ }, { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -3740,17 +3631,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "keyboard_accessory_junit_tests", @@ -3758,8 +3638,7 @@ }, { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -3777,17 +3656,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "media_base_junit_tests", @@ -3795,8 +3663,7 @@ }, { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -3814,17 +3681,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "module_installer_junit_tests", @@ -3873,8 +3729,7 @@ }, { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -3892,17 +3747,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "net_junit_tests", @@ -3910,8 +3754,7 @@ }, { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -3929,17 +3772,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "paint_preview_junit_tests", @@ -3947,8 +3779,7 @@ }, { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -3966,17 +3797,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "password_check_junit_tests", @@ -3984,8 +3804,7 @@ }, { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -4003,17 +3822,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "password_manager_junit_tests", @@ -4021,8 +3829,7 @@ }, { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -4040,17 +3847,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "services_junit_tests", @@ -4188,8 +3984,7 @@ }, { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -4207,17 +4002,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "touch_to_fill_junit_tests", @@ -4225,8 +4009,7 @@ }, { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -4244,17 +4027,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "ui_junit_tests", @@ -4262,8 +4034,7 @@ }, { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -4281,17 +4052,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "webapk_client_junit_tests", @@ -4299,8 +4059,7 @@ }, { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -4318,17 +4077,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "webapk_shell_apk_h2o_junit_tests", @@ -4336,8 +4084,7 @@ }, { "args": [ - "--use-persistent-shell", - "--avd-config=../../tools/android/avd/proto/android_29_google_apis_x86.textpb" + "--use-persistent-shell" ], "isolate_profile_data": true, "merge": { @@ -4355,17 +4102,6 @@ "os": "Ubuntu-22.04", "pool": "chromium.tests" }, - "named_caches": [ - { - "name": "android_29_google_apis_x86", - "path": ".android_emulator/android_29_google_apis_x86" - } - ], - "optional_dimensions": { - "60": { - "caches": "android_29_google_apis_x86" - } - }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "webapk_shell_apk_junit_tests",
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg index 246d236f..b5f05bb6 100644 --- a/infra/config/generated/luci/cr-buildbucket.cfg +++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -94883,8 +94883,6 @@ name: "dawn-try-mac-amd-exp" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" - dimensions: "cpu:x86-64" - dimensions: "free_space:standard" dimensions: "os:Mac" dimensions: "pool:luci.chromium.gpu.mac.retina.amd.try" exe { @@ -94993,7 +94991,6 @@ name: "dawn-try-mac-arm64-deps-rel" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" - dimensions: "free_space:standard" dimensions: "os:Mac" dimensions: "pool:luci.chromium.gpu.mac.arm64.apple.m2.try" exe { @@ -95102,7 +95099,6 @@ name: "dawn-try-mac-arm64-m2-exp" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" - dimensions: "free_space:standard" dimensions: "os:Mac" dimensions: "pool:luci.chromium.gpu.mac.arm64.apple.m2.try" exe { @@ -95211,7 +95207,6 @@ name: "dawn-try-mac-arm64-rel" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" - dimensions: "free_space:standard" dimensions: "os:Mac" dimensions: "pool:luci.chromium.gpu.mac.arm64.apple.m2.try" exe { @@ -95320,8 +95315,6 @@ name: "dawn-try-mac-intel-exp" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" - dimensions: "cpu:x86-64" - dimensions: "free_space:standard" dimensions: "os:Mac" dimensions: "pool:luci.chromium.gpu.mac.mini.intel.try" exe {
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.dawn.star b/infra/config/subprojects/chromium/try/tryserver.chromium.dawn.star index 2ea13d8..5bfe8d63 100644 --- a/infra/config/subprojects/chromium/try/tryserver.chromium.dawn.star +++ b/infra/config/subprojects/chromium/try/tryserver.chromium.dawn.star
@@ -482,7 +482,19 @@ ), ) -try_.builder( +def dawn_mac_builder(*, name, **kwargs): + kwargs.setdefault("cpu", None) + return try_.builder( + name = name, + builderless = True, + cores = None, + free_space = None, + os = os.MAC_ANY, + ssd = None, + **kwargs + ) + +dawn_mac_builder( name = "dawn-try-mac-amd-exp", mirrors = [ "ci/Dawn Mac x64 Builder", @@ -490,14 +502,12 @@ ], gn_args = "ci/Dawn Mac x64 Builder", pool = "luci.chromium.gpu.mac.retina.amd.try", - builderless = True, - os = os.MAC_ANY, test_presentation = resultdb.test_presentation( grouping_keys = ["status", "v.test_suite", "v.gpu"], ), ) -try_.builder( +dawn_mac_builder( name = "dawn-try-mac-arm64-deps-rel", mirrors = [ "ci/Dawn Mac arm64 DEPS Builder", @@ -505,15 +515,12 @@ ], gn_args = "ci/Dawn Mac arm64 DEPS Builder", pool = "luci.chromium.gpu.mac.arm64.apple.m2.try", - builderless = True, - os = os.MAC_ANY, - cpu = None, test_presentation = resultdb.test_presentation( grouping_keys = ["status", "v.test_suite", "v.gpu"], ), ) -try_.builder( +dawn_mac_builder( name = "dawn-try-mac-arm64-m2-exp", description_html = "Manual-only trybot for running ToT Dawn tests on experimental M2 machines", mirrors = [ @@ -522,15 +529,12 @@ ], gn_args = "ci/Dawn Mac arm64 Builder", pool = "luci.chromium.gpu.mac.arm64.apple.m2.try", - builderless = True, - os = os.MAC_ANY, - cpu = None, test_presentation = resultdb.test_presentation( grouping_keys = ["status", "v.test_suite", "v.gpu"], ), ) -try_.builder( +dawn_mac_builder( name = "dawn-try-mac-arm64-rel", mirrors = [ "ci/Dawn Mac arm64 Builder", @@ -538,15 +542,12 @@ ], gn_args = "ci/Dawn Mac arm64 Builder", pool = "luci.chromium.gpu.mac.arm64.apple.m2.try", - builderless = True, - os = os.MAC_ANY, - cpu = None, test_presentation = resultdb.test_presentation( grouping_keys = ["status", "v.test_suite", "v.gpu"], ), ) -try_.builder( +dawn_mac_builder( name = "dawn-try-mac-intel-exp", mirrors = [ "ci/Dawn Mac x64 Builder", @@ -554,8 +555,6 @@ ], gn_args = "ci/Dawn Mac x64 Builder", pool = "luci.chromium.gpu.mac.mini.intel.try", - builderless = True, - os = os.MAC_ANY, test_presentation = resultdb.test_presentation( grouping_keys = ["status", "v.test_suite", "v.gpu"], ),
diff --git a/infra/config/targets/bundles.star b/infra/config/targets/bundles.star index 3933b1e..f7e9ba1 100644 --- a/infra/config/targets/bundles.star +++ b/infra/config/targets/bundles.star
@@ -1551,6 +1551,7 @@ "nougat-x86-emulator", "oreo-x86-emulator", "pie-x86-emulator", + "10-x86-emulator", ], ), "base_junit_tests": targets.per_test_modification( @@ -1560,6 +1561,7 @@ "nougat-x86-emulator", "oreo-x86-emulator", "pie-x86-emulator", + "10-x86-emulator", ], ), "build_junit_tests": targets.per_test_modification( @@ -1569,6 +1571,7 @@ "nougat-x86-emulator", "oreo-x86-emulator", "pie-x86-emulator", + "10-x86-emulator", ], ), "chrome_java_test_pagecontroller_junit_tests": targets.per_test_modification( @@ -1578,6 +1581,7 @@ "nougat-x86-emulator", "oreo-x86-emulator", "pie-x86-emulator", + "10-x86-emulator", ], ), "chrome_junit_tests": targets.per_test_modification( @@ -1587,6 +1591,7 @@ "nougat-x86-emulator", "oreo-x86-emulator", "pie-x86-emulator", + "10-x86-emulator", ], ), "components_junit_tests": targets.per_test_modification( @@ -1596,6 +1601,7 @@ "nougat-x86-emulator", "oreo-x86-emulator", "pie-x86-emulator", + "10-x86-emulator", ], ), "content_junit_tests": targets.per_test_modification( @@ -1605,6 +1611,7 @@ "nougat-x86-emulator", "oreo-x86-emulator", "pie-x86-emulator", + "10-x86-emulator", ], ), "device_junit_tests": targets.per_test_modification( @@ -1614,6 +1621,7 @@ "nougat-x86-emulator", "oreo-x86-emulator", "pie-x86-emulator", + "10-x86-emulator", ], ), "junit_unit_tests": targets.per_test_modification( @@ -1623,6 +1631,7 @@ "nougat-x86-emulator", "oreo-x86-emulator", "pie-x86-emulator", + "10-x86-emulator", ], ), "keyboard_accessory_junit_tests": targets.per_test_modification( @@ -1632,6 +1641,7 @@ "nougat-x86-emulator", "oreo-x86-emulator", "pie-x86-emulator", + "10-x86-emulator", ], ), "media_base_junit_tests": targets.per_test_modification( @@ -1641,6 +1651,7 @@ "nougat-x86-emulator", "oreo-x86-emulator", "pie-x86-emulator", + "10-x86-emulator", ], ), "module_installer_junit_tests": targets.per_test_modification( @@ -1650,6 +1661,7 @@ "nougat-x86-emulator", "oreo-x86-emulator", "pie-x86-emulator", + "10-x86-emulator", ], ), "net_junit_tests": targets.per_test_modification( @@ -1659,6 +1671,7 @@ "nougat-x86-emulator", "oreo-x86-emulator", "pie-x86-emulator", + "10-x86-emulator", ], ), "paint_preview_junit_tests": targets.per_test_modification( @@ -1668,6 +1681,7 @@ "nougat-x86-emulator", "oreo-x86-emulator", "pie-x86-emulator", + "10-x86-emulator", ], ), "password_check_junit_tests": targets.per_test_modification( @@ -1677,6 +1691,7 @@ "nougat-x86-emulator", "oreo-x86-emulator", "pie-x86-emulator", + "10-x86-emulator", ], ), "password_manager_junit_tests": targets.per_test_modification( @@ -1686,6 +1701,7 @@ "nougat-x86-emulator", "oreo-x86-emulator", "pie-x86-emulator", + "10-x86-emulator", ], ), "services_junit_tests": targets.per_test_modification( @@ -1695,6 +1711,7 @@ "nougat-x86-emulator", "oreo-x86-emulator", "pie-x86-emulator", + "10-x86-emulator", ], ), "touch_to_fill_junit_tests": targets.per_test_modification( @@ -1704,6 +1721,7 @@ "nougat-x86-emulator", "oreo-x86-emulator", "pie-x86-emulator", + "10-x86-emulator", ], ), "ui_junit_tests": targets.per_test_modification( @@ -1713,6 +1731,7 @@ "nougat-x86-emulator", "oreo-x86-emulator", "pie-x86-emulator", + "10-x86-emulator", ], ), "webapk_client_junit_tests": targets.per_test_modification( @@ -1722,6 +1741,7 @@ "nougat-x86-emulator", "oreo-x86-emulator", "pie-x86-emulator", + "10-x86-emulator", ], ), "webapk_shell_apk_h2o_junit_tests": targets.per_test_modification( @@ -1731,6 +1751,7 @@ "nougat-x86-emulator", "oreo-x86-emulator", "pie-x86-emulator", + "10-x86-emulator", ], ), "webapk_shell_apk_junit_tests": targets.per_test_modification( @@ -1740,6 +1761,7 @@ "nougat-x86-emulator", "oreo-x86-emulator", "pie-x86-emulator", + "10-x86-emulator", ], ), },
diff --git a/internal b/internal index eaf7cb0..d3ffbda 160000 --- a/internal +++ b/internal
@@ -1 +1 @@ -Subproject commit eaf7cb0f029bc20da46743fa0a0d8de6400b3dd4 +Subproject commit d3ffbdadbfe9840b0f0059171663afee4fb9fca7
diff --git a/ios/chrome/app/resources/BUILD.gn b/ios/chrome/app/resources/BUILD.gn index eddcdc0b..0e351a5 100644 --- a/ios/chrome/app/resources/BUILD.gn +++ b/ios/chrome/app/resources/BUILD.gn
@@ -65,6 +65,7 @@ "$root_gen_dir/components/dev_ui_components_resources.pak", "$root_gen_dir/components/download_internals_resources.pak", "$root_gen_dir/components/flags_ui_resources.pak", + "$root_gen_dir/components/management_resources.pak", "$root_gen_dir/components/metrics/metrics_server_urls.pak", "$root_gen_dir/components/ntp_tiles_internals_resources.pak", "$root_gen_dir/components/optimization_guide_internals_resources.pak",
diff --git a/ios/chrome/browser/infobars/ui_bundled/banners/infobar_banner_constants.h b/ios/chrome/browser/infobars/ui_bundled/banners/infobar_banner_constants.h index 3d0aa6dc..40f4334 100644 --- a/ios/chrome/browser/infobars/ui_bundled/banners/infobar_banner_constants.h +++ b/ios/chrome/browser/infobars/ui_bundled/banners/infobar_banner_constants.h
@@ -19,4 +19,7 @@ // Banner icon size. extern const CGFloat kInfobarBannerIconSize; +// The presented view maximum height. +extern const CGFloat kInfobarBannerMaxHeight; + #endif // IOS_CHROME_BROWSER_INFOBARS_UI_BUNDLED_BANNERS_INFOBAR_BANNER_CONSTANTS_H_
diff --git a/ios/chrome/browser/infobars/ui_bundled/banners/infobar_banner_constants.mm b/ios/chrome/browser/infobars/ui_bundled/banners/infobar_banner_constants.mm index 2e85511..5187cdb 100644 --- a/ios/chrome/browser/infobars/ui_bundled/banners/infobar_banner_constants.mm +++ b/ios/chrome/browser/infobars/ui_bundled/banners/infobar_banner_constants.mm
@@ -13,3 +13,5 @@ @"kInfobarBannerOpenModalButtonIdentifier"; const CGFloat kInfobarBannerIconSize = 28.0f; + +const CGFloat kInfobarBannerMaxHeight = 230.0f;
diff --git a/ios/chrome/browser/infobars/ui_bundled/banners/infobar_banner_view_controller.mm b/ios/chrome/browser/infobars/ui_bundled/banners/infobar_banner_view_controller.mm index 373077b..497e990 100644 --- a/ios/chrome/browser/infobars/ui_bundled/banners/infobar_banner_view_controller.mm +++ b/ios/chrome/browser/infobars/ui_bundled/banners/infobar_banner_view_controller.mm
@@ -203,15 +203,17 @@ labelsStackView.accessibilityLabel = [self accessibilityLabel]; // Button setup. - self.infobarButton = [UIButton buttonWithType:UIButtonTypeSystem]; - [self.infobarButton setTitle:self.buttonText forState:UIControlStateNormal]; - self.infobarButton.titleLabel.font = [[UIFontMetrics defaultMetrics] + UIFont* titleLabelFont = [[UIFontMetrics defaultMetrics] scaledFontForFont:[UIFont preferredFontForTextStyle:UIFontTextStyleHeadline] maximumPointSize:kButtonMaxFontSize]; + self.infobarButton = [UIButton buttonWithType:UIButtonTypeSystem]; + [self.infobarButton setTitle:self.buttonText forState:UIControlStateNormal]; + self.infobarButton.titleLabel.font = titleLabelFont; self.infobarButton.titleLabel.adjustsFontForContentSizeCategory = YES; - self.infobarButton.titleLabel.numberOfLines = 0; - self.infobarButton.titleLabel.textAlignment = NSTextAlignmentCenter; + self.infobarButton.titleLabel.adjustsFontSizeToFitWidth = YES; + self.infobarButton.titleLabel.numberOfLines = static_cast<NSInteger>( + floor(kInfobarBannerMaxHeight / titleLabelFont.lineHeight)); [self.infobarButton addTarget:self action:@selector(bannerInfobarButtonWasPressed:) forControlEvents:UIControlEventTouchUpInside];
diff --git a/ios/chrome/browser/infobars/ui_bundled/presentation/infobar_banner_presentation_controller.mm b/ios/chrome/browser/infobars/ui_bundled/presentation/infobar_banner_presentation_controller.mm index 05dc0bce..fc0211b 100644 --- a/ios/chrome/browser/infobars/ui_bundled/presentation/infobar_banner_presentation_controller.mm +++ b/ios/chrome/browser/infobars/ui_bundled/presentation/infobar_banner_presentation_controller.mm
@@ -8,6 +8,7 @@ #import <cmath> #import "base/check.h" +#import "ios/chrome/browser/infobars/ui_bundled/banners/infobar_banner_constants.h" #import "ios/chrome/browser/infobars/ui_bundled/presentation/infobar_banner_positioner.h" namespace { @@ -15,8 +16,6 @@ const CGFloat kContainerHorizontalPadding = 8; // The presented view maximum width. const CGFloat kContainerMaxWidth = 398; -// The presented view maximum height. -const CGFloat kContainerMaxHeight = 230; // Minimum height or width frame change that should warrant a resizing of the // container view in response to a relayout. const CGFloat kMinimumSizeChange = 0.5; @@ -71,7 +70,7 @@ withHorizontalFittingPriority:UILayoutPriorityRequired verticalFittingPriority:1] .height; - bannerFrame.size.height = std::min(kContainerMaxHeight, bannerHeight); + bannerFrame.size.height = std::min(kInfobarBannerMaxHeight, bannerHeight); return bannerFrame; }
diff --git a/ios/chrome/browser/optimization_guide/model/optimization_guide_service.mm b/ios/chrome/browser/optimization_guide/model/optimization_guide_service.mm index bbc68a5..2d68607f 100644 --- a/ios/chrome/browser/optimization_guide/model/optimization_guide_service.mm +++ b/ios/chrome/browser/optimization_guide/model/optimization_guide_service.mm
@@ -191,8 +191,9 @@ on_device_model_state_manager_->GetWeakPtr()); model_execution_manager_ = std::make_unique<optimization_guide::ModelExecutionManager>( - url_loader_factory, identity_manager, - std::move(on_device_model_service_controller), + url_loader_factory, local_state, identity_manager, + std::move(on_device_model_service_controller), this, + on_device_model_state_manager_->GetWeakPtr(), optimization_guide_logger_.get(), nullptr); } #endif // BUILDFLAG(BUILD_WITH_INTERNAL_OPTIMIZATION_GUIDE)
diff --git a/ios/chrome/browser/webui/ui_bundled/management/management_ui.mm b/ios/chrome/browser/webui/ui_bundled/management/management_ui.mm index 8faaef4..eadb4e0 100644 --- a/ios/chrome/browser/webui/ui_bundled/management/management_ui.mm +++ b/ios/chrome/browser/webui/ui_bundled/management/management_ui.mm
@@ -7,7 +7,8 @@ #import <optional> #import "base/strings/utf_string_conversions.h" -#import "components/grit/components_resources.h" +#import "components/grit/management_resources.h" +#import "components/grit/management_resources_map.h" #import "components/policy/core/common/cloud/cloud_policy_core.h" #import "components/policy/core/common/cloud/cloud_policy_store.h" #import "components/policy/proto/device_management_backend.pb.h" @@ -95,9 +96,8 @@ IDS_IOS_MANAGEMENT_UI_LEARN_MORE_LINK); source->UseStringsJs(); - source->AddResourcePath("management.css", IDR_MOBILE_MANAGEMENT_CSS); - source->AddResourcePath("management.js", IDR_MOBILE_MANAGEMENT_JS); - source->SetDefaultResource(IDR_MOBILE_MANAGEMENT_HTML); + source->AddResourcePaths(kManagementResources); + source->AddResourcePath("", IDR_MANAGEMENT_MANAGEMENT_HTML); return source; }
diff --git a/ios/testing/data/http_server_files/OWNERS b/ios/testing/data/http_server_files/OWNERS new file mode 100644 index 0000000..7264e64d --- /dev/null +++ b/ios/testing/data/http_server_files/OWNERS
@@ -0,0 +1,2 @@ +# HTML files are often required to test Autofill and PWM features. +per-file *.html=file://ios/chrome/browser/autofill/model/OWNERS \ No newline at end of file
diff --git a/ios/testing/http_server_bundle_data.filelist b/ios/testing/http_server_bundle_data.filelist index f92b5dc..0fddfbd 100644 --- a/ios/testing/http_server_bundle_data.filelist +++ b/ios/testing/http_server_bundle_data.filelist
@@ -4,6 +4,7 @@ # NOTE: this file is generated by build/ios/update_bundle_filelist.py # If it requires updating, you should get a presubmit error with # instructions on how to regenerate. Otherwise, do not edit. +data/http_server_files/OWNERS data/http_server_files/autofill_smoke_test.html data/http_server_files/browsing_prevent_default_test_page.html data/http_server_files/bundle.pkpasses @@ -16,6 +17,7 @@ data/http_server_files/credit_card.html data/http_server_files/destination.html data/http_server_files/download_test_page.html +data/http_server_files/email_signup_form.html data/http_server_files/fullscreen.html data/http_server_files/generic.pkpass data/http_server_files/green.pdf @@ -29,15 +31,14 @@ data/http_server_files/links.html data/http_server_files/memory_usage.html data/http_server_files/multi_field_form.html -data/http_server_files/new_password_and_confirmation_form_autofocus.html data/http_server_files/new_password_and_confirmation_form.html +data/http_server_files/new_password_and_confirmation_form_autofocus.html data/http_server_files/onload_replacestate_reload.html data/http_server_files/onload_replacestate_reload.js data/http_server_files/opensearch.xml data/http_server_files/permissions/camera_and_microphone.html data/http_server_files/permissions/camera_only.html data/http_server_files/permissions/microphone_only.html -data/http_server_files/email_signup_form.html data/http_server_files/pony.html data/http_server_files/profile_form.html data/http_server_files/readonly_form.html
diff --git a/media/audio/simple_sources.cc b/media/audio/simple_sources.cc index d7c0d597..6fd3b7e 100644 --- a/media/audio/simple_sources.cc +++ b/media/audio/simple_sources.cc
@@ -149,7 +149,9 @@ } for (int ch = 1; ch < dest->channels(); ++ch) { - dest->channel_span(ch).copy_prefix_from(first_channel_frames); + dest->channel_span(ch) + .first(max_frames) + .copy_from_nonoverlapping(first_channel_frames); } } }
diff --git a/media/base/audio_buffer.cc b/media/base/audio_buffer.cc index 729eb4d2..1b3b8b9a 100644 --- a/media/base/audio_buffer.cc +++ b/media/base/audio_buffer.cc
@@ -174,7 +174,7 @@ // Note: `data_size` is the external data size, not `data_size_`. auto [data_portion, zero_portion] = data_->span().split_at(data_size); - data_portion.copy_from(base::span(data[0], data_size)); + data_portion.copy_from_nonoverlapping(base::span(data[0], data_size)); needs_zeroing = zero_portion; } @@ -501,7 +501,8 @@ dest->SetBitstreamSize(new_dest_size); auto dest_span = dest->bitstream_data().subspan(dest_size, data_size()); - dest_span.copy_from(base::span(channel_data_[0], data_size())); + dest_span.copy_from_nonoverlapping( + base::span(channel_data_[0], data_size())); dest->SetBitstreamFrames(dest_frame_offset + frame_count()); return;
diff --git a/media/base/audio_bus.cc b/media/base/audio_bus.cc index 0125084..410e941 100644 --- a/media/base/audio_bus.cc +++ b/media/base/audio_bus.cc
@@ -24,6 +24,7 @@ #include "base/memory/raw_ptr.h" #include "base/notreached.h" #include "base/numerics/safe_conversions.h" +#include "base/types/zip.h" #include "media/base/audio_parameters.h" #include "media/base/limits.h" #include "media/base/vector_math.h" @@ -338,7 +339,7 @@ dest->SetBitstreamSize(bitstream_data_.size()); dest->SetBitstreamFrames(bitstream_frames_); - dest->bitstream_data().copy_from(bitstream_data_); + dest->bitstream_data().copy_from_nonoverlapping(bitstream_data_); return; } @@ -366,11 +367,13 @@ const size_t dest_offset = base::checked_cast<size_t>(dest_start_frame); const size_t count = base::checked_cast<size_t>(frame_count); + ChannelVector src_channels = AllChannelsSubspan(source_offset, count); + ChannelVector dest_channels = dest->AllChannelsSubspan(dest_offset, count); + // Since we don't know if the other AudioBus is wrapped or not (and we don't - // want to care), just copy using the public channel() accessors. - for (int i = 0; i < channels(); ++i) { - ConstChannel src_span = channel_span(i).subspan(source_offset, count); - dest->channel_span(i).subspan(dest_offset, count).copy_from(src_span); + // want to care), just copy using the channel accessors. + for (auto [src_span, dest_span] : base::zip(src_channels, dest_channels)) { + dest_span.copy_from_nonoverlapping(src_span); } }
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc index 6fa87b1..51f45e42 100644 --- a/media/base/media_switches.cc +++ b/media/base/media_switches.cc
@@ -248,13 +248,6 @@ // in testing where we do want to go through the permission flow even in dev // mode. This can be enabled by this flag. const char kAllowRAInDevMode[] = "allow-ra-in-dev-mode"; - -// These flags are passed from ash-chrome to lacros-chrome that correspond to -// the directories used for the Widevine CDM (the bundled CDM and the Component -// Updated CDM). -const char kCrosWidevineBundledDir[] = "cros-bundled-widevine"; -const char kCrosWidevineComponentUpdatedHintFile[] = - "cros-component-updated-widevine-hint-file"; #endif // BUILDFLAG(IS_CHROMEOS) namespace autoplay { @@ -864,13 +857,6 @@ "OnDeviceWebSpeech", base::FEATURE_DISABLED_BY_DEFAULT); -#if BUILDFLAG(IS_CHROMEOS) -// Enables Lacros Chrome to use the Ash Chrome Widevine CDM. -BASE_FEATURE(kLacrosUseAshWidevine, - "LacrosUseAshWidevine", - base::FEATURE_ENABLED_BY_DEFAULT); -#endif - // Enables the Live Caption feature on supported devices. BASE_FEATURE(kLiveCaption, "LiveCaption", base::FEATURE_ENABLED_BY_DEFAULT);
diff --git a/media/base/media_switches.h b/media/base/media_switches.h index a659f74..7156e80c 100644 --- a/media/base/media_switches.h +++ b/media/base/media_switches.h
@@ -99,8 +99,6 @@ MEDIA_EXPORT extern const char kLacrosUseChromeosProtectedMedia[]; MEDIA_EXPORT extern const char kLacrosUseChromeosProtectedAv1[]; MEDIA_EXPORT extern const char kAllowRAInDevMode[]; -MEDIA_EXPORT extern const char kCrosWidevineBundledDir[]; -MEDIA_EXPORT extern const char kCrosWidevineComponentUpdatedHintFile[]; #endif // BUILDFLAG(IS_CHROMEOS) namespace autoplay { @@ -274,9 +272,6 @@ kHardwareSecureDecryptionFallbackOnHardwareContextReset; MEDIA_EXPORT BASE_DECLARE_FEATURE(kInternalMediaSession); MEDIA_EXPORT BASE_DECLARE_FEATURE(kOnDeviceWebSpeech); -#if BUILDFLAG(IS_CHROMEOS) -MEDIA_EXPORT BASE_DECLARE_FEATURE(kLacrosUseAshWidevine); -#endif MEDIA_EXPORT BASE_DECLARE_FEATURE(kLiveCaption); MEDIA_EXPORT BASE_DECLARE_FEATURE(kLiveCaptionAutomaticLanguageDownload); MEDIA_EXPORT BASE_DECLARE_FEATURE(kLiveCaptionRightClick);
diff --git a/media/gpu/chromeos/frame_resource.cc b/media/gpu/chromeos/frame_resource.cc index 568ff58..db0573a9 100644 --- a/media/gpu/chromeos/frame_resource.cc +++ b/media/gpu/chromeos/frame_resource.cc
@@ -17,12 +17,6 @@ FrameResource::FrameResource() : unique_id_(GetNextID()) {} -const base::UnguessableToken& FrameResource::tracking_token() const { - CHECK(metadata().tracking_token.has_value()); - CHECK(!metadata().tracking_token->is_empty()); - return *metadata().tracking_token; -} - VideoFrameResource* FrameResource::AsVideoFrameResource() { return nullptr; }
diff --git a/media/gpu/chromeos/frame_resource.h b/media/gpu/chromeos/frame_resource.h index 78046e6e..cbe25d4 100644 --- a/media/gpu/chromeos/frame_resource.h +++ b/media/gpu/chromeos/frame_resource.h
@@ -141,7 +141,7 @@ // An UnguessableToken that identifies unique frames regardless of wrapping. // The returned UnguessableToken is guaranteed to be non-empty. - const base::UnguessableToken& tracking_token() const; + virtual const base::UnguessableToken& tracking_token() const = 0; virtual base::TimeDelta timestamp() const = 0; virtual void set_timestamp(base::TimeDelta timestamp) = 0;
diff --git a/media/gpu/chromeos/native_pixmap_frame_resource.cc b/media/gpu/chromeos/native_pixmap_frame_resource.cc index 09c763a7..cd9c02b7 100644 --- a/media/gpu/chromeos/native_pixmap_frame_resource.cc +++ b/media/gpu/chromeos/native_pixmap_frame_resource.cc
@@ -392,6 +392,13 @@ metadata_.tracking_token = original_tracking_token; } +const base::UnguessableToken& NativePixmapFrameResource::tracking_token() + const { + CHECK(metadata().tracking_token.has_value()); + CHECK(!metadata().tracking_token->is_empty()); + return *metadata().tracking_token; +} + base::TimeDelta NativePixmapFrameResource::timestamp() const { return timestamp_; }
diff --git a/media/gpu/chromeos/native_pixmap_frame_resource.h b/media/gpu/chromeos/native_pixmap_frame_resource.h index 1da891d7..3d942f74 100644 --- a/media/gpu/chromeos/native_pixmap_frame_resource.h +++ b/media/gpu/chromeos/native_pixmap_frame_resource.h
@@ -93,6 +93,7 @@ const VideoFrameMetadata& metadata() const override; VideoFrameMetadata& metadata() override; void set_metadata(const VideoFrameMetadata& metadata) override; + const base::UnguessableToken& tracking_token() const override; gfx::ColorSpace ColorSpace() const override; void set_color_space(const gfx::ColorSpace& color_space) override; const std::optional<gfx::HDRMetadata>& hdr_metadata() const override;
diff --git a/media/gpu/chromeos/video_frame_resource.cc b/media/gpu/chromeos/video_frame_resource.cc index 1448e24..225954b 100644 --- a/media/gpu/chromeos/video_frame_resource.cc +++ b/media/gpu/chromeos/video_frame_resource.cc
@@ -152,6 +152,12 @@ GetMutableVideoFrame()->set_metadata(metadata); } +const base::UnguessableToken& VideoFrameResource::tracking_token() const { + CHECK(metadata().tracking_token.has_value()); + CHECK(!metadata().tracking_token->is_empty()); + return *metadata().tracking_token; +} + base::TimeDelta VideoFrameResource::timestamp() const { return frame_->timestamp(); }
diff --git a/media/gpu/chromeos/video_frame_resource.h b/media/gpu/chromeos/video_frame_resource.h index 597ac2752..87e529d 100644 --- a/media/gpu/chromeos/video_frame_resource.h +++ b/media/gpu/chromeos/video_frame_resource.h
@@ -52,6 +52,7 @@ const VideoFrameMetadata& metadata() const override; VideoFrameMetadata& metadata() override; void set_metadata(const VideoFrameMetadata& metadata) override; + const base::UnguessableToken& tracking_token() const override; gfx::ColorSpace ColorSpace() const override; void set_color_space(const gfx::ColorSpace& color_space) override; const std::optional<gfx::HDRMetadata>& hdr_metadata() const override;
diff --git a/media/renderers/video_resource_updater.cc b/media/renderers/video_resource_updater.cc index fe6222a6..4e6706e 100644 --- a/media/renderers/video_resource_updater.cc +++ b/media/renderers/video_resource_updater.cc
@@ -502,29 +502,26 @@ context_provider_(context_provider) { DCHECK(context_provider_); auto* sii = SharedImageInterface(); - if (format.is_single_plane()) { - // TODO(crbug.com/40239769): Set `overlay_candidate_` for multiplanar - // formats. - overlay_candidate_ = - use_gpu_memory_buffer_resources && - sii->GetCapabilities().supports_scanout_shared_images && - CanCreateGpuMemoryBufferForSinglePlaneSharedImageFormat(format); - } + // TODO(crbug.com/40239769): Set `overlay_candidate` for multiplanar + // formats. + const bool overlay_candidate = + format.is_single_plane() && use_gpu_memory_buffer_resources && + sii->GetCapabilities().supports_scanout_shared_images && + CanCreateGpuMemoryBufferForSinglePlaneSharedImageFormat(format); + // These SharedImages will be sent over to the display compositor as // TransferableResources. RasterInterface which in turn uses RasterDecoder // writes the contents of video frames into SharedImages. gpu::SharedImageUsageSet shared_image_usage = gpu::SHARED_IMAGE_USAGE_DISPLAY_READ | gpu::SHARED_IMAGE_USAGE_RASTER_WRITE; - if (overlay_candidate_) { + if (overlay_candidate) { shared_image_usage |= gpu::SHARED_IMAGE_USAGE_SCANOUT; } shared_image_ = sii->CreateSharedImage( {format, size, color_space, shared_image_usage, "VideoResourceUpdater"}, gpu::kNullSurfaceHandle); CHECK(shared_image_); - // Determine if a platform-specific target is needed. - texture_target_ = shared_image_->GetTextureTarget(); RasterInterface()->WaitSyncTokenCHROMIUM( sii->GenUnverifiedSyncToken().GetConstData()); } @@ -539,10 +536,9 @@ std::move(shared_image_)); } - const gpu::Mailbox& mailbox() const { return shared_image_->mailbox(); } - - GLenum texture_target() const { return texture_target_; } - bool overlay_candidate() const { return overlay_candidate_; } + const scoped_refptr<gpu::ClientSharedImage>& shared_image() const { + return shared_image_; + } private: gpu::SharedImageInterface* SharedImageInterface() { @@ -559,8 +555,6 @@ const raw_ptr<viz::RasterContextProvider> context_provider_; scoped_refptr<gpu::ClientSharedImage> shared_image_; - GLenum texture_target_ = GL_TEXTURE_2D; - bool overlay_candidate_ = false; }; VideoResourceUpdater::SoftwarePlaneResource* @@ -826,10 +820,10 @@ auto* ri = RasterInterface(); ri->WaitSyncTokenCHROMIUM(video_frame->acquire_sync_token().GetConstData()); - ri->CopySharedImage(shared_image->mailbox(), hardware_resource->mailbox(), - /*xoffset=*/0, /*yoffset=*/0, /*x=*/0, /*y=*/0, - output_plane_resource_size.width(), - output_plane_resource_size.height()); + ri->CopySharedImage( + shared_image->mailbox(), hardware_resource->shared_image()->mailbox(), + /*xoffset=*/0, /*yoffset=*/0, /*x=*/0, /*y=*/0, + output_plane_resource_size.width(), output_plane_resource_size.height()); // Wait (if the existing token isn't null) and replace it with a new one. // @@ -840,7 +834,7 @@ gpu::SyncToken sync_token = video_frame->UpdateReleaseSyncToken(&client); auto transferable_resource = viz::TransferableResource::MakeGpu( - hardware_resource->mailbox(), GL_TEXTURE_2D, sync_token, + hardware_resource->shared_image(), GL_TEXTURE_2D, sync_token, output_plane_resource_size, copy_si_format, false /* is_overlay_candidate */, viz::TransferableResource::ResourceSource::kVideo); @@ -1111,9 +1105,10 @@ SkImageInfo info = SkImageInfo::Make(plane_size.width(), plane_size.height(), color_type, kPremul_SkAlphaType); SkPixmap pixmap = SkPixmap(info, source_pixels, bytes_per_row); - ri->WritePixels(hardware_resource->mailbox(), /*dst_x_offset=*/0, - /*dst_y_offset=*/0, hardware_resource->texture_target(), - pixmap); + ri->WritePixels( + hardware_resource->shared_image()->mailbox(), /*dst_x_offset=*/0, + /*dst_y_offset=*/0, hardware_resource->shared_image()->GetTextureTarget(), + pixmap); return true; } @@ -1263,7 +1258,8 @@ SkYUVAInfo info = SkYUVAInfo(video_size, plane_config, subsampling, color_space); SkYUVAPixmaps yuv_pixmap = SkYUVAPixmaps::FromExternalPixmaps(info, pixmaps); - RasterInterface()->WritePixelsYUV(resource->mailbox(), yuv_pixmap); + RasterInterface()->WritePixelsYUV(resource->shared_image()->mailbox(), + yuv_pixmap); return true; } @@ -1370,9 +1366,11 @@ gpu::SyncToken sync_token; RasterInterface()->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData()); transferable_resource = viz::TransferableResource::MakeGpu( - hardware_resource->mailbox(), hardware_resource->texture_target(), - sync_token, hardware_resource->resource_size(), output_si_format, - hardware_resource->overlay_candidate(), + hardware_resource->shared_image(), + hardware_resource->shared_image()->GetTextureTarget(), sync_token, + hardware_resource->resource_size(), output_si_format, + hardware_resource->shared_image()->usage().Has( + gpu::SHARED_IMAGE_USAGE_SCANOUT), viz::TransferableResource::ResourceSource::kVideo); } @@ -1404,9 +1402,9 @@ RasterInterface()->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData()); auto transferable_resource = viz::TransferableResource::MakeGpu( - resource->mailbox(), resource->texture_target(), sync_token, - resource->resource_size(), output_si_format, - resource->overlay_candidate(), + resource->shared_image(), resource->shared_image()->GetTextureTarget(), + sync_token, resource->resource_size(), output_si_format, + resource->shared_image()->usage().Has(gpu::SHARED_IMAGE_USAGE_SCANOUT), viz::TransferableResource::ResourceSource::kVideo); transferable_resource.origin = kTopLeft_GrSurfaceOrigin; transferable_resource.color_space = output_color_space; @@ -1497,10 +1495,8 @@ resource->AsSoftware()->GetSharedMemoryGuid(); pmd->CreateSharedMemoryOwnershipEdge(dump->guid(), shm_guid, kImportance); } else { - base::trace_event::MemoryAllocatorDumpGuid guid = - gpu::GetSharedImageGUIDForTracing(resource->AsHardware()->mailbox()); - pmd->CreateSharedGlobalAllocatorDump(guid); - pmd->AddOwnershipEdge(dump->guid(), guid, kImportance); + resource->AsHardware()->shared_image()->OnMemoryDump(pmd, dump->guid(), + kImportance); } }
diff --git a/pdf/pdf_ink_module.cc b/pdf/pdf_ink_module.cc index 766219e..8e1d0cf 100644 --- a/pdf/pdf_ink_module.cc +++ b/pdf/pdf_ink_module.cc
@@ -36,7 +36,9 @@ #include "pdf/pdf_ink_transform.h" #include "third_party/blink/public/common/input/web_input_event.h" #include "third_party/blink/public/common/input/web_mouse_event.h" +#include "third_party/blink/public/common/input/web_pointer_properties.h" #include "third_party/blink/public/common/input/web_touch_event.h" +#include "third_party/blink/public/common/input/web_touch_point.h" #include "third_party/ink/src/ink/brush/brush.h" #include "third_party/ink/src/ink/geometry/affine_transform.h" #include "third_party/ink/src/ink/geometry/intersects.h" @@ -59,12 +61,21 @@ namespace { -// TODO(crbug.com/377733396): Determine if it possible to differentiate between -// touch and pen. Defaulting to touch for now. -constexpr auto kTouchOrPenToolType = ink::StrokeInput::ToolType::kTouch; - constexpr ink::AffineTransform kIdentityTransform; +ink::StrokeInput::ToolType GetToolTypeFromTouchEvent( + const blink::WebTouchEvent& event) { + // TODO(crbug.com/377733396): Investigate how multiple touches and pens should + // behave. For now, if there is any pen touch, set the tool type to pen. + for (size_t i = 0; i < event.touches_length; ++i) { + if (event.touches[i].pointer_type == + blink::WebPointerProperties::PointerType::kPen) { + return ink::StrokeInput::ToolType::kStylus; + } + } + return ink::StrokeInput::ToolType::kTouch; +} + PdfInkModule::StrokeInputPoints GetStrokePointsForTesting( // IN-TEST const ink::StrokeInputBatch& input_batch) { PdfInkModule::StrokeInputPoints stroke_points; @@ -195,7 +206,7 @@ switch (event.GetType()) { case blink::WebInputEvent::Type::kMouseDown: { - // TODO(crbug.com/353942909): Send a content focused message for certain + // TODO(crbug.com/377733396): Send a content focused message for certain // non-mouse inputs, too. base::Value::Dict message; message.Set("type", "contentFocused"); @@ -206,6 +217,7 @@ return OnMouseUp(static_cast<const blink::WebMouseEvent&>(event)); case blink::WebInputEvent::Type::kMouseMove: return OnMouseMove(static_cast<const blink::WebMouseEvent&>(event)); + // Touch and pen input events are blink::WebTouchEvent instances. case blink::WebInputEvent::Type::kTouchStart: return OnTouchStart(static_cast<const blink::WebTouchEvent&>(event)); case blink::WebInputEvent::Type::kTouchEnd: @@ -387,8 +399,9 @@ } gfx::PointF position = event.touches[0].PositionInWidget(); + ink::StrokeInput::ToolType tool_type = GetToolTypeFromTouchEvent(event); return is_drawing_stroke() - ? StartStroke(position, event.TimeStamp(), kTouchOrPenToolType) + ? StartStroke(position, event.TimeStamp(), tool_type) : StartEraseStroke(position); } @@ -400,8 +413,9 @@ } gfx::PointF position = event.touches[0].PositionInWidget(); + ink::StrokeInput::ToolType tool_type = GetToolTypeFromTouchEvent(event); return is_drawing_stroke() - ? FinishStroke(position, event.TimeStamp(), kTouchOrPenToolType) + ? FinishStroke(position, event.TimeStamp(), tool_type) : FinishEraseStroke(position); } @@ -413,8 +427,9 @@ } gfx::PointF position = event.touches[0].PositionInWidget(); + ink::StrokeInput::ToolType tool_type = GetToolTypeFromTouchEvent(event); return is_drawing_stroke() - ? ContinueStroke(position, event.TimeStamp(), kTouchOrPenToolType) + ? ContinueStroke(position, event.TimeStamp(), tool_type) : ContinueEraseStroke(position); }
diff --git a/pdf/pdf_ink_module_unittest.cc b/pdf/pdf_ink_module_unittest.cc index 1e3723c..d121881 100644 --- a/pdf/pdf_ink_module_unittest.cc +++ b/pdf/pdf_ink_module_unittest.cc
@@ -217,6 +217,16 @@ return touch_event; } +blink::WebTouchEvent CreatePenEvent(blink::WebInputEvent::Type type, + base::span<const gfx::PointF> points) { + blink::WebTouchEvent pen_event = CreateTouchEvent(type, points); + for (size_t i = 0; i < pen_event.touches_length; ++i) { + pen_event.touches[i].pointer_type = + blink::WebPointerProperties::PointerType::kPen; + } + return pen_event; +} + class FakeClient : public PdfInkModuleClient { public: FakeClient() = default; @@ -789,15 +799,8 @@ kMouseDownPoint, base::span_from_ref(kMouseMovePoint), kMouseUpPoint, /*expect_mouse_events_handled=*/annotation_mode_enabled); - const int expected_count = annotation_mode_enabled ? 1 : 0; - EXPECT_EQ(expected_count, client().stroke_finished_count()); - const std::vector<int>& updated_thumbnail_page_indices = - client().updated_thumbnail_page_indices(); - if (annotation_mode_enabled) { - EXPECT_THAT(updated_thumbnail_page_indices, ElementsAre(0)); - } else { - EXPECT_TRUE(updated_thumbnail_page_indices.empty()); - } + ValidateRunStrokeCheckTest( + /*expect_stroke_success=*/annotation_mode_enabled); } void ApplyStrokeWithMouseAtMouseDownPoint() { @@ -829,15 +832,8 @@ base::span_from_ref(kMouseUpPoint), /*expect_touch_events_handled=*/annotation_mode_enabled); - const int expected_count = annotation_mode_enabled ? 1 : 0; - EXPECT_EQ(expected_count, client().stroke_finished_count()); - const std::vector<int>& updated_thumbnail_page_indices = - client().updated_thumbnail_page_indices(); - if (annotation_mode_enabled) { - EXPECT_THAT(updated_thumbnail_page_indices, ElementsAre(0)); - } else { - EXPECT_TRUE(updated_thumbnail_page_indices.empty()); - } + ValidateRunStrokeCheckTest( + /*expect_stroke_success=*/annotation_mode_enabled); } // TODO(crbug.com/377733396): Consider refactoring to combine with @@ -863,10 +859,35 @@ touch_start_points, all_touch_move_points, touch_end_points, /*expect_touch_events_handled=*/false); - EXPECT_EQ(0, client().stroke_finished_count()); - const std::vector<int>& updated_thumbnail_page_indices = - client().updated_thumbnail_page_indices(); - EXPECT_TRUE(updated_thumbnail_page_indices.empty()); + ValidateRunStrokeCheckTest(/*expect_stroke_success=*/false); + } + + void ApplyStrokeWithPenAtPoints( + base::span<const gfx::PointF> pen_start_points, + std::vector<base::span<const gfx::PointF>> all_pen_move_points, + base::span<const gfx::PointF> pen_end_points) { + ApplyStrokeWithPenAtPointsMaybeHandled(pen_start_points, + all_pen_move_points, pen_end_points, + /*expect_pen_events_handled=*/true); + } + + // TODO(crbug.com/377733396): Consider refactoring to combine with + // RunStrokeCheckTest(). + void RunStrokePenCheckTest(bool annotation_mode_enabled) { + EXPECT_TRUE(ink_module().OnMessage( + CreateSetAnnotationModeMessageForTesting(annotation_mode_enabled))); + EXPECT_EQ(annotation_mode_enabled, ink_module().enabled()); + + const std::vector<base::span<const gfx::PointF>> all_pen_move_points{ + base::span_from_ref(kMouseMovePoint), + }; + ApplyStrokeWithPenAtPointsMaybeHandled( + base::span_from_ref(kMouseDownPoint), all_pen_move_points, + base::span_from_ref(kMouseUpPoint), + /*expect_pen_events_handled=*/annotation_mode_enabled); + + ValidateRunStrokeCheckTest( + /*expect_stroke_success=*/annotation_mode_enabled); } void RunStrokeMissedEndEventCheckTest() { @@ -1013,6 +1034,39 @@ EXPECT_EQ(expect_touch_events_handled, ink_module().HandleInputEvent(touch_end_event)); } + + void ApplyStrokeWithPenAtPointsMaybeHandled( + base::span<const gfx::PointF> pen_start_points, + std::vector<base::span<const gfx::PointF>> all_pen_move_points, + base::span<const gfx::PointF> pen_end_points, + bool expect_pen_events_handled) { + blink::WebTouchEvent pen_start_event = CreatePenEvent( + blink::WebInputEvent::Type::kTouchStart, pen_start_points); + EXPECT_EQ(expect_pen_events_handled, + ink_module().HandleInputEvent(pen_start_event)); + for (const auto& pen_move_points : all_pen_move_points) { + blink::WebTouchEvent pen_move_event = CreatePenEvent( + blink::WebInputEvent::Type::kTouchMove, pen_move_points); + EXPECT_EQ(expect_pen_events_handled, + ink_module().HandleInputEvent(pen_move_event)); + } + + blink::WebTouchEvent pen_end_event = + CreatePenEvent(blink::WebInputEvent::Type::kTouchEnd, pen_end_points); + EXPECT_EQ(expect_pen_events_handled, + ink_module().HandleInputEvent(pen_end_event)); + } + + void ValidateRunStrokeCheckTest(bool expect_stroke_success) { + EXPECT_EQ(expect_stroke_success ? 1 : 0, client().stroke_finished_count()); + const std::vector<int>& updated_thumbnail_page_indices = + client().updated_thumbnail_page_indices(); + if (expect_stroke_success) { + EXPECT_THAT(updated_thumbnail_page_indices, ElementsAre(0)); + } else { + EXPECT_TRUE(updated_thumbnail_page_indices.empty()); + } + } }; TEST_F(PdfInkModuleStrokeTest, NoAnnotationWithMouseIfNotEnabled) { @@ -1022,6 +1076,8 @@ /*page_index=*/0, ink::StrokeInput::ToolType::kMouse)); EXPECT_EQ(0, ink_module().GetInputOfTypeCountForPageForTesting( /*page_index=*/0, ink::StrokeInput::ToolType::kTouch)); + EXPECT_EQ(0, ink_module().GetInputOfTypeCountForPageForTesting( + /*page_index=*/0, ink::StrokeInput::ToolType::kStylus)); } TEST_F(PdfInkModuleStrokeTest, AnnotationWithMouseIfEnabled) { @@ -1031,6 +1087,8 @@ /*page_index=*/0, ink::StrokeInput::ToolType::kMouse)); EXPECT_EQ(0, ink_module().GetInputOfTypeCountForPageForTesting( /*page_index=*/0, ink::StrokeInput::ToolType::kTouch)); + EXPECT_EQ(0, ink_module().GetInputOfTypeCountForPageForTesting( + /*page_index=*/0, ink::StrokeInput::ToolType::kStylus)); } TEST_F(PdfInkModuleStrokeTest, NoAnnotationWithTouchIfNotEnabled) { @@ -1040,6 +1098,8 @@ /*page_index=*/0, ink::StrokeInput::ToolType::kMouse)); EXPECT_EQ(0, ink_module().GetInputOfTypeCountForPageForTesting( /*page_index=*/0, ink::StrokeInput::ToolType::kTouch)); + EXPECT_EQ(0, ink_module().GetInputOfTypeCountForPageForTesting( + /*page_index=*/0, ink::StrokeInput::ToolType::kStylus)); } TEST_F(PdfInkModuleStrokeTest, AnnotationWithTouchIfEnabled) { @@ -1049,6 +1109,8 @@ /*page_index=*/0, ink::StrokeInput::ToolType::kMouse)); EXPECT_EQ(3, ink_module().GetInputOfTypeCountForPageForTesting( /*page_index=*/0, ink::StrokeInput::ToolType::kTouch)); + EXPECT_EQ(0, ink_module().GetInputOfTypeCountForPageForTesting( + /*page_index=*/0, ink::StrokeInput::ToolType::kStylus)); } TEST_F(PdfInkModuleStrokeTest, NoAnnotationWithMultiTouchIfNotEnabled) { @@ -1058,6 +1120,8 @@ /*page_index=*/0, ink::StrokeInput::ToolType::kMouse)); EXPECT_EQ(0, ink_module().GetInputOfTypeCountForPageForTesting( /*page_index=*/0, ink::StrokeInput::ToolType::kTouch)); + EXPECT_EQ(0, ink_module().GetInputOfTypeCountForPageForTesting( + /*page_index=*/0, ink::StrokeInput::ToolType::kStylus)); } TEST_F(PdfInkModuleStrokeTest, NoAnnotationWithMultiTouchIfEnabled) { @@ -1067,6 +1131,30 @@ /*page_index=*/0, ink::StrokeInput::ToolType::kMouse)); EXPECT_EQ(0, ink_module().GetInputOfTypeCountForPageForTesting( /*page_index=*/0, ink::StrokeInput::ToolType::kTouch)); + EXPECT_EQ(0, ink_module().GetInputOfTypeCountForPageForTesting( + /*page_index=*/0, ink::StrokeInput::ToolType::kStylus)); +} + +TEST_F(PdfInkModuleStrokeTest, NoAnnotationWithPenIfNotEnabled) { + InitializeSimpleSinglePageBasicLayout(); + RunStrokePenCheckTest(/*annotation_mode_enabled=*/false); + EXPECT_EQ(0, ink_module().GetInputOfTypeCountForPageForTesting( + /*page_index=*/0, ink::StrokeInput::ToolType::kMouse)); + EXPECT_EQ(0, ink_module().GetInputOfTypeCountForPageForTesting( + /*page_index=*/0, ink::StrokeInput::ToolType::kTouch)); + EXPECT_EQ(0, ink_module().GetInputOfTypeCountForPageForTesting( + /*page_index=*/0, ink::StrokeInput::ToolType::kStylus)); +} + +TEST_F(PdfInkModuleStrokeTest, AnnotationWithPenIfEnabled) { + InitializeSimpleSinglePageBasicLayout(); + RunStrokePenCheckTest(/*annotation_mode_enabled=*/true); + EXPECT_EQ(0, ink_module().GetInputOfTypeCountForPageForTesting( + /*page_index=*/0, ink::StrokeInput::ToolType::kMouse)); + EXPECT_EQ(0, ink_module().GetInputOfTypeCountForPageForTesting( + /*page_index=*/0, ink::StrokeInput::ToolType::kTouch)); + EXPECT_EQ(3, ink_module().GetInputOfTypeCountForPageForTesting( + /*page_index=*/0, ink::StrokeInput::ToolType::kStylus)); } TEST_F(PdfInkModuleStrokeTest, CanonicalAnnotationPoints) { @@ -1523,6 +1611,55 @@ EXPECT_THAT(updated_thumbnail_page_indices, ElementsAre(0, 0)); } +TEST_F(PdfInkModuleStrokeTest, EraseStrokeWithPen) { + InitializeSimpleSinglePageBasicLayout(); + RunStrokePenCheckTest(/*annotation_mode_enabled=*/true); + + // Check that there are now some visible strokes. + EXPECT_THAT( + VisibleStrokeInputPositions(), + ElementsAre(Pair(0, ElementsAre(ElementsAreArray(kMousePoints))))); + EXPECT_EQ(1, client().stroke_finished_count()); + const std::vector<int>& updated_thumbnail_page_indices = + client().updated_thumbnail_page_indices(); + EXPECT_THAT(updated_thumbnail_page_indices, ElementsAre(0)); + + // Stroke with the eraser tool. + SelectEraserToolOfSize(3.0f); + const std::vector<base::span<const gfx::PointF>> pen_move_points{ + base::span_from_ref(kMouseMovePoint), + }; + ApplyStrokeWithPenAtPoints(base::span_from_ref(kMouseDownPoint), + pen_move_points, + base::span_from_ref(kMouseDownPoint)); + + // Now there are no visible strokes left. + EXPECT_TRUE(VisibleStrokeInputPositions().empty()); + // Erasing counts as another stroke action. + EXPECT_EQ(2, client().stroke_finished_count()); + EXPECT_THAT(updated_thumbnail_page_indices, ElementsAre(0, 0)); + + // Stroke again. The stroke that have already been erased should stay erased. + ApplyStrokeWithPenAtPoints(base::span_from_ref(kMouseDownPoint), + pen_move_points, + base::span_from_ref(kMouseDownPoint)); + + // Still no visible strokes. + EXPECT_TRUE(VisibleStrokeInputPositions().empty()); + // Nothing got erased, so the count stays at 2. + EXPECT_EQ(2, client().stroke_finished_count()); + EXPECT_THAT(updated_thumbnail_page_indices, ElementsAre(0, 0)); + + // Stroke again with the mouse gets the same results. + ApplyStrokeWithMouseAtMouseDownPoint(); + + // Still no visible strokes. + EXPECT_TRUE(VisibleStrokeInputPositions().empty()); + // Nothing got erased, so the count stays at 2. + EXPECT_EQ(2, client().stroke_finished_count()); + EXPECT_THAT(updated_thumbnail_page_indices, ElementsAre(0, 0)); +} + TEST_F(PdfInkModuleStrokeTest, RunStrokeMissedEndEventDuringDrawing) { InitializeSimpleSinglePageBasicLayout(); EXPECT_TRUE(ink_module().OnMessage(
diff --git a/styleguide/java/java.md b/styleguide/java/java.md index 0de40a01..61f7f334 100644 --- a/styleguide/java/java.md +++ b/styleguide/java/java.md
@@ -230,6 +230,15 @@ [Google's Java style guide]: https://google.github.io/styleguide/javaguide.html#s6.4-finalizers [Android's Java style guide]: https://source.android.com/docs/setup/contribute/code-style#dont-use-finalizers +## Nullability Annotations + +A migration to add `@NullMarked` to all Java files is currently underway +([crbug.com/389129271]). See [nullaway.md] for how to `@Nullable` and related +annotations. + +[crbug.com/389129271]: https://crbug.com/389129271 +[nullaway.md]: nullaway.md + ## Java Library APIs Android provides the ability to bundle copies of `java.*` APIs alongside
diff --git a/styleguide/java/nullaway.md b/styleguide/java/nullaway.md new file mode 100644 index 0000000..1b43735b --- /dev/null +++ b/styleguide/java/nullaway.md
@@ -0,0 +1,173 @@ +# Null Checking + +Chromium uses [NullAway] to enforce [JSpecify]-style `@Nullable` annotations. +NullAway is a [Error Prone] plugin and [runs as a static analysis step] for +targets without `chromium_code = false`. + +[TOC] + +[NullAway]: https://github.com/uber/NullAway +[JSpecify]: https://jspecify.dev/docs/user-guide/ +[Error Prone]: https://errorprone.info/ +[runs as a static analysis step]: /build/android/docs/static_analysis.md#ErrorProne + +## NullAway Configuration + +[Chromium's NullAway configuration] is as follows: +* [JSpecify mode] is enabled. + * `@Nullable` is `TYPE_USE`. + * Non-annotated means non-null for fields, parameters, and return types. + * Nullness of local variables is inferred. +* Copies of [supported annotations] exist under + `org.chromium.build.annotations`. + * These are a part of `//build/android:build_java`, which for convenience, + is a default dep of all `android_library` and `java_library` targets. +* Null checking is enabled only for classes annotated with `@NullMarked`. + * For other classes (e.g.: most library & OS APIs), `@Nullable` and + `@NonNull` are respected, but non-annotated types are permissive (return + types are non-null and parameters are nullable). +* Java collections and Guava's `Preconditions` are [modeled directly] in + NullAway. + * Some additional types are modeled via [`ChromeNullAwayLibraryModel`]. +* Android `onCreate()` methods are implicitly marked `@Initializer`. +* `assert foo != null` causes `foo` to no longer be nullable. +* [`assumeNonNull(foo)`] causes `foo` to no longer be nullable without actually + checking. + +[Chromium's NullAway configuration]: https://source.chromium.org/search?q=%22XepOpt:NullAway%22%20f:compile_java%20-f:third_party&sq=&ss=chromium +[JSpecify mode]: https://github.com/uber/NullAway/wiki/JSpecify-Support +[supported annotations]: https://github.com/uber/NullAway/wiki/Supported-Annotations +[`ChromeNullAwayLibraryModel`]: https://source.chromium.org/chromium/chromium/src/+/main:tools/android/errorprone_plugin/src/org/chromium/tools/errorprone/plugin/ChromeNullAwayLibraryModel.java +[modeled directly]: https://github.com/uber/NullAway/blob/HEAD/nullaway/src/main/java/com/uber/nullaway/handlers/LibraryModelsHandler.java +[`assumeNonNull(foo)`]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/openscreen/src/build/android/java/src/org/chromium/build/NullUtil.java + +## Nullness Primer + +### Type Annotations + +```java +// Plain Objects: +private String mNonNullString; +private @Nullable String mNullableString; +private Outer.@Nullable Inner mNullableNestedType; + +// Arrays: +private String @Nullable[] mNullableArrayOfNonNullString; +private @Nullable String[] mNonNullArrayOfNullableString; + +// Generics: +private List<@Nullable String> mNonNullListOfNullableString; +private @Nullable Callback<@Nullable String> mNullableCallbackOfNullableString; + +// Does not compile (annotation must come immediately before type): +@Nullable +private String mInvalidAnnotation; +``` + +### Method Annotations + +NullAway analyzes code on a per-method basis. These annotations tell it how +about pre/post conditions: + +```java +// Using this with non-private methods never makes sense. +@RequiresNonNull("mNullableString") +private void usesNullableString() { + // No warning: + if (mNullableString.isEmpty()) { ... } +} + +@EnsuresNonNull("mNullableString") +private void codeCanCallThisAndThenUseNullableString() { + // This will warn if mNullableString is @Nullable at any egress. + assert mNullableString != null; +} + +// If this method returns true, then mThing is non-null. +@EnsuresNonNullIf("mThing") +private boolean isThingEnabled() { + return mThing != null; +} + +// Also works with static fields and negated return values. +@EnsuresNonNullIf(value={"sThing1", "sThing2"}, result=false) +private static boolean isThingEnabled() { + return sThing1 == null || sThing2 == null; +} + +// If foo is null, this method returns false. +// Most other forms of contracts are not supported. +@Contract("null -> false") +private boolean isParamNull(@Nullable String foo) { + return foo != null; +} +``` + +### Object Construction and Destruction + +**Construction:** + +* NullAway warns if any non-null fields are still nullable at the end of a + constructor. + * When a class uses two-phase initialization (e.g., has an `onCreate()` or + `initialize()`), you can tell NullAway to not check for null until after + methods annotated with `@Initializer` are called. + * `@Initializer` can also be used for `static` methods, which impacts + warnings for `static` fields. + +**Destruction:** + +For classes with `destroy()` methods that set fields to `null` that would +otherwise be non-null, you can either: + +1) Annotate the fields as `@Nullable` and add `!isDestroyed()` asserts / guards + where necessary (where `isDestroyed()` is annotated with + `@EnsuresNonNullIf(value=..., result=false)`), or +2) Annotate the `destroy()` method with `@SuppressWarnings("NullAway")`. + +### JNI + +* Nullness is not checked for `@CalledByNative` methods ([crbug/389192501]). +* Nullness **is checked** via `assert` statements for Java->Native methods + (when `@NullMarked` exists). + +[crbug/389192501]: https://crbug.com/389192501 + +### NullAway Shortcomings + +It does not understand when local variables contain non-null information +* Feature request: https://github.com/uber/NullAway/issues/98 + +It does not infer nullness of inferred generics +* Feature request: https://github.com/uber/NullAway/issues/1075 + +### FAQ + +**Q: Why not use Checker Framework?** + +A: Chromium already uses Error Prone, so NullAway was easy to integrate. + +**Q: How do `@NullUnmarked` and `@SuppressWarnings("ErrorProne")` differ?** + +A: NullAway treats these two the same. In Chromium, `@SuppressWarnings` is used +when a warning is unavoidable (appeasing NullAway would make the code worse), +and `@NullUnmarked` is used when a method has not yet been updated to support +`@Nullable` annotations (its a remnant of our [automated adding of +annotations]). + +[automated adding of annotations]: https://docs.google.com/document/d/1KNKs7jI8uoBLfBq4HCuGTYPLuTOMgUEuKrzyCUFjEk8/edit?tab=t.0#heading=h.1y1pwesy8vhq + +**Q: Can I use JSpecify Annotations?** + +A: Yes. For code that will be mirrored and built in other environments, it is +best to use JSpecify annotations. You'll probably want to set: + +```gn +deps += [ "//third_party/android_deps:org_jspecify_jspecify_java" ] + +# Prevent automatic dep on build_java. +chromium_code = false + +# Do not let chromium_code = false disable Error Prone. +enable_errorprone = true +```
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index fac3b2b..47c2725 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -9586,6 +9586,9 @@ "experiments": [ { "name": "Enabled", + "params": { + "FRESignInSecondaryActionLabelUpdateParam": "StaySignedOut" + }, "enable_features": [ "FRESignInSecondaryActionLabelUpdate" ] @@ -11184,6 +11187,27 @@ ] } ], + "HistoryEmbeddingsV2Images": [ + { + "platforms": [ + "chromeos", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "Enabled", + "params": { + "EnableImagesForResults": "true" + }, + "enable_features": [ + "HistoryEmbeddings" + ] + } + ] + } + ], "HistorySyncAlternativeIllustration": [ { "platforms": [
diff --git a/third_party/angle b/third_party/angle index f094a81..6551324 160000 --- a/third_party/angle +++ b/third_party/angle
@@ -1 +1 @@ -Subproject commit f094a81e4bd591801933a7ff08c093c4da5228cc +Subproject commit 6551324044bc6a476d2d5ad372d34f49f6cba25e
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 2420456..0ed395bd 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
@@ -4347,7 +4347,7 @@ kV8ModelGenericSession_Destroy_Method = 4973, kUsedDeviceScaleAdjustment = 4974, kOBSOLETE_DisableThirdPartyStoragePartitioning2 = 4975, - kLinkRelPayment = 4976, + kLinkRelFacilitatedPayment = 4976, kOBSOLETE_V8GPUAdapter_RequestAdapterInfo_Method = 4977, kOBSOLETE_V8ModelGenericSession_Destroy_Method = 4978, kOBSOLETE_V8AITextSession_Execute_Method = 4979,
diff --git a/third_party/blink/renderer/core/css/basic_shape_functions.cc b/third_party/blink/renderer/core/css/basic_shape_functions.cc index ee5b76b..f6439d4 100644 --- a/third_party/blink/renderer/core/css/basic_shape_functions.cc +++ b/third_party/blink/renderer/core/css/basic_shape_functions.cc
@@ -30,6 +30,7 @@ #include "third_party/blink/renderer/core/css/basic_shape_functions.h" #include "base/memory/scoped_refptr.h" +#include "base/notreached.h" #include "third_party/blink/renderer/core/css/css_basic_shape_values.h" #include "third_party/blink/renderer/core/css/css_identifier_value.h" #include "third_party/blink/renderer/core/css/css_numeric_literal_value.h" @@ -47,6 +48,8 @@ #include "third_party/blink/renderer/core/style/computed_style.h" #include "third_party/blink/renderer/core/style/style_ray.h" #include "third_party/blink/renderer/core/style/style_shape.h" +#include "third_party/blink/renderer/core/svg/svg_path_data.h" +#include "third_party/blink/renderer/platform/geometry/length_point.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" namespace blink { @@ -92,43 +95,106 @@ CSSValuePair::IdenticalValuesPolicy::kKeepIdenticalValues); } +template <typename T, wtf_size_t NumControlPoints = T::GetNumControlPoints()> +StyleShape::Segment CurveCommandToShapeSegment( + const cssvalue::CSSShapeCommand& command, + const StyleResolverState& state) { + const auto& curve = + static_cast<const cssvalue::CSSShapeCurveCommand<NumControlPoints>&>( + command); + std::array<StyleShape::ControlPoint, NumControlPoints> control_points; + + std::ranges::transform( + curve.GetControlPoints(), control_points.begin(), + [&](const cssvalue::CSSShapeControlPoint& value) { + StyleShape::ControlPoint result{ + .point = + StyleBuilderConverter::ConvertPosition(state, *value.second)}; + + switch (value.first) { + case CSSValueID::kStart: + result.origin = StyleShape::ControlPoint::Origin::kSegmentStart; + break; + case CSSValueID::kEnd: + result.origin = StyleShape::ControlPoint::Origin::kSegmentEnd; + break; + case CSSValueID::kOrigin: + result.origin = StyleShape::ControlPoint::Origin::kReferenceBox; + break; + default: + NOTREACHED(); + } + + return result; + }); + + return T{ + {{StyleBuilderConverter::ConvertPosition(state, command.GetEndPoint())}, + std::move(control_points)}}; +} + StyleShape::Segment ShapeCommandToShapeSegment( const cssvalue::CSSShapeCommand& command, const StyleResolverState& state) { - // TODO(crbug.com/384870259): support other segment types. - bool is_relative = command.GetEndPointOrigin() == CSSValueID::kBy; - using Segment = StyleShape::Segment; - switch (command.GetType()) { - case CSSValueID::kMove: { - LengthPoint target_point = - StyleBuilderConverter::ConvertPosition(state, command.GetEndPoint()); - return is_relative ? Segment(StyleShape::MoveBySegment{target_point}) - : Segment(StyleShape::MoveToSegment{target_point}); - } - case CSSValueID::kLine: { - LengthPoint target_point = - StyleBuilderConverter::ConvertPosition(state, command.GetEndPoint()); - return is_relative ? Segment(StyleShape::LineBySegment{target_point}) - : Segment(StyleShape::LineToSegment{target_point}); - } - case CSSValueID::kHline: { - Length x = + case SVGPathSegType::kPathSegMoveToAbs: + return StyleShape::MoveToSegment{ + StyleBuilderConverter::ConvertPosition(state, command.GetEndPoint())}; + case SVGPathSegType::kPathSegMoveToRel: + return StyleShape::MoveBySegment{ + StyleBuilderConverter::ConvertPosition(state, command.GetEndPoint())}; + case SVGPathSegType::kPathSegLineToAbs: + return StyleShape::LineToSegment{ + StyleBuilderConverter::ConvertPosition(state, command.GetEndPoint())}; + case SVGPathSegType::kPathSegLineToRel: + return StyleShape::LineBySegment{ + StyleBuilderConverter::ConvertPosition(state, command.GetEndPoint())}; + case SVGPathSegType::kPathSegLineToHorizontalAbs: + return StyleShape::HLineToSegment{ StyleBuilderConverter::ConvertPositionLength<CSSValueID::kLeft, CSSValueID::kRight>( - state, command.GetEndPoint()); - return is_relative ? Segment(StyleShape::HLineBySegment{x}) - : Segment(StyleShape::HLineToSegment{x}); - } - case CSSValueID::kVline: { - Length y = + state, command.GetEndPoint())}; + case SVGPathSegType::kPathSegLineToHorizontalRel: + return StyleShape::HLineBySegment{ + StyleBuilderConverter::ConvertPositionLength<CSSValueID::kLeft, + CSSValueID::kRight>( + state, command.GetEndPoint())}; + case SVGPathSegType::kPathSegLineToVerticalAbs: + return StyleShape::VLineToSegment{ StyleBuilderConverter::ConvertPositionLength<CSSValueID::kTop, CSSValueID::kBottom>( - state, command.GetEndPoint()); - return is_relative ? Segment(StyleShape::VLineBySegment{y}) - : Segment(StyleShape::VLineToSegment{y}); - } - case CSSValueID::kArc: { + state, command.GetEndPoint())}; + case SVGPathSegType::kPathSegLineToVerticalRel: + return StyleShape::VLineBySegment{ + StyleBuilderConverter::ConvertPositionLength<CSSValueID::kTop, + CSSValueID::kBottom>( + state, command.GetEndPoint())}; + case SVGPathSegType::kPathSegCurveToCubicAbs: + return CurveCommandToShapeSegment<StyleShape::CubicCurveToSegment>( + command, state); + case SVGPathSegType::kPathSegCurveToCubicRel: + return CurveCommandToShapeSegment<StyleShape::CubicCurveBySegment>( + command, state); + case SVGPathSegType::kPathSegCurveToQuadraticAbs: + return CurveCommandToShapeSegment<StyleShape::QuadraticCurveToSegment>( + command, state); + case SVGPathSegType::kPathSegCurveToQuadraticRel: + return CurveCommandToShapeSegment<StyleShape::QuadraticCurveBySegment>( + command, state); + case SVGPathSegType::kPathSegCurveToCubicSmoothAbs: + return CurveCommandToShapeSegment<StyleShape::SmoothCubicCurveToSegment>( + command, state); + case SVGPathSegType::kPathSegCurveToCubicSmoothRel: + return CurveCommandToShapeSegment<StyleShape::SmoothCubicCurveBySegment>( + command, state); + case SVGPathSegType::kPathSegCurveToQuadraticSmoothAbs: + return StyleShape::SmoothQuadraticCurveToSegment{ + StyleBuilderConverter::ConvertPosition(state, command.GetEndPoint())}; + case SVGPathSegType::kPathSegCurveToQuadraticSmoothRel: + return StyleShape::SmoothQuadraticCurveBySegment{ + StyleBuilderConverter::ConvertPosition(state, command.GetEndPoint())}; + case SVGPathSegType::kPathSegArcAbs: + case SVGPathSegType::kPathSegArcRel: { const cssvalue::CSSShapeArcCommand& arc = static_cast<const cssvalue::CSSShapeArcCommand&>(command); @@ -141,14 +207,15 @@ StyleBuilderConverter::ConvertRadius(state, arc.Radius()); bool large = arc.Size() == CSSValueID::kLarge; bool sweep = arc.Sweep() == CSSValueID::kCw; - return is_relative ? Segment(StyleShape::ArcBySegment{ - {{target_point}, angle, radius, large, sweep}}) - : Segment(StyleShape::ArcToSegment{ - {{target_point}, angle, radius, large, sweep}}); + return command.GetType() == SVGPathSegType::kPathSegArcAbs + ? StyleShape::Segment(StyleShape::ArcToSegment{ + {{target_point}, angle, radius, large, sweep}}) + : StyleShape::Segment(StyleShape::ArcBySegment{ + {{target_point}, angle, radius, large, sweep}}); } - case CSSValueID::kClose: + case SVGPathSegType::kPathSegClosePath: return StyleShape::CloseSegment{}; - default: + case SVGPathSegType::kPathSegUnknown: NOTREACHED(); } } @@ -160,48 +227,128 @@ const CSSShapeCommand* operator()(const StyleShape::MoveToSegment& segment) { return MakeGarbageCollected<const CSSShapeCommand>( - CSSValueID::kMove, CSSValueID::kTo, - LengthPointToCSSValue(segment.target_point, zoom)); + segment.kSegType, LengthPointToCSSValue(segment.target_point, zoom)); } const CSSShapeCommand* operator()(const StyleShape::MoveBySegment& segment) { return MakeGarbageCollected<const CSSShapeCommand>( - CSSValueID::kMove, CSSValueID::kBy, - LengthPointToCSSValue(segment.target_point, zoom)); + segment.kSegType, LengthPointToCSSValue(segment.target_point, zoom)); } const CSSShapeCommand* operator()(const StyleShape::LineToSegment& segment) { return MakeGarbageCollected<const CSSShapeCommand>( - CSSValueID::kLine, CSSValueID::kTo, - LengthPointToCSSValue(segment.target_point, zoom)); + segment.kSegType, LengthPointToCSSValue(segment.target_point, zoom)); } const CSSShapeCommand* operator()(const StyleShape::LineBySegment& segment) { return MakeGarbageCollected<const CSSShapeCommand>( - CSSValueID::kLine, CSSValueID::kBy, - LengthPointToCSSValue(segment.target_point, zoom)); + segment.kSegType, LengthPointToCSSValue(segment.target_point, zoom)); } const CSSShapeCommand* operator()(const StyleShape::HLineToSegment& segment) { return MakeGarbageCollected<const CSSShapeCommand>( - CSSValueID::kHline, CSSValueID::kTo, + segment.kSegType, *CSSPrimitiveValue::CreateFromLength(segment.x, zoom)); } const CSSShapeCommand* operator()(const StyleShape::HLineBySegment& segment) { return MakeGarbageCollected<const CSSShapeCommand>( - CSSValueID::kHline, CSSValueID::kBy, + segment.kSegType, *CSSPrimitiveValue::CreateFromLength(segment.x, zoom)); } const CSSShapeCommand* operator()(const StyleShape::VLineToSegment& segment) { return MakeGarbageCollected<const CSSShapeCommand>( - CSSValueID::kVline, CSSValueID::kTo, + segment.kSegType, *CSSPrimitiveValue::CreateFromLength(segment.y, zoom)); } const CSSShapeCommand* operator()(const StyleShape::VLineBySegment& segment) { return MakeGarbageCollected<const CSSShapeCommand>( - CSSValueID::kVline, CSSValueID::kBy, + segment.kSegType, *CSSPrimitiveValue::CreateFromLength(segment.y, zoom)); } - const CSSShapeCommand* Arc(CSSValueID origin, - const StyleShape::ArcSegment& segment) { + + const CSSShapeCommand* operator()( + const StyleShape::CubicCurveToSegment& segment) { + return MakeGarbageCollected<cssvalue::CSSShapeCurveCommand<2>>( + segment.kSegType, LengthPointToCSSValue(segment.target_point, zoom), + ToControlPoint(segment.control_points.at(0)), + ToControlPoint(segment.control_points.at(1))); + } + + const CSSShapeCommand* operator()( + const StyleShape::CubicCurveBySegment& segment) { + return MakeGarbageCollected<cssvalue::CSSShapeCurveCommand<2>>( + segment.kSegType, LengthPointToCSSValue(segment.target_point, zoom), + ToControlPoint(segment.control_points.at(0)), + ToControlPoint(segment.control_points.at(1))); + } + + const CSSShapeCommand* operator()( + const StyleShape::QuadraticCurveToSegment& segment) { + return MakeGarbageCollected<cssvalue::CSSShapeCurveCommand<2>>( + segment.kSegType, LengthPointToCSSValue(segment.target_point, zoom), + ToControlPoint(segment.control_points.at(0))); + } + const CSSShapeCommand* operator()( + const StyleShape::QuadraticCurveBySegment& segment) { + return MakeGarbageCollected<cssvalue::CSSShapeCurveCommand<2>>( + segment.kSegType, LengthPointToCSSValue(segment.target_point, zoom), + ToControlPoint(segment.control_points.at(0))); + } + const CSSShapeCommand* operator()( + const StyleShape::SmoothCubicCurveToSegment& segment) { + return MakeGarbageCollected<cssvalue::CSSShapeCurveCommand<2>>( + segment.kSegType, LengthPointToCSSValue(segment.target_point, zoom), + ToControlPoint(segment.control_points.at(0))); + } + + const CSSShapeCommand* operator()( + const StyleShape::SmoothCubicCurveBySegment& segment) { + return MakeGarbageCollected<cssvalue::CSSShapeCurveCommand<2>>( + segment.kSegType, LengthPointToCSSValue(segment.target_point, zoom), + ToControlPoint(segment.control_points.at(0))); + } + + const CSSShapeCommand* operator()( + const StyleShape::SmoothQuadraticCurveToSegment& segment) { + return MakeGarbageCollected<const cssvalue::CSSShapeCommand>( + segment.kSegType, LengthPointToCSSValue(segment.target_point, zoom)); + } + const CSSShapeCommand* operator()( + const StyleShape::SmoothQuadraticCurveBySegment& segment) { + return MakeGarbageCollected<const cssvalue::CSSShapeCommand>( + segment.kSegType, LengthPointToCSSValue(segment.target_point, zoom)); + } + + const CSSShapeCommand* operator()(const StyleShape::ArcToSegment& segment) { + return Arc(segment.kSegType, segment); + } + const CSSShapeCommand* operator()(const StyleShape::ArcBySegment& segment) { + return Arc(segment.kSegType, segment); + } + + const CSSShapeCommand* operator()(const StyleShape::CloseSegment&) { + return CSSShapeCommand::Close(); + } + + const cssvalue::CSSShapeControlPoint ToControlPoint( + const StyleShape::ControlPoint& control_point) { + CSSValueID origin; + switch (control_point.origin) { + case StyleShape::ControlPoint::Origin::kReferenceBox: + origin = CSSValueID::kOrigin; + break; + case StyleShape::ControlPoint::Origin::kSegmentStart: + origin = CSSValueID::kStart; + break; + case StyleShape::ControlPoint::Origin::kSegmentEnd: + origin = CSSValueID::kEnd; + break; + } + return cssvalue::CSSShapeControlPoint( + origin, LengthPointToCSSValue(control_point.point, zoom)); + } + + template <SVGPathSegType T> + const CSSShapeCommand* Arc(CSSShapeCommand::Type type, + const StyleShape::ArcSegment<T>& segment) { return MakeGarbageCollected<const cssvalue::CSSShapeArcCommand>( - origin, LengthPointToCSSValue(segment.target_point, zoom), + type, LengthPointToCSSValue(segment.target_point, zoom), *CSSNumericLiteralValue::Create(segment.angle, CSSPrimitiveValue::UnitType::kDegrees), *MakeGarbageCollected<CSSValuePair>( @@ -212,17 +359,6 @@ segment.sweep ? CSSValueID::kCw : CSSValueID::kCcw); } - const CSSShapeCommand* operator()(const StyleShape::ArcToSegment& segment) { - return Arc(CSSValueID::kTo, segment); - } - const CSSShapeCommand* operator()(const StyleShape::ArcBySegment& segment) { - return Arc(CSSValueID::kBy, segment); - } - - const CSSShapeCommand* operator()(const StyleShape::CloseSegment&) { - return CSSShapeCommand::Close(); - } - float zoom; };
diff --git a/third_party/blink/renderer/core/css/css_shape_value.cc b/third_party/blink/renderer/core/css/css_shape_value.cc index 72c9bb1..6a7b9dc 100644 --- a/third_party/blink/renderer/core/css/css_shape_value.cc +++ b/third_party/blink/renderer/core/css/css_shape_value.cc
@@ -6,51 +6,144 @@ #include <memory> +#include "base/notreached.h" #include "third_party/blink/renderer/core/css/css_numeric_literal_value.h" #include "third_party/blink/renderer/core/css/css_value.h" #include "third_party/blink/renderer/core/css/cssom/css_numeric_value.h" #include "third_party/blink/renderer/core/css_value_keywords.h" +#include "third_party/blink/renderer/core/svg/svg_path_data.h" #include "third_party/blink/renderer/platform/heap/persistent.h" #include "third_party/blink/renderer/platform/wtf/text/string_builder.h" #include "third_party/blink/renderer/platform/wtf/wtf_size_t.h" namespace blink::cssvalue { +namespace { +void AppendControlPointCSSText(StringBuilder& builder, + const CSSShapeControlPoint& control_point, + bool is_relative) { + builder.Append(control_point.second->CssText()); + if ((is_relative && control_point.first != CSSValueID::kStart) || + (!is_relative && control_point.first != CSSValueID::kOrigin)) { + builder.Append(" from "); + builder.Append(GetCSSValueNameAs<StringView>(control_point.first)); + } +} +} // namespace String CSSShapeCommand::CSSText() const { - if (type_ == CSSValueID::kClose) { + if (type_ == Type::kPathSegClosePath) { return GetCSSValueNameAs<String>(CSSValueID::kClose); } StringBuilder builder; - builder.Append(GetCSSValueNameAs<StringView>(type_)); - builder.Append(' '); - builder.Append(GetCSSValueNameAs<StringView>(end_point_origin_)); - builder.Append(' '); + switch (type_) { + case Type::kPathSegMoveToAbs: + builder.Append("move to "); + break; + case Type::kPathSegMoveToRel: + builder.Append("move by "); + break; + case Type::kPathSegLineToAbs: + builder.Append("line to "); + break; + case Type::kPathSegLineToRel: + builder.Append("line by "); + break; + case Type::kPathSegLineToHorizontalAbs: + builder.Append("hline to "); + break; + case Type::kPathSegLineToHorizontalRel: + builder.Append("hline by "); + break; + case Type::kPathSegLineToVerticalAbs: + builder.Append("vline to "); + break; + case Type::kPathSegLineToVerticalRel: + builder.Append("vline by "); + break; + case Type::kPathSegCurveToCubicAbs: + case Type::kPathSegCurveToQuadraticAbs: + builder.Append("curve to "); + break; + case Type::kPathSegCurveToCubicRel: + case Type::kPathSegCurveToQuadraticRel: + builder.Append("curve by "); + break; + case Type::kPathSegCurveToCubicSmoothAbs: + case Type::kPathSegCurveToQuadraticSmoothAbs: + builder.Append("smooth to "); + break; + case Type::kPathSegCurveToCubicSmoothRel: + case Type::kPathSegCurveToQuadraticSmoothRel: + builder.Append("smooth by "); + break; + case Type::kPathSegArcAbs: + builder.Append("arc to "); + break; + case Type::kPathSegArcRel: + builder.Append("arc by "); + break; + default: + NOTREACHED(); + } + builder.Append(end_point_->CssText()); - if (type_ == CSSValueID::kArc) { - const CSSShapeArcCommand& arc = - static_cast<const CSSShapeArcCommand&>(*this); - builder.Append(" of "); - builder.Append(arc.Radius().CssText()); - if (arc.Size() == CSSValueID::kCw) { - builder.Append(" cw"); + switch (type_) { + case Type::kPathSegCurveToCubicAbs: + case Type::kPathSegCurveToCubicRel: { + const auto& curve = static_cast<const CSSShapeCurveCommand<2>&>(*this); + builder.Append(" with "); + AppendControlPointCSSText(builder, curve.GetControlPoints().at(0), + type_ == Type::kPathSegCurveToCubicRel); + builder.Append(" / "); + AppendControlPointCSSText(builder, curve.GetControlPoints().at(1), + type_ == Type::kPathSegCurveToCubicRel); + break; } - if (arc.Sweep() == CSSValueID::kLarge) { - builder.Append(" large"); + + case Type::kPathSegCurveToQuadraticAbs: + case Type::kPathSegCurveToQuadraticRel: + case Type::kPathSegCurveToCubicSmoothAbs: + case Type::kPathSegCurveToCubicSmoothRel: { + const auto& curve = static_cast<const CSSShapeCurveCommand<1>&>(*this); + builder.Append(" with "); + AppendControlPointCSSText( + builder, curve.GetControlPoints().at(0), + type_ == Type::kPathSegCurveToQuadraticRel || + type_ == Type::kPathSegCurveToCubicSmoothRel); + break; } - auto* numeric_angle = DynamicTo<CSSNumericLiteralValue>(arc.Angle()); - if (!numeric_angle || numeric_angle->ComputeDegrees() != 0) { - builder.Append(" rotate "); - builder.Append(arc.Angle().CssText()); + + case Type::kPathSegArcAbs: + case Type::kPathSegArcRel: { + const CSSShapeArcCommand& arc = + static_cast<const CSSShapeArcCommand&>(*this); + builder.Append(" of "); + builder.Append(arc.Radius().CssText()); + if (arc.Sweep() == CSSValueID::kCw) { + builder.Append(" cw"); + } + if (arc.Size() == CSSValueID::kLarge) { + builder.Append(" large"); + } + auto* numeric_angle = DynamicTo<CSSNumericLiteralValue>(arc.Angle()); + if (!numeric_angle || numeric_angle->ComputeDegrees() != 0) { + builder.Append(" rotate "); + builder.Append(arc.Angle().CssText()); + } + break; } + default: + break; } + return builder.ReleaseString(); } bool CSSShapeCommand::operator==(const CSSShapeCommand& other) const { - return type_ == other.type_ && end_point_origin_ == other.end_point_origin_ && + return type_ == other.type_ && base::ValuesEquivalent(end_point_, other.end_point_); }
diff --git a/third_party/blink/renderer/core/css/css_shape_value.h b/third_party/blink/renderer/core/css/css_shape_value.h index 9a90397b..f290bcd3 100644 --- a/third_party/blink/renderer/core/css/css_shape_value.h +++ b/third_party/blink/renderer/core/css/css_shape_value.h
@@ -11,6 +11,7 @@ #include "third_party/blink/renderer/core/css/css_value_list.h" #include "third_party/blink/renderer/core/css/css_value_pair.h" #include "third_party/blink/renderer/core/css_value_keywords.h" +#include "third_party/blink/renderer/core/svg/svg_path_data.h" #include "third_party/blink/renderer/platform/graphics/graphics_types.h" #include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" @@ -25,20 +26,18 @@ // Each command’s starting point is the previous command’s ending point. class CSSShapeCommand : public GarbageCollected<CSSShapeCommand> { public: - CSSValueID GetType() const { return type_; } - CSSValueID GetEndPointOrigin() const { return end_point_origin_; } + using Type = SVGPathSegType; + Type GetType() const { return type_; } const CSSValue& GetEndPoint() const { return *end_point_; } + bool IsAbsolute() const { return IsAbsolutePathSegType(type_); } String CSSText() const; bool operator==(const CSSShapeCommand& other) const; virtual void Trace(Visitor* visitor) const { visitor->Trace(end_point_); } - CSSShapeCommand(CSSValueID type, CSSValueID origin, const CSSValue& end_point) - : type_(type), end_point_origin_(origin), end_point_(end_point) { - CHECK(type == CSSValueID::kMove || type == CSSValueID::kLine || - type == CSSValueID::kHline || type == CSSValueID::kVline || - type == CSSValueID::kArc); - CHECK(origin == CSSValueID::kTo || origin == CSSValueID::kBy); + CSSShapeCommand(Type type, const CSSValue& end_point) + : type_(type), end_point_(end_point) { + CHECK(type != Type::kPathSegClosePath); } static const CSSShapeCommand* Close() { @@ -46,34 +45,27 @@ } // This should be private, but can't because of MakeGarbageCollected. - CSSShapeCommand() : type_(CSSValueID::kClose) {} + CSSShapeCommand() : type_(Type::kPathSegClosePath) {} private: - // Either kMove or kLine. - CSSValueID type_; - - // Either kBy or kTo. - // See https://drafts.csswg.org/css-shapes-2/#typedef-shape-command-end-point - // https://drafts.csswg.org/css-shapes-2/#valdef-shape-to is relative to the - // reference box, https://drafts.csswg.org/css-shapes-2/#valdef-shape-by is - // relative to the end of the previous command. - CSSValueID end_point_origin_; + Type type_; Member<const CSSValue> end_point_; }; class CSSShapeArcCommand : public CSSShapeCommand { public: - CSSShapeArcCommand(CSSValueID origin, + CSSShapeArcCommand(Type type, const CSSValue& end_point, const CSSPrimitiveValue& angle, const CSSValuePair& radius, CSSValueID size, CSSValueID sweep) - : CSSShapeCommand(CSSValueID::kArc, origin, end_point), + : CSSShapeCommand(type, end_point), angle_(angle), radius_(radius), size_(size), sweep_(sweep) { + CHECK(type == Type::kPathSegArcAbs || type == Type::kPathSegArcRel); CHECK(sweep == CSSValueID::kCw || sweep == CSSValueID::kCcw); CHECK(size == CSSValueID::kLarge || size == CSSValueID::kSmall); } @@ -99,6 +91,44 @@ CSSValueID sweep_; }; +using CSSShapeControlPoint = std::pair<CSSValueID, Member<const CSSValuePair>>; + +template <wtf_size_t NumControlPoints> +class CSSShapeCurveCommand : public CSSShapeCommand { + public: + CSSShapeCurveCommand<1>(Type type, + const CSSValuePair& end_point, + const CSSShapeControlPoint control_point) + : CSSShapeCommand(type, end_point), control_points_{control_point} {} + CSSShapeCurveCommand(Type type, + const CSSValuePair& end_point, + const CSSShapeControlPoint control_point1, + const CSSShapeControlPoint control_point2) + : CSSShapeCommand(type, end_point), + control_points_{control_point1, control_point2} {} + + bool operator==(const CSSShapeCurveCommand<NumControlPoints>& other) const { + return CSSShapeCommand::operator==(other) && + control_points_ == other.control_points_; + } + + void Trace(Visitor* visitor) const override { + CSSShapeCommand::Trace(visitor); + visitor->Trace(control_points_.at(0).second); + if (NumControlPoints == 2) { + visitor->Trace(control_points_.at(1).second); + } + } + + const std::array<CSSShapeControlPoint, NumControlPoints>& GetControlPoints() + const { + return control_points_; + } + + private: + std::array<CSSShapeControlPoint, NumControlPoints> control_points_; +}; + class CSSShapeValue : public CSSValue { public: CSSShapeValue(WindRule wind_rule,
diff --git a/third_party/blink/renderer/core/css/css_value_keywords.json5 b/third_party/blink/renderer/core/css/css_value_keywords.json5 index 94f6e29..62cad58 100644 --- a/third_party/blink/renderer/core/css/css_value_keywords.json5 +++ b/third_party/blink/renderer/core/css/css_value_keywords.json5
@@ -1401,6 +1401,12 @@ // "large", // "small", // "of", + "curve", + // "smooth", + // "start", + // "end", + "origin", + "with", // @font-face src "format",
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 d75f90bb..3fbfa07 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
@@ -5,6 +5,8 @@ #include "third_party/blink/renderer/core/css/properties/css_parsing_utils.h" #include <cmath> +#include <cstddef> +#include <initializer_list> #include <memory> #include <utility> @@ -86,6 +88,7 @@ #include "third_party/blink/renderer/core/style_property_shorthand.h" #include "third_party/blink/renderer/core/svg/svg_parsing_error.h" #include "third_party/blink/renderer/core/svg/svg_path_byte_stream_builder.h" +#include "third_party/blink/renderer/core/svg/svg_path_data.h" #include "third_party/blink/renderer/core/svg/svg_path_utilities.h" #include "third_party/blink/renderer/platform/animation/timing_function.h" #include "third_party/blink/renderer/platform/fonts/font_selection_types.h" @@ -6737,6 +6740,49 @@ } } +const CSSValuePair* ConsumeShapeCommandControlPoint( + CSSParserTokenStream& args, + const CSSParserContext& context, + CSSValueID end_point_origin, + CSSValueID& control_point_origin) { + const CSSValuePair* control_point = nullptr; + if (end_point_origin == CSSValueID::kTo) { + control_point = + ConsumePosition(args, context, UnitlessQuirk::kForbid, std::nullopt); + if (!control_point) { + return nullptr; + } + if (control_point->First().IsIdentifierValue() || + control_point->Second().IsIdentifierValue()) { + control_point_origin = CSSValueID::kOrigin; + return control_point; + } + } else { + control_point = ConsumeCoordinatePair(args, context); + if (!control_point) { + return nullptr; + } + } + + if (args.Peek().Id() != CSSValueID::kFrom) { + control_point_origin = end_point_origin == CSSValueID::kTo + ? CSSValueID::kOrigin + : CSSValueID::kStart; + return control_point; + } + + args.ConsumeIncludingWhitespace(); + if (args.AtEnd()) { + return nullptr; + } + control_point_origin = args.ConsumeIncludingWhitespace().Id(); + if (IdentMatches<CSSValueID::kStart, CSSValueID::kEnd, CSSValueID::kOrigin>( + control_point_origin)) { + return control_point; + } + return nullptr; +} + // https://drafts.csswg.org/css-shapes-2/#funcdef-shape cssvalue::CSSShapeValue* ConsumeBasicShapeShape( CSSParserTokenStream& args, @@ -6785,7 +6831,14 @@ if (const CSSValuePair* end_point = ConsumeShapeCommandEndPoint(args, context, end_point_origin)) { commands.push_back(MakeGarbageCollected<const CSSShapeCommand>( - command_type, end_point_origin, *end_point)); + command_type == CSSValueID::kLine + ? (end_point_origin == CSSValueID::kTo + ? CSSShapeCommand::Type::kPathSegLineToAbs + : CSSShapeCommand::Type::kPathSegLineToRel) + : (end_point_origin == CSSValueID::kTo + ? CSSShapeCommand::Type::kPathSegMoveToAbs + : CSSShapeCommand::Type::kPathSegMoveToRel), + *end_point)); } else { return nullptr; } @@ -6822,13 +6875,109 @@ if (end_point) { commands.push_back(MakeGarbageCollected<const CSSShapeCommand>( - command_type, end_point_origin, *end_point)); + command_type == CSSValueID::kHline + ? (end_point_origin == CSSValueID::kTo + ? CSSShapeCommand::Type::kPathSegLineToHorizontalAbs + : CSSShapeCommand::Type::kPathSegLineToHorizontalRel) + : (end_point_origin == CSSValueID::kTo + ? CSSShapeCommand::Type::kPathSegLineToVerticalAbs + : CSSShapeCommand::Type::kPathSegLineToVerticalRel), + *end_point)); } else { return nullptr; } break; } + case CSSValueID::kCurve: { + const CSSValuePair* end_point = + ConsumeShapeCommandEndPoint(args, context, end_point_origin); + if (!end_point) { + return nullptr; + } + + if (args.ConsumeIncludingWhitespace().Id() != CSSValueID::kWith) { + return nullptr; + } + + CSSValueID control_point_origin_1 = CSSValueID::kInvalid; + + const CSSValuePair* control_point_1 = ConsumeShapeCommandControlPoint( + args, context, end_point_origin, control_point_origin_1); + if (!control_point_1) { + return nullptr; + } + + if (ConsumeSlashIncludingWhitespace(args)) { + CSSValueID control_point_origin_2 = CSSValueID::kInvalid; + if (const CSSValuePair* control_point_2 = + ConsumeShapeCommandControlPoint(args, context, + end_point_origin, + control_point_origin_2)) { + commands.push_back( + MakeGarbageCollected<cssvalue::CSSShapeCurveCommand<2>>( + end_point_origin == CSSValueID::kTo + ? CSSShapeCommand::Type::kPathSegCurveToCubicAbs + : CSSShapeCommand::Type::kPathSegCurveToCubicRel, + *end_point, + cssvalue::CSSShapeControlPoint(control_point_origin_1, + control_point_1), + cssvalue::CSSShapeControlPoint(control_point_origin_2, + control_point_2))); + + } else { + return nullptr; + } + } else { + commands.push_back( + MakeGarbageCollected<cssvalue::CSSShapeCurveCommand<1>>( + end_point_origin == CSSValueID::kTo + ? CSSShapeCommand::Type::kPathSegCurveToQuadraticAbs + : CSSShapeCommand::Type::kPathSegCurveToQuadraticRel, + *end_point, + cssvalue::CSSShapeControlPoint(control_point_origin_1, + control_point_1))); + } + + break; + } + + case CSSValueID::kSmooth: { + const CSSValuePair* end_point = + ConsumeShapeCommandEndPoint(args, context, end_point_origin); + if (!end_point) { + return nullptr; + } + + CSSValueID control_point_origin = CSSValueID::kInvalid; + if (args.Peek().Id() == CSSValueID::kWith) { + args.ConsumeIncludingWhitespace(); + if (const CSSValuePair* control_point = + ConsumeShapeCommandControlPoint( + args, context, end_point_origin, control_point_origin)) { + commands.push_back( + MakeGarbageCollected<cssvalue::CSSShapeCurveCommand<1>>( + end_point_origin == CSSValueID::kTo + ? CSSShapeCommand::Type::kPathSegCurveToCubicSmoothAbs + : CSSShapeCommand::Type::kPathSegCurveToCubicSmoothRel, + *end_point, + cssvalue::CSSShapeControlPoint(control_point_origin, + control_point))); + + } else { + return nullptr; + } + } else { + commands.push_back(MakeGarbageCollected<cssvalue::CSSShapeCommand>( + end_point_origin == CSSValueID::kTo + ? CSSShapeCommand::Type::kPathSegCurveToQuadraticSmoothAbs + : CSSShapeCommand::Type::kPathSegCurveToQuadraticSmoothRel, + *end_point)); + } + + break; + } + // https://drafts.csswg.org/css-shapes-2/#typedef-shape-arc-command // arc [[<by-to> <coordinate-pair>] || [of <length-percentage>{1,2}] || // <arc-sweep>? || <arc-size>?|| rotate <angle>? ] @@ -6925,11 +7074,14 @@ size = CSSValueID::kSmall; } if (sweep == CSSValueID::kInvalid) { - sweep = CSSValueID::kCw; + sweep = CSSValueID::kCcw; } commands.push_back(MakeGarbageCollected<cssvalue::CSSShapeArcCommand>( - end_point_origin, *end_point, *angle, *radius, size, sweep)); + end_point_origin == CSSValueID::kTo + ? CSSShapeCommand::Type::kPathSegArcAbs + : CSSShapeCommand::Type::kPathSegArcRel, + *end_point, *angle, *radius, size, sweep)); break; }
diff --git a/third_party/blink/renderer/core/dom/document_test.cc b/third_party/blink/renderer/core/dom/document_test.cc index 81fbb8a..c6d21ff 100644 --- a/third_party/blink/renderer/core/dom/document_test.cc +++ b/third_party/blink/renderer/core/dom/document_test.cc
@@ -2035,6 +2035,27 @@ }; #if BUILDFLAG(IS_ANDROID) +TEST_F(DocumentTest, PaymentLinkNotHandled_PaymentRel) { + TestPaymentLinkHandler test_payment_link_handler; + + GetDocument().GetFrame()->GetBrowserInterfaceBroker().SetBinderForTesting( + payments::facilitated::mojom::blink::PaymentLinkHandler::Name_, + base::BindRepeating(&TestPaymentLinkHandler::Bind, + base::Unretained(&test_payment_link_handler))); + + ScopedPaymentLinkDetectionForTest payment_link_detection(true); + + // Link elements with rel='payment' won't trigger payment link handling. + SetHtmlInnerHTML(R"HTML( + <head> + <link rel="payment" href="upi://payment_link_1"> + </head> + )HTML"); + + // Check that the payment link was not handled. + EXPECT_EQ(test_payment_link_handler.get_payment_link_handled_counter(), 0); +} + TEST_F(DocumentTest, PaymentLinkHandling_SinglePaymentLink) { TestPaymentLinkHandler test_payment_link_handler; base::RunLoop run_loop; @@ -2050,7 +2071,7 @@ SetHtmlInnerHTML(R"HTML( <head> - <link rel="payment" href="upi://payment_link_1"> + <link rel="facilitated-payment" href="upi://payment_link_1"> </head> )HTML"); @@ -2078,8 +2099,8 @@ SetHtmlInnerHTML(R"HTML( <head> - <link rel="payment" href="upi://payment_link_1"> - <link rel="payment" href="upi://payment_link_2"> + <link rel="facilitated-payment" href="upi://payment_link_1"> + <link rel="facilitated-payment" href="upi://payment_link_2"> </head> )HTML");
diff --git a/third_party/blink/renderer/core/frame/dom_window.cc b/third_party/blink/renderer/core/frame/dom_window.cc index 8458075c..4e0bcfa2 100644 --- a/third_party/blink/renderer/core/frame/dom_window.cc +++ b/third_party/blink/renderer/core/frame/dom_window.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/351564777): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "third_party/blink/renderer/core/frame/dom_window.h" #include <algorithm> @@ -758,67 +753,63 @@ const LocalFrameToken accessing_main_frame_token = accessing_main_frame.GetLocalFrameToken(); - auto it = coop_access_monitor_.begin(); - while (it != coop_access_monitor_.end()) { - if ((*it)->accessing_main_frame != accessing_main_frame_token) { - ++it; - continue; - } + WTF::EraseIf( + coop_access_monitor_, [&](const Member<CoopAccessMonitor>& monitor) { + if (monitor->accessing_main_frame != accessing_main_frame_token) { + return false; + } - String property_name_as_string = property_name; - if ((*it)->is_in_same_virtual_coop_related_group && - (property_name_as_string == "postMessage" || - property_name_as_string == "closed")) { - ++it; - continue; - } + String property_name_as_string = property_name; + if (monitor->is_in_same_virtual_coop_related_group && + (property_name_as_string == "postMessage" || + property_name_as_string == "closed")) { + return false; + } - // TODO(arthursonzogni): Send the blocked-window-url. + // TODO(arthursonzogni): Send the blocked-window-url. - auto location = CaptureSourceLocation( - ExecutionContext::From(isolate->GetCurrentContext())); - // TODO(crbug.com/349583610): Update to use SourceLocation typemap. - auto source_location = network::mojom::blink::SourceLocation::New( - location->Url() ? location->Url() : "", location->LineNumber(), - location->ColumnNumber()); + auto location = CaptureSourceLocation( + ExecutionContext::From(isolate->GetCurrentContext())); + // TODO(crbug.com/349583610): Update to use SourceLocation typemap. + auto source_location = network::mojom::blink::SourceLocation::New( + location->Url() ? location->Url() : "", location->LineNumber(), + location->ColumnNumber()); - accessing_window->GetFrameConsole()->AddMessage( - MakeGarbageCollected<ConsoleMessage>( - mojom::blink::ConsoleMessageSource::kJavaScript, - mojom::blink::ConsoleMessageLevel::kError, - CoopReportOnlyErrorMessage(property_name), location->Clone())); + accessing_window->GetFrameConsole()->AddMessage( + MakeGarbageCollected<ConsoleMessage>( + mojom::blink::ConsoleMessageSource::kJavaScript, + mojom::blink::ConsoleMessageLevel::kError, + CoopReportOnlyErrorMessage(property_name), location->Clone())); - CoopAccessMonitor* monitor = *it; + // If the reporting document hasn't specified any network report + // endpoint(s), then it is likely not interested in receiving + // ReportingObserver's reports. + // + // TODO(arthursonzogni): Reconsider this decision later, developers + // might be interested. + if (monitor->endpoint_defined) { + if (monitor->reporter.is_bound()) { + monitor->reporter->QueueAccessReport( + monitor->report_type, property_name, std::move(source_location), + std::move(monitor->reported_window_url)); + } + // Send a coop-access-violation report. + if (network::IsAccessFromCoopPage(monitor->report_type)) { + ReportingContext::From(accessing_main_frame.DomWindow()) + ->QueueReport(MakeGarbageCollected<Report>( + ReportType::kCoopAccessViolation, + accessing_main_frame.GetDocument()->Url().GetString(), + MakeGarbageCollected<CoopAccessViolationReportBody>( + std::move(location), monitor->report_type, + String(property_name), monitor->reported_window_url))); + } + } - // If the reporting document hasn't specified any network report - // endpoint(s), then it is likely not interested in receiving - // ReportingObserver's reports. - // - // TODO(arthursonzogni): Reconsider this decision later, developers might be - // interested. - if (monitor->endpoint_defined) { - if (monitor->reporter.is_bound()) { - monitor->reporter->QueueAccessReport( - monitor->report_type, property_name, std::move(source_location), - std::move(monitor->reported_window_url)); - } - // Send a coop-access-violation report. - if (network::IsAccessFromCoopPage(monitor->report_type)) { - ReportingContext::From(accessing_main_frame.DomWindow()) - ->QueueReport(MakeGarbageCollected<Report>( - ReportType::kCoopAccessViolation, - accessing_main_frame.GetDocument()->Url().GetString(), - MakeGarbageCollected<CoopAccessViolationReportBody>( - std::move(location), monitor->report_type, - String(property_name), monitor->reported_window_url))); - } - } - - // CoopAccessMonitor are used once and destroyed. This avoids sending - // multiple reports for the same access. - (*it)->reporter.reset(); - it = coop_access_monitor_.erase(it); - } + // CoopAccessMonitor are used once and destroyed. This avoids sending + // multiple reports for the same access. + monitor->reporter.reset(); + return true; + }); } void DOMWindow::DoPostMessage(scoped_refptr<SerializedScriptValue> message, @@ -1120,14 +1111,11 @@ void DOMWindow::DisconnectCoopAccessMonitor( const LocalFrameToken& accessing_main_frame) { - auto it = coop_access_monitor_.begin(); - while (it != coop_access_monitor_.end()) { - if ((*it)->accessing_main_frame == accessing_main_frame) { - it = coop_access_monitor_.erase(it); - } else { - ++it; - } - } + WTF::EraseIf( + coop_access_monitor_, + [&accessing_main_frame](const Member<CoopAccessMonitor>& monitor) { + return monitor->accessing_main_frame == accessing_main_frame; + }); } } // namespace blink
diff --git a/third_party/blink/renderer/core/html/html_link_element.cc b/third_party/blink/renderer/core/html/html_link_element.cc index 81dfa57..6a8d57d0 100644 --- a/third_party/blink/renderer/core/html/html_link_element.cc +++ b/third_party/blink/renderer/core/html/html_link_element.cc
@@ -97,8 +97,9 @@ if (rel_attribute_.IsTermsOfService()) { UseCounter::Count(&GetDocument(), WebFeature::kLinkRelTermsOfService); } - if (rel_attribute_.IsPayment() && GetDocument().IsInOutermostMainFrame()) { - UseCounter::Count(&GetDocument(), WebFeature::kLinkRelPayment); + if (rel_attribute_.IsFacilitatedPayment() && + GetDocument().IsInOutermostMainFrame()) { + UseCounter::Count(&GetDocument(), WebFeature::kLinkRelFacilitatedPayment); MaybeHandlePaymentLink(); } rel_list_->DidUpdateAttributeValue(params.old_value, value); @@ -523,8 +524,8 @@ void HTMLLinkElement::MaybeHandlePaymentLink() { #if BUILDFLAG(IS_ANDROID) KURL payment_link = GetNonEmptyURLAttribute(html_names::kHrefAttr); - if (rel_attribute_.IsPayment() && !payment_link.IsEmpty() && isConnected() && - GetDocument().IsInOutermostMainFrame() && + if (rel_attribute_.IsFacilitatedPayment() && !payment_link.IsEmpty() && + isConnected() && GetDocument().IsInOutermostMainFrame() && RuntimeEnabledFeatures::PaymentLinkDetectionEnabled()) { GetDocument().HandlePaymentLink(payment_link); }
diff --git a/third_party/blink/renderer/core/html/html_link_element_test.cc b/third_party/blink/renderer/core/html/html_link_element_test.cc index 3a29f52..20e2210 100644 --- a/third_party/blink/renderer/core/html/html_link_element_test.cc +++ b/third_party/blink/renderer/core/html/html_link_element_test.cc
@@ -163,19 +163,29 @@ EXPECT_TRUE(GetDocument().IsUseCounted(WebFeature::kLinkRelTermsOfService)); } -// This tests whether `rel=payment` is properly counted. +// This tests whether `rel=facilitated-payment` is properly counted. TEST_F(HTMLLinkElementTest, PaymentCounter) { - // <link rel="payment"> is not counted when absent. + // <link rel="facilitated-payment"> is not counted when absent. GetDocument().head()->setInnerHTML(R"HTML( - <link rel="not-payment" href="https://example.com/"> + <link rel="not-facilitated-payment" href="https://example.com/"> )HTML"); - EXPECT_FALSE(GetDocument().IsUseCounted(WebFeature::kLinkRelPayment)); + EXPECT_FALSE( + GetDocument().IsUseCounted(WebFeature::kLinkRelFacilitatedPayment)); - // <link rel="payment"> is counted when present. + // <link rel="facilitated-payment"> is not counted when <link rel="payment"> + // is present. GetDocument().head()->setInnerHTML(R"HTML( <link rel="payment" href="https://example.com/"> )HTML"); - EXPECT_TRUE(GetDocument().IsUseCounted(WebFeature::kLinkRelPayment)); + EXPECT_FALSE( + GetDocument().IsUseCounted(WebFeature::kLinkRelFacilitatedPayment)); + + // <link rel="facilitated-payment"> is counted when present. + GetDocument().head()->setInnerHTML(R"HTML( + <link rel="facilitated-payment" href="https://example.com/"> + )HTML"); + EXPECT_TRUE( + GetDocument().IsUseCounted(WebFeature::kLinkRelFacilitatedPayment)); } #if BUILDFLAG(IS_ANDROID) @@ -187,7 +197,8 @@ auto* link_element = MakeGarbageCollected<HTMLLinkElement>( GetDocument(), CreateElementFlags()); - link_element->setAttribute(html_names::kRelAttr, AtomicString("payment")); + link_element->setAttribute(html_names::kRelAttr, + AtomicString("facilitated-payment")); link_element->setAttribute(html_names::kHrefAttr, AtomicString("https://example.com/")); GetDocument().head()->appendChild(link_element); @@ -206,7 +217,8 @@ GetDocument(), CreateElementFlags()); link_element->setAttribute(html_names::kHrefAttr, AtomicString("https://example.com/")); - link_element->setAttribute(html_names::kRelAttr, AtomicString("payment")); + link_element->setAttribute(html_names::kRelAttr, + AtomicString("facilitated-payment")); GetDocument().head()->appendChild(link_element); // Ensures Document::HandlePaymentLink is invoked. @@ -222,7 +234,8 @@ auto* link_element = MakeGarbageCollected<HTMLLinkElement>( GetDocument(), CreateElementFlags()); GetDocument().head()->appendChild(link_element); - link_element->setAttribute(html_names::kRelAttr, AtomicString("payment")); + link_element->setAttribute(html_names::kRelAttr, + AtomicString("facilitated-payment")); link_element->setAttribute(html_names::kHrefAttr, AtomicString("https://example.com/")); @@ -241,7 +254,8 @@ GetDocument().head()->appendChild(link_element); link_element->setAttribute(html_names::kHrefAttr, AtomicString("https://example.com/")); - link_element->setAttribute(html_names::kRelAttr, AtomicString("payment")); + link_element->setAttribute(html_names::kRelAttr, + AtomicString("facilitated-payment")); // Ensures Document::HandlePaymentLink is invoked. EXPECT_TRUE(GetDocument().payment_link_handled_); @@ -271,7 +285,8 @@ auto* link_element = MakeGarbageCollected<HTMLLinkElement>( GetDocument(), CreateElementFlags()); - link_element->setAttribute(html_names::kRelAttr, AtomicString("payment")); + link_element->setAttribute(html_names::kRelAttr, + AtomicString("facilitated-payment")); GetDocument().head()->appendChild(link_element); // Ensures Document::HandlePaymentLink is not invoked. @@ -286,7 +301,8 @@ auto* link_element = MakeGarbageCollected<HTMLLinkElement>( GetDocument(), CreateElementFlags()); - link_element->setAttribute(html_names::kRelAttr, AtomicString("payment")); + link_element->setAttribute(html_names::kRelAttr, + AtomicString("facilitated-payment")); link_element->setAttribute(html_names::kHrefAttr, AtomicString("https://example.com/")); @@ -315,7 +331,7 @@ test::RunPendingTasks(); child_frame_resource.Complete(R"HTML( - <link rel="payment" href='https://paymentlinkexample.com/'> + <link rel="facilitated-payment" href='https://paymentlinkexample.com/'> )HTML"); Compositor().BeginFrame(); @@ -328,7 +344,7 @@ iframe_element->contentDocument()->head()->firstChild()); ASSERT_NE(link_element, nullptr); ASSERT_EQ(link_element->FastGetAttribute(html_names::kRelAttr), - AtomicString("payment")); + AtomicString("facilitated-payment")); // Ensures Document::HandlePaymentLink is not invoked. EXPECT_FALSE(GetDocument().payment_link_handled_);
diff --git a/third_party/blink/renderer/core/html/link_rel_attribute.cc b/third_party/blink/renderer/core/html/link_rel_attribute.cc index d6ddcd75..d639abf 100644 --- a/third_party/blink/renderer/core/html/link_rel_attribute.cc +++ b/third_party/blink/renderer/core/html/link_rel_attribute.cc
@@ -85,8 +85,8 @@ is_terms_of_service_ = true; } else if (EqualIgnoringASCIICase(link_type, "expect")) { is_expect_ = true; - } else if (EqualIgnoringASCIICase(link_type, "payment")) { - is_payment_ = true; + } else if (EqualIgnoringASCIICase(link_type, "facilitated-payment")) { + is_facilitated_payment_ = true; } // Adding or removing a value here whose processing model is web-visible
diff --git a/third_party/blink/renderer/core/html/link_rel_attribute.h b/third_party/blink/renderer/core/html/link_rel_attribute.h index ffc3ba72..85ee4fd 100644 --- a/third_party/blink/renderer/core/html/link_rel_attribute.h +++ b/third_party/blink/renderer/core/html/link_rel_attribute.h
@@ -64,7 +64,7 @@ bool IsPrivacyPolicy() const { return is_privacy_policy_; } bool IsTermsOfService() const { return is_terms_of_service_; } bool IsExpect() const { return is_expect_; } - bool IsPayment() const { return is_payment_; } + bool IsFacilitatedPayment() const { return is_facilitated_payment_; } private: mojom::blink::FaviconIconType icon_type_ = @@ -86,7 +86,7 @@ bool is_privacy_policy_ : 1 = false; bool is_terms_of_service_ : 1 = false; bool is_expect_ : 1 = false; - bool is_payment_ : 1 = false; + bool is_facilitated_payment_ : 1 = false; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/html/link_rel_attribute_test.cc b/third_party/blink/renderer/core/html/link_rel_attribute_test.cc index cb4441b..b47bca9 100644 --- a/third_party/blink/renderer/core/html/link_rel_attribute_test.cc +++ b/third_party/blink/renderer/core/html/link_rel_attribute_test.cc
@@ -45,7 +45,7 @@ bool is_preconnect = false, bool is_canonical = false, bool is_compression_dictionary = false, - bool is_payment = false) { + bool is_facilitated_payment = false) { SCOPED_TRACE(value.Utf8()); LinkRelAttribute link_rel_attribute(value); ASSERT_EQ(is_style_sheet, link_rel_attribute.IsStyleSheet()); @@ -57,7 +57,7 @@ ASSERT_EQ(is_canonical, link_rel_attribute.IsCanonical()); ASSERT_EQ(is_compression_dictionary, link_rel_attribute.IsCompressionDictionary()); - ASSERT_EQ(is_payment, link_rel_attribute.IsPayment()); + ASSERT_EQ(is_facilitated_payment, link_rel_attribute.IsFacilitatedPayment()); } TEST(LinkRelAttributeTest, Constructor) { @@ -157,13 +157,13 @@ false, /*is_preconnect=*/false, /*is_canonical=*/false, /*is_compression_dictionary=*/false); TestLinkRelAttribute( - "payment", false, mojom::blink::FaviconIconType::kInvalid, false, false, - false, /*is_preconnect=*/false, /*is_canonical=*/false, - /*is_compression_dictionary=*/false, /*is_payment=*/true); + "facilitated-payment", false, mojom::blink::FaviconIconType::kInvalid, + false, false, false, /*is_preconnect=*/false, /*is_canonical=*/false, + /*is_compression_dictionary=*/false, /*is_facilitated_payment=*/true); TestLinkRelAttribute( - "pAymENt", false, mojom::blink::FaviconIconType::kInvalid, false, false, - false, /*is_preconnect=*/false, /*is_canonical=*/false, - /*is_compression_dictionary=*/false, /*is_payment=*/true); + "fAciLitaTed-pAymENt", false, mojom::blink::FaviconIconType::kInvalid, + false, false, false, /*is_preconnect=*/false, /*is_canonical=*/false, + /*is_compression_dictionary=*/false, /*is_facilitated_payment=*/true); } } // namespace blink
diff --git a/third_party/blink/renderer/core/paint/paint_layer.cc b/third_party/blink/renderer/core/paint/paint_layer.cc index 10ddcc4..3488866 100644 --- a/third_party/blink/renderer/core/paint/paint_layer.cc +++ b/third_party/blink/renderer/core/paint/paint_layer.cc
@@ -180,7 +180,6 @@ needs_descendant_dependent_flags_update_(true), needs_visual_overflow_recalc_(true), has_visible_self_painting_descendant_(false), - has3d_transformed_descendant_(false), needs_cull_rect_update_(false), forces_children_cull_rect_update_(false), descendant_needs_cull_rect_update_(false), @@ -461,6 +460,11 @@ GetLayoutObject().View()->SetBackgroundNeedsFullPaintInvalidation(); GetLayoutObject().SetNeedsPaintPropertyUpdate(); } + + if (RuntimeEnabledFeatures::Fast3DTransformedDescendantStatusEnabled()) { + Update3DTransformedDescendantStatus(); + } + needs_descendant_dependent_flags_update_ = false; if (IsSelfPaintingLayer() && needs_visual_overflow_recalc_) { @@ -513,28 +517,22 @@ layout_object_->SetShouldCheckForPaintInvalidation(); } - Update3DTransformedDescendantStatus(); + if (!RuntimeEnabledFeatures::Fast3DTransformedDescendantStatusEnabled()) { + Update3DTransformedDescendantStatus(); + } } void PaintLayer::Update3DTransformedDescendantStatus() { - has3d_transformed_descendant_ = false; + has_3d_transformed_descendant_ = false; // Transformed or preserve-3d descendants can only be in the z-order lists, // not in the normal flow list, so we only need to check those. PaintLayerPaintOrderIterator iterator(this, kStackedChildren); while (PaintLayer* child_layer = iterator.Next()) { - bool child_has3d = false; - // If the child lives in a 3d hierarchy, then the layer at the root of - // that hierarchy needs the m_has3DTransformedDescendant set. - if (child_layer->Preserves3D() && - (child_layer->Has3DTransform() || - child_layer->Has3DTransformedDescendant())) - child_has3d = true; - else if (child_layer->Has3DTransform()) - child_has3d = true; - - if (child_has3d) { - has3d_transformed_descendant_ = true; + if (child_layer->Has3DTransform() || + (child_layer->Preserves3D() && + child_layer->Has3DTransformedDescendant())) { + has_3d_transformed_descendant_ = true; break; } } @@ -1327,7 +1325,7 @@ // reference it. DCHECK(container_transform_state); local_transform_state = container_transform_state; - } else if (container_transform_state || has3d_transformed_descendant_) { + } else if (container_transform_state || Has3DTransformedDescendant()) { DCHECK(!Preserves3D()); // We need transform state for the first time, or to offset the container // state, so create it here.
diff --git a/third_party/blink/renderer/core/paint/paint_layer.h b/third_party/blink/renderer/core/paint/paint_layer.h index 24244c3..2519839 100644 --- a/third_party/blink/renderer/core/paint/paint_layer.h +++ b/third_party/blink/renderer/core/paint/paint_layer.h
@@ -499,7 +499,7 @@ bool Has3DTransformedDescendant() const { DCHECK(!needs_descendant_dependent_flags_update_); - return has3d_transformed_descendant_; + return has_3d_transformed_descendant_; } // See @@ -694,7 +694,7 @@ // Set on a stacking context layer that has 3D descendants anywhere // in a preserves3D hierarchy. Hint to do 3D-aware hit testing. - unsigned has3d_transformed_descendant_ : 1; + unsigned has_3d_transformed_descendant_ : 1 = false; unsigned self_needs_repaint_ : 1 = false; // This is marked along the PaintingContainer() chain, i.e. the 'descendant'
diff --git a/third_party/blink/renderer/core/style/style_shape.cc b/third_party/blink/renderer/core/style/style_shape.cc index 77d30a5..db53e87 100644 --- a/third_party/blink/renderer/core/style/style_shape.cc +++ b/third_party/blink/renderer/core/style/style_shape.cc
@@ -14,6 +14,7 @@ #include "third_party/blink/renderer/platform/geometry/length_functions.h" #include "third_party/blink/renderer/platform/geometry/length_point.h" #include "third_party/blink/renderer/platform/graphics/path.h" +#include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/size.h" namespace blink { @@ -37,50 +38,63 @@ SegmentVisitor(SVGPathBuilder& path_builder, const gfx::SizeF& size) : builder(path_builder), box_size(size) {} - void operator()(const StyleShape::MoveToSegment& segment) { - Emit(segment, SVGPathSegType::kPathSegMoveToAbs); - } - - void operator()(const StyleShape::MoveBySegment& segment) { - Emit(segment, SVGPathSegType::kPathSegMoveToRel); - } - - void operator()(const StyleShape::LineToSegment& segment) { - Emit(segment, SVGPathSegType::kPathSegLineToAbs); - } - - void operator()(const StyleShape::LineBySegment& segment) { - Emit(segment, SVGPathSegType::kPathSegLineToRel); - } - - void operator()(const StyleShape::HLineToSegment& segment) { - Emit(segment, SVGPathSegType::kPathSegLineToHorizontalAbs); - } - - void operator()(const StyleShape::HLineBySegment& segment) { - Emit(segment, SVGPathSegType::kPathSegLineToHorizontalRel); - } - - void operator()(const StyleShape::VLineToSegment& segment) { - Emit(segment, SVGPathSegType::kPathSegLineToVerticalAbs); - } - - void operator()(const StyleShape::VLineBySegment& segment) { - Emit(segment, SVGPathSegType::kPathSegLineToVerticalRel); - } - - void operator()(const StyleShape::ArcToSegment& segment) { - Emit(segment, SVGPathSegType::kPathSegArcAbs); - } - void operator()(const StyleShape::ArcBySegment& segment) { - Emit(segment, SVGPathSegType::kPathSegArcRel); + template <typename T> + void operator()(const T& segment) { + Emit(segment, T::kSegType); } void operator()(const StyleShape::CloseSegment&) { builder.EmitSegment({.command = SVGPathSegType::kPathSegClosePath}); } private: - void Emit(const StyleShape::SegmentWithTargetPoint& segment, + gfx::PointF PointForControlPoint( + const StyleShape::ControlPoint& control_point, + gfx::PointF start, + gfx::PointF end) const { + gfx::PointF point = PointForLengthPoint(control_point.point, box_size); + switch (control_point.origin) { + case StyleShape::ControlPoint::Origin::kReferenceBox: + return point; + case StyleShape::ControlPoint::Origin::kSegmentStart: + return point + start.OffsetFromOrigin(); + case StyleShape::ControlPoint::Origin::kSegmentEnd: + return point + end.OffsetFromOrigin(); + } + } + + template <size_t NumControlPoints, SVGPathSegType T> + void Emit(const StyleShape::CurveSegment<NumControlPoints, T>& segment, + SVGPathSegType command) { + gfx::PointF segment_start = builder.CurrentPoint(); + gfx::PointF target_point = + PointForLengthPoint(segment.target_point, box_size); + bool is_absolute = IsAbsolutePathSegType(command); + gfx::PointF segment_end = + is_absolute ? target_point + : (segment_start + target_point.OffsetFromOrigin()); + + gfx::PointF point1 = PointForControlPoint(segment.control_points.at(0), + segment_start, segment_end); + PathSegmentData data{.command = ToAbsolutePathSegType(command), + .target_point = segment_end}; + + if (T == SVGPathSegType::kPathSegCurveToCubicSmoothAbs || + T == SVGPathSegType::kPathSegCurveToCubicSmoothRel) { + data.point2 = point1; + } else { + data.point1 = point1; + } + + if (NumControlPoints == 2) { + data.point2 = PointForControlPoint(segment.control_points.at(1), + segment_start, segment_end); + } + + builder.EmitSegment(data); + } + + template <SVGPathSegType T> + void Emit(const StyleShape::SegmentWithTargetPoint<T>& segment, SVGPathSegType command) { builder.EmitSegment( {.command = command, @@ -100,7 +114,8 @@ FloatValueForLength(segment.y, box_size.height())}}); } - void Emit(const StyleShape::ArcSegment& segment, SVGPathSegType command) { + template <SVGPathSegType T> + void Emit(const StyleShape::ArcSegment<T>& segment, SVGPathSegType command) { PathSegmentData arc_data{ .command = command, .target_point = PointForLengthPoint(segment.target_point, box_size),
diff --git a/third_party/blink/renderer/core/style/style_shape.h b/third_party/blink/renderer/core/style/style_shape.h index 9ec8468..420775a 100644 --- a/third_party/blink/renderer/core/style/style_shape.h +++ b/third_party/blink/renderer/core/style/style_shape.h
@@ -5,11 +5,13 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_STYLE_STYLE_SHAPE_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_STYLE_STYLE_SHAPE_H_ +#include <cstddef> #include <optional> #include <variant> #include "base/memory/scoped_refptr.h" #include "third_party/blink/renderer/core/style/basic_shapes.h" +#include "third_party/blink/renderer/core/svg/svg_path_data.h" #include "third_party/blink/renderer/platform/geometry/length_point.h" #include "third_party/blink/renderer/platform/wtf/casting.h" #include "ui/gfx/geometry/rect_f.h" @@ -22,38 +24,91 @@ // values. class StyleShape final : public BasicShape { public: - enum class TargetPointOrigin { kReferenceBox, kPreviousSegment }; using CloseSegment = std::monostate; + template <SVGPathSegType Type> struct SegmentWithTargetPoint { + static constexpr SVGPathSegType kSegType = Type; LengthPoint target_point; bool operator==(const SegmentWithTargetPoint& other) const = default; }; - struct MoveToSegment : public SegmentWithTargetPoint {}; - struct MoveBySegment : public SegmentWithTargetPoint {}; - struct LineToSegment : public SegmentWithTargetPoint {}; - struct LineBySegment : public SegmentWithTargetPoint {}; + struct MoveToSegment + : public SegmentWithTargetPoint<SVGPathSegType::kPathSegMoveToAbs> {}; + struct MoveBySegment + : public SegmentWithTargetPoint<SVGPathSegType::kPathSegMoveToRel> {}; + struct LineToSegment + : public SegmentWithTargetPoint<SVGPathSegType::kPathSegLineToAbs> {}; + struct LineBySegment + : public SegmentWithTargetPoint<SVGPathSegType::kPathSegLineToRel> {}; struct HLineSegment { Length x; bool operator==(const HLineSegment& other) const = default; }; - struct HLineBySegment : public HLineSegment {}; - struct HLineToSegment : public HLineSegment {}; + struct HLineToSegment : public HLineSegment { + static constexpr SVGPathSegType kSegType = + SVGPathSegType::kPathSegLineToHorizontalAbs; + }; + struct HLineBySegment : public HLineSegment { + static constexpr SVGPathSegType kSegType = + SVGPathSegType::kPathSegLineToHorizontalRel; + }; struct VLineSegment { Length y; bool operator==(const VLineSegment& other) const = default; }; - struct VLineBySegment : public VLineSegment {}; - struct VLineToSegment : public VLineSegment {}; - struct ArcSegment : public SegmentWithTargetPoint { + struct VLineToSegment : public VLineSegment { + static constexpr SVGPathSegType kSegType = + SVGPathSegType::kPathSegLineToVerticalAbs; + }; + struct VLineBySegment : public VLineSegment { + static constexpr SVGPathSegType kSegType = + SVGPathSegType::kPathSegLineToVerticalRel; + }; + struct ControlPoint { + enum class Origin { kSegmentStart, kSegmentEnd, kReferenceBox }; + Origin origin; + LengthPoint point; + bool operator==(const ControlPoint& other) const = default; + }; + + template <size_t NumControlPoints, SVGPathSegType Type> + struct CurveSegment : SegmentWithTargetPoint<Type> { + static constexpr size_t GetNumControlPoints() { return NumControlPoints; } + std::array<ControlPoint, NumControlPoints> control_points; + bool operator==(const CurveSegment<NumControlPoints, Type>& other) const = + default; + }; + struct CubicCurveToSegment + : public CurveSegment<2, SVGPathSegType::kPathSegCurveToCubicAbs> {}; + struct CubicCurveBySegment + : public CurveSegment<2, SVGPathSegType::kPathSegCurveToCubicRel> {}; + struct QuadraticCurveToSegment + : public CurveSegment<1, SVGPathSegType::kPathSegCurveToQuadraticAbs> {}; + struct QuadraticCurveBySegment + : public CurveSegment<1, SVGPathSegType::kPathSegCurveToQuadraticRel> {}; + struct SmoothCubicCurveToSegment + : public CurveSegment<1, SVGPathSegType::kPathSegCurveToCubicSmoothAbs> { + }; + struct SmoothCubicCurveBySegment + : public CurveSegment<1, SVGPathSegType::kPathSegCurveToCubicSmoothRel> { + }; + struct SmoothQuadraticCurveToSegment + : public SegmentWithTargetPoint< + SVGPathSegType::kPathSegCurveToQuadraticSmoothAbs> {}; + struct SmoothQuadraticCurveBySegment + : public SegmentWithTargetPoint< + SVGPathSegType::kPathSegCurveToQuadraticSmoothRel> {}; + + template <SVGPathSegType Type> + struct ArcSegment : public SegmentWithTargetPoint<Type> { double angle; LengthSize radius; bool large; bool sweep; bool operator==(const ArcSegment& other) const = default; }; - struct ArcToSegment : public ArcSegment {}; - struct ArcBySegment : public ArcSegment {}; + struct ArcToSegment : public ArcSegment<SVGPathSegType::kPathSegArcAbs> {}; + struct ArcBySegment : public ArcSegment<SVGPathSegType::kPathSegArcRel> {}; using Segment = std::variant<MoveToSegment, MoveBySegment, @@ -63,6 +118,14 @@ HLineBySegment, VLineToSegment, VLineBySegment, + CubicCurveToSegment, + CubicCurveBySegment, + QuadraticCurveToSegment, + QuadraticCurveBySegment, + SmoothCubicCurveToSegment, + SmoothCubicCurveBySegment, + SmoothQuadraticCurveToSegment, + SmoothQuadraticCurveBySegment, ArcToSegment, ArcBySegment, CloseSegment>;
diff --git a/third_party/blink/renderer/core/svg/svg_path_builder.h b/third_party/blink/renderer/core/svg/svg_path_builder.h index a3d59ca..915bfc7 100644 --- a/third_party/blink/renderer/core/svg/svg_path_builder.h +++ b/third_party/blink/renderer/core/svg/svg_path_builder.h
@@ -38,6 +38,8 @@ void EmitSegment(const PathSegmentData&) override; + const gfx::PointF& CurrentPoint() const { return current_point_; } + private: void EmitClose(); void EmitMoveTo(const gfx::PointF&);
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc index e7e298f0..74f3d4d8 100644 --- a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc +++ b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc
@@ -59,8 +59,6 @@ #include "third_party/blink/public/mojom/scroll/scroll_enums.mojom-blink.h" #include "third_party/blink/public/mojom/scroll/scroll_into_view_params.mojom-blink.h" #include "third_party/blink/public/platform/task_type.h" -#include "third_party/blink/renderer/bindings/modules/v8/v8_canvas_rendering_context_2d_settings.h" -#include "third_party/blink/renderer/bindings/modules/v8/v8_canvas_will_read_frequently.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_typedefs.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_union_canvasrenderingcontext2d_gpucanvascontext_imagebitmaprenderingcontext_webgl2renderingcontext_webglrenderingcontext.h" #include "third_party/blink/renderer/core/accessibility/ax_object_cache.h" @@ -92,6 +90,7 @@ #include "third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.h" #include "third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_state.h" #include "third_party/blink/renderer/modules/canvas/canvas2d/path_2d.h" +#include "third_party/blink/renderer/modules/canvas/htmlcanvas/canvas_context_creation_attributes_helpers.h" #include "third_party/blink/renderer/platform/fonts/font.h" #include "third_party/blink/renderer/platform/geometry/layout_unit.h" #include "third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.h" @@ -112,7 +111,6 @@ #include "third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.h" #include "third_party/blink/renderer/platform/graphics/web_graphics_context_3d_provider_util.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" -#include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "third_party/blink/renderer/platform/timer.h" #include "third_party/blink/renderer/platform/wtf/hash_table.h" #include "third_party/blink/renderer/platform/wtf/key_value_pair.h" @@ -162,17 +160,6 @@ "AdjustCanCreateCanvas2dResourceProvider", base::FEATURE_ENABLED_BY_DEFAULT); -// Convert from a PredefinedColorSpace to a V8PredefinedColorSpace. -V8CanvasPixelFormat CanvasPixelFormatToV8(CanvasPixelFormat pixel_format) { - switch (pixel_format) { - case CanvasPixelFormat::kF16: - return V8CanvasPixelFormat(V8CanvasPixelFormat::Enum::kFloat16); - case CanvasPixelFormat::kUint8: - return V8CanvasPixelFormat(V8CanvasPixelFormat::Enum::kUint8); - } - NOTREACHED(); -} - } // namespace CanvasRenderingContext* CanvasRenderingContext2D::Factory::Create( @@ -973,27 +960,7 @@ CanvasRenderingContext2DSettings* CanvasRenderingContext2D::getContextAttributes() const { - const auto& attrs = CreationAttributes(); - CanvasRenderingContext2DSettings* settings = - CanvasRenderingContext2DSettings::Create(); - settings->setAlpha(attrs.alpha); - settings->setColorSpace(PredefinedColorSpaceToV8(attrs.color_space)); - if (RuntimeEnabledFeatures::CanvasFloatingPointEnabled()) { - settings->setPixelFormat( - CanvasPixelFormatToV8(color_params_.PixelFormat())); - } - settings->setDesynchronized(attrs.desynchronized_specified); - - switch (attrs.will_read_frequently) { - case CanvasContextCreationAttributesCore::WillReadFrequently::kTrue: - settings->setWillReadFrequently(true); - break; - case CanvasContextCreationAttributesCore::WillReadFrequently::kFalse: - case CanvasContextCreationAttributesCore::WillReadFrequently::kUndefined: - settings->setWillReadFrequently(false); - break; - } - return settings; + return ToCanvasRenderingContext2DSettings(CreationAttributes()); } void CanvasRenderingContext2D::drawFocusIfNeeded(Element* element) {
diff --git a/third_party/blink/renderer/modules/canvas/htmlcanvas/canvas_context_creation_attributes_helpers.cc b/third_party/blink/renderer/modules/canvas/htmlcanvas/canvas_context_creation_attributes_helpers.cc index 47f46c2..f97968f 100644 --- a/third_party/blink/renderer/modules/canvas/htmlcanvas/canvas_context_creation_attributes_helpers.cc +++ b/third_party/blink/renderer/modules/canvas/htmlcanvas/canvas_context_creation_attributes_helpers.cc
@@ -6,8 +6,12 @@ #include "build/build_config.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_canvas_context_creation_attributes_module.h" +#include "third_party/blink/renderer/bindings/modules/v8/v8_canvas_pixel_format.h" +#include "third_party/blink/renderer/bindings/modules/v8/v8_canvas_rendering_context_2d_settings.h" +#include "third_party/blink/renderer/bindings/modules/v8/v8_canvas_will_read_frequently.h" #include "third_party/blink/renderer/core/html/canvas/canvas_context_creation_attributes_core.h" #include "third_party/blink/renderer/core/html/canvas/predefined_color_space.h" +#include "third_party/blink/renderer/platform/runtime_enabled_features.h" namespace blink { @@ -73,4 +77,36 @@ return true; } +CanvasRenderingContext2DSettings* ToCanvasRenderingContext2DSettings( + const CanvasContextCreationAttributesCore& attrs) { + CanvasRenderingContext2DSettings* settings = + CanvasRenderingContext2DSettings::Create(); + settings->setAlpha(attrs.alpha); + settings->setColorSpace(PredefinedColorSpaceToV8(attrs.color_space)); + if (RuntimeEnabledFeatures::CanvasFloatingPointEnabled()) { + switch (attrs.pixel_format) { + case CanvasPixelFormat::kF16: + settings->setPixelFormat( + V8CanvasPixelFormat(V8CanvasPixelFormat::Enum::kFloat16)); + break; + case CanvasPixelFormat::kUint8: + settings->setPixelFormat( + V8CanvasPixelFormat(V8CanvasPixelFormat::Enum::kUint8)); + break; + } + } + settings->setDesynchronized(attrs.desynchronized_specified); + + switch (attrs.will_read_frequently) { + case CanvasContextCreationAttributesCore::WillReadFrequently::kTrue: + settings->setWillReadFrequently(true); + break; + case CanvasContextCreationAttributesCore::WillReadFrequently::kFalse: + case CanvasContextCreationAttributesCore::WillReadFrequently::kUndefined: + settings->setWillReadFrequently(false); + break; + } + return settings; +} + } // namespace blink
diff --git a/third_party/blink/renderer/modules/canvas/htmlcanvas/canvas_context_creation_attributes_helpers.h b/third_party/blink/renderer/modules/canvas/htmlcanvas/canvas_context_creation_attributes_helpers.h index 03c5270..9910f53 100644 --- a/third_party/blink/renderer/modules/canvas/htmlcanvas/canvas_context_creation_attributes_helpers.h +++ b/third_party/blink/renderer/modules/canvas/htmlcanvas/canvas_context_creation_attributes_helpers.h
@@ -11,12 +11,16 @@ class CanvasContextCreationAttributesCore; class CanvasContextCreationAttributesModule; +class CanvasRenderingContext2DSettings; bool ToCanvasContextCreationAttributes( const CanvasContextCreationAttributesModule*, CanvasContextCreationAttributesCore& result, ExceptionState& exception_state); +CanvasRenderingContext2DSettings* ToCanvasRenderingContext2DSettings( + const CanvasContextCreationAttributesCore&); + } // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_MODULES_CANVAS_HTMLCANVAS_CANVAS_CONTEXT_CREATION_ATTRIBUTES_HELPERS_H_
diff --git a/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.cc b/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.cc index 75107774..c3141db7 100644 --- a/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.cc +++ b/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.cc
@@ -21,6 +21,7 @@ #include "third_party/blink/renderer/core/imagebitmap/image_bitmap.h" #include "third_party/blink/renderer/core/workers/worker_global_scope.h" #include "third_party/blink/renderer/core/workers/worker_settings.h" +#include "third_party/blink/renderer/modules/canvas/htmlcanvas/canvas_context_creation_attributes_helpers.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/fonts/text_run_paint_info.h" #include "third_party/blink/renderer/platform/graphics/canvas_resource_provider.h" @@ -137,6 +138,11 @@ Host()->FlushRecording(reason); } +CanvasRenderingContext2DSettings* +OffscreenCanvasRenderingContext2D::getContextAttributes() const { + return ToCanvasRenderingContext2DSettings(CreationAttributes()); +} + // BaseRenderingContext2D implementation bool OffscreenCanvasRenderingContext2D::OriginClean() const { return Host()->OriginClean();
diff --git a/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.h b/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.h index fb2fa4d..ab6d051c 100644 --- a/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.h +++ b/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.h
@@ -19,6 +19,7 @@ namespace blink { +class CanvasRenderingContext2DSettings; class CanvasResourceProvider; class ExceptionState; @@ -87,6 +88,8 @@ !dirty_rect_for_commit_.isEmpty(); } + CanvasRenderingContext2DSettings* getContextAttributes() const; + // BaseRenderingContext2D implementation bool OriginClean() const final; void SetOriginTainted() final;
diff --git a/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.idl b/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.idl index 05ace65..11b27d8 100644 --- a/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.idl +++ b/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.idl
@@ -11,6 +11,8 @@ // back-reference to the canvas [ImplementedAs=offscreenCanvasForBinding] readonly attribute OffscreenCanvas canvas; + [RuntimeEnabled=OffscreenCanvasGetContextAttributes] CanvasRenderingContext2DSettings getContextAttributes(); + }; OffscreenCanvasRenderingContext2D includes BaseRenderingContext2D;
diff --git a/third_party/blink/renderer/platform/bindings/dom_data_store.h b/third_party/blink/renderer/platform/bindings/dom_data_store.h index 933c180..e6d0159 100644 --- a/third_party/blink/renderer/platform/bindings/dom_data_store.h +++ b/third_party/blink/renderer/platform/bindings/dom_data_store.h
@@ -70,10 +70,10 @@ return DOMWrapperWorld::Current(isolate).DomDataStore(); } - // Sets the `return_value` from `value`. Can be used from any world. Will only - // consider the current world. + // Sets the `return_value` from `value` in the given `context`. static inline bool SetReturnValue(v8::ReturnValue<v8::Value> return_value, - ScriptWrappable* value); + ScriptWrappable* value, + v8::Local<v8::Context> context); // Sets the `return_value` from `value` in a world that can use inline // storage. @@ -264,12 +264,13 @@ // static bool DOMDataStore::SetReturnValue(v8::ReturnValue<v8::Value> return_value, - ScriptWrappable* value) { + ScriptWrappable* value, + v8::Local<v8::Context> context) { if (CanUseInlineStorageForWrapper()) { return SetReturnValueFromInlineStorage(return_value, value); } - return Current(return_value.GetIsolate()) - .SetReturnValueFrom(return_value, value); + auto& world = DOMWrapperWorld::World(return_value.GetIsolate(), context); + return world.DomDataStore().SetReturnValueFrom(return_value, value); } // static
diff --git a/third_party/blink/renderer/platform/bindings/v8_set_return_value.h b/third_party/blink/renderer/platform/bindings/v8_set_return_value.h index fcb8acf..7b93b21 100644 --- a/third_party/blink/renderer/platform/bindings/v8_set_return_value.h +++ b/third_party/blink/renderer/platform/bindings/v8_set_return_value.h
@@ -455,27 +455,21 @@ V8ReturnValue::SetWrapper(info, wrappable, context); } +// This `current_context` variant is for static operations where there is no +// receiver object. template <FunctionCallbackInfoOrPropertyCallbackInfo CallbackInfo> void V8SetReturnValue(const CallbackInfo& info, const ScriptWrappable* value, - v8::Local<v8::Context> creation_context) { + v8::Local<v8::Context> current_context) { if (!value) [[unlikely]] { return info.GetReturnValue().SetNull(); } ScriptWrappable* wrappable = const_cast<ScriptWrappable*>(value); - if (DOMDataStore::SetReturnValue(info.GetReturnValue(), wrappable)) + if (DOMDataStore::SetReturnValue(info.GetReturnValue(), wrappable, + current_context)) { return; - V8ReturnValue::SetWrapper(info, wrappable, creation_context); -} - -template <FunctionCallbackInfoOrPropertyCallbackInfo CallbackInfo> -void V8SetReturnValue(const CallbackInfo& info, - ScriptWrappable& value, - v8::Local<v8::Context> creation_context) { - ScriptWrappable* wrappable = const_cast<ScriptWrappable*>(&value); - if (DOMDataStore::SetReturnValue(info.GetReturnValue(), wrappable)) - return; - V8ReturnValue::SetWrapper(info, wrappable, creation_context); + } + V8ReturnValue::SetWrapper(info, wrappable, current_context); } // EnumerationBase
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc index 0b54eaa..89881d1 100644 --- a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc +++ b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc
@@ -21,6 +21,7 @@ #include "cc/trees/clip_node.h" #include "cc/trees/effect_node.h" #include "cc/trees/layer_tree_host.h" +#include "cc/trees/layer_tree_impl.h" #include "cc/trees/layer_tree_settings.h" #include "cc/trees/property_tree.h" #include "cc/trees/scroll_node.h" @@ -4100,12 +4101,17 @@ // layer_tree_host_->ActivateCommitState() and the second argument would come // from layer_tree_host_->active_commit_state(); we use pending_commit_state() // just to keep the test code simple. - layer->PushPropertiesTo( - layer->CreateLayerImpl(host_impl.sync_tree()).get(), - *const_cast<const cc::LayerTreeHost&>(GetLayerTreeHost()) - .pending_commit_state(), - const_cast<const cc::LayerTreeHost&>(GetLayerTreeHost()) - .thread_unsafe_commit_state()); + auto layer_impl = layer->CreateLayerImpl(host_impl.sync_tree()); + { + cc::LayerTreeImpl::DiscardableImageMapUpdater updater( + host_impl.sync_tree()); + layer->PushPropertiesTo( + layer_impl.get(), + *const_cast<const cc::LayerTreeHost&>(GetLayerTreeHost()) + .pending_commit_state(), + const_cast<const cc::LayerTreeHost&>(GetLayerTreeHost()) + .thread_unsafe_commit_state()); + } Update(artifact2); ASSERT_EQ(1u, LayerCount()); ASSERT_EQ(layer, LayerAt(0)); @@ -4127,12 +4133,16 @@ Color::kBlack) .Build(); // Simluate commit to the compositor thread. - layer->PushPropertiesTo( - layer->CreateLayerImpl(host_impl.sync_tree()).get(), - *const_cast<const cc::LayerTreeHost&>(GetLayerTreeHost()) - .pending_commit_state(), - const_cast<const cc::LayerTreeHost&>(GetLayerTreeHost()) - .thread_unsafe_commit_state()); + { + cc::LayerTreeImpl::DiscardableImageMapUpdater updater( + host_impl.sync_tree()); + layer->PushPropertiesTo( + layer_impl.get(), + *const_cast<const cc::LayerTreeHost&>(GetLayerTreeHost()) + .pending_commit_state(), + const_cast<const cc::LayerTreeHost&>(GetLayerTreeHost()) + .thread_unsafe_commit_state()); + } Update(artifact3); ASSERT_EQ(1u, LayerCount()); ASSERT_EQ(layer, LayerAt(0));
diff --git a/third_party/blink/renderer/platform/graphics/parkable_image.cc b/third_party/blink/renderer/platform/graphics/parkable_image.cc index 34914a4..be4fea3 100644 --- a/third_party/blink/renderer/platform/graphics/parkable_image.cc +++ b/third_party/blink/renderer/platform/graphics/parkable_image.cc
@@ -194,10 +194,6 @@ parkable_image_->UnlockData(); } -BASE_FEATURE(kUseParkableImageSegmentReader, - "UseParkableImageSegmentReader", - base::FEATURE_ENABLED_BY_DEFAULT); - constexpr base::TimeDelta ParkableImageImpl::kParkingDelay; void ParkableImageImpl::Append(WTF::SharedBuffer* buffer, size_t offset) { @@ -230,20 +226,6 @@ return shared_buffer; } -scoped_refptr<SegmentReader> ParkableImageImpl::GetROBufferSegmentReader() { - base::AutoLock lock(lock_); - Unpark(); - DCHECK(rw_buffer_); - // The locking and unlocking here is only needed to make sure ASAN unpoisons - // things correctly here. - LockData(); - scoped_refptr<ROBuffer> ro_buffer(rw_buffer_->MakeROBufferSnapshot()); - scoped_refptr<SegmentReader> segment_reader = - SegmentReader::CreateFromROBuffer(std::move(ro_buffer)); - UnlockData(); - return segment_reader; -} - bool ParkableImageImpl::CanParkNow() const { DCHECK(!is_on_disk()); return !TransientlyUnableToPark() && !is_locked() && @@ -542,12 +524,7 @@ scoped_refptr<SegmentReader> ParkableImage::MakeROSnapshot() { DCHECK(impl_); DCHECK_CALLED_ON_VALID_THREAD(impl_->thread_checker_); - - if (base::FeatureList::IsEnabled(kUseParkableImageSegmentReader)) { - return CreateSegmentReader(); - } else { - return impl_->GetROBufferSegmentReader(); - } + return CreateSegmentReader(); } void ParkableImage::Freeze() {
diff --git a/third_party/blink/renderer/platform/graphics/parkable_image.h b/third_party/blink/renderer/platform/graphics/parkable_image.h index 3933f54..b97c7b52 100644 --- a/third_party/blink/renderer/platform/graphics/parkable_image.h +++ b/third_party/blink/renderer/platform/graphics/parkable_image.h
@@ -76,9 +76,6 @@ void UnlockData() EXCLUSIVE_LOCKS_REQUIRED(lock_); size_t size() const; - // Returns a ROBufferSegmentReader, wrapping the internal RWBuffer. - scoped_refptr<SegmentReader> GetROBufferSegmentReader() LOCKS_EXCLUDED(lock_); - bool is_frozen() const { return !frozen_time_.is_null(); } bool ShouldReschedule() const LOCKS_EXCLUDED(lock_) {
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 3939838..e05a2a3 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1755,6 +1755,11 @@ }, // Kill switch. { + name: "Fast3DTransformedDescendantStatus", + status: "stable", + }, + // Kill switch. + { name: "FastClearNeedsRepaint", status: "stable", }, @@ -2995,6 +3000,10 @@ status: "experimental", }, { + name: "OffscreenCanvasGetContextAttributes", + status: "experimental", + }, + { name: "OmitBlurEventOnElementRemoval", status: "test" },
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 7b89421..f3e3f336 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -550,11 +550,6 @@ # CSS clip-path: shape() not implemented crbug.com/40829059 [ Win11 ] external/wpt/css/css-masking/animations/clip-path-interpolation-shape.html [ Failure ] crbug.com/384990511 [ Win11-arm64 ] external/wpt/css/css-masking/animations/clip-path-interpolation-shape.html [ Failure ] -crbug.com/40829059 [ Win ] external/wpt/css/css-masking/parsing/clip-path-shape-parsing.html [ Failure ] -crbug.com/40829059 external/wpt/css/css-masking/clip-path/clip-path-shape-002-units.html [ Failure ] -crbug.com/40829059 external/wpt/css/css-masking/clip-path/clip-path-shape-002.html [ Failure ] -crbug.com/40829059 external/wpt/css/css-masking/clip-path/clip-path-shape-003.html [ Failure ] -crbug.com/40829059 external/wpt/css/css-masking/clip-path/clip-path-shape-004.html [ Failure ] crbug.com/40829059 external/wpt/css/css-masking/clip-path/animations/clip-path-shape-interpolation-001.html [ Failure ] crbug.com/40829059 external/wpt/css/css-masking/clip-path/animations/clip-path-shape-interpolation-002.html [ Failure ] crbug.com/40829059 virtual/composite-clip-path-animation/external/wpt/css/css-masking/clip-path/animations/clip-path-shape-interpolation-003.html [ Failure ] @@ -2670,6 +2665,7 @@ crbug.com/383880384 [ Win ] external/wpt/css/css-properties-values-api/registered-property-change-style-002.html [ Failure Pass ] # ====== New tests from wpt-importer added here ====== +[ Mac13 ] virtual/fractional-scroll-offsets/external/wpt/css/css-position/sticky/position-sticky-fractional-offset.html [ Failure ] crbug.com/389545685 [ Mac14 ] external/wpt/css/css-position/sticky/position-sticky-fractional-offset.html [ Failure ] crbug.com/388922812 external/wpt/svg/animations/reftests/discard-check-remove.svg [ Failure ] crbug.com/388922812 external/wpt/svg/animations/reftests/discard-rect-as-child.svg [ Failure ] @@ -3025,14 +3021,6 @@ crbug.com/377977965 [ Linux ] external/wpt/webdriver/tests/bidi/browser/get_client_windows/get_client_windows.py [ Failure ] crbug.com/377576485 [ Mac15 ] external/wpt/webrtc-extensions/RTCRtpParameters-adaptivePtime.html [ Timeout ] crbug.com/384990511 [ Mac ] external/wpt/css/css-shapes/shape-functions/shape-function-valid.tentative.html [ Failure Pass ] -crbug.com/377576478 external/wpt/css/css-masking/clip-path/clip-path-shape-007.tentative.html [ Failure ] -crbug.com/377576478 [ Win11 ] external/wpt/css/css-masking/clip-path/clip-path-shape-008.tentative.html [ Failure ] -crbug.com/377576478 [ Win11-arm64 ] external/wpt/css/css-masking/clip-path/clip-path-shape-008.tentative.html [ Failure Timeout ] -crbug.com/377576478 [ Win10.20h2 ] external/wpt/css/css-masking/clip-path/clip-path-shape-008.tentative.html [ Failure ] -crbug.com/377576478 [ Linux ] external/wpt/css/css-masking/clip-path/clip-path-shape-008.tentative.html [ Failure ] -crbug.com/377576478 [ Mac ] external/wpt/css/css-masking/clip-path/clip-path-shape-008.tentative.html [ Failure ] -crbug.com/377576478 external/wpt/css/css-masking/clip-path/clip-path-shape-009.tentative.html [ Failure ] -crbug.com/377576478 external/wpt/css/css-masking/clip-path/clip-path-shape-010.tentative.html [ Failure ] crbug.com/377100054 [ Win11-arm64 ] external/wpt/css/css-variables/variable-substitution-basic.html [ Failure Timeout ] crbug.com/376770788 [ Mac13 ] external/wpt/webcodecs/per-frame-qp-encoding.https.any.worker.html?av1 [ Timeout ] crbug.com/377072733 [ Win11-arm64 ] external/wpt/webrtc/RTCDataChannel-send-close.html [ Skip Timeout ]
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 488aa3cd..483a0053 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
@@ -127274,6 +127274,19 @@ ] ] }, + "font-face-local-not-family.html": [ + "6b6d5c9a368eb4186a6e792a9f878b9ac92dec1d", + [ + null, + [ + [ + "/css/css-fonts/font-face-local-not-family-ref.html", + "==" + ] + ], + {} + ] + ], "font-face-sign-function.html": [ "28c958c7ee704c1fa35ce838b29d9b766270862c", [ @@ -157986,6 +157999,19 @@ {} ] ], + "clip-path-shape-winding.html": [ + "8949fb70033c90cc22ca8070bb2c21d6b642d28d", + [ + null, + [ + [ + "/css/css-masking/clip-path/reference/clip-path-path-winding-ref.html", + "==" + ] + ], + {} + ] + ], "clip-path-strokeBox-1a.html": [ "487f5363b694304923538d0314d3c6d2a685da6b", [ @@ -291522,6 +291548,32 @@ {} ] ], + "input-date-whitespace-pre-1.html": [ + "6118987617199d91979de5db5d9517d1c195340a", + [ + null, + [ + [ + "/html/rendering/widgets/input-date-whitespace-pre-ref.html", + "==" + ] + ], + {} + ] + ], + "input-date-whitespace-pre-2.html": [ + "f4b6ebaac97440be1827bf67cb01b45c0e058cc7", + [ + null, + [ + [ + "/html/rendering/widgets/input-date-whitespace-pre-ref.html", + "==" + ] + ], + {} + ] + ], "input-number-text-size.tentative.html": [ "0850f0558e3fb97e31b25f4b9aa498e59f08f7cd", [ @@ -310652,7 +310704,7 @@ ], "BlobURL": { "cross-partition-navigation.https-expected.txt": [ - "7a01c003f8b9c0090324d5c36ab87635a10dd219", + "07359521436ed5069dec3a149d4ccb21aa865ca3", [] ], "cross-partition-worker-creation.https-expected.txt": [ @@ -333859,6 +333911,10 @@ [] ] }, + "font-face-local-not-family-ref.html": [ + "e51cb80a440dcc4be4f09155eac8e3254ba21ac0", + [] + ], "font-face-stretch-auto-static-ref.html": [ "5b3c4477332a127234b43993af3a31658c439c72", [] @@ -346333,6 +346389,10 @@ "d9ea5183fb1e6aa745c01f02e702df065d4945e6", [] ], + "clip-path-path-winding-ref.html": [ + "34c189f7b4392e32453ed9df8bcede5d6601f4c6", + [] + ], "clip-path-path-with-zoom-ref.html": [ "76b6e473f06b788830748991a056d5f627d17315", [] @@ -373482,7 +373542,7 @@ [] ], "inserthtml-expected.txt": [ - "349f58dda50d3802a2b7f64ec570f4c649d8d67d", + "a03c41b978fc6c3982255a15ba936002ced27a16", [] ], "insertimage-expected.txt": [ @@ -379283,6 +379343,14 @@ [] ] }, + "server-response-private-aggregation.https.window_1-6-expected.txt": [ + "516ea788517f7017cd9f1abcd1f6bf6a654872eb", + [] + ], + "server-response-private-aggregation.https.window_7-last-expected.txt": [ + "0061db9847001226347888724885df3a4672f8a4", + [] + ], "server-response.https.window_1-6-expected.txt": [ "26a131cb49e43d372262a44180b8299c7713cb8c", [] @@ -392994,6 +393062,10 @@ "18019c56b1bd2535b998c05f301fca3abc8ae1bb", [] ], + "input-date-whitespace-pre-ref.html": [ + "64f0162e2dfdd28d516b0e5bc4094e7cd583346b", + [] + ], "input-no-centering-ref.html": [ "5b2ea91fe5fa635c221adc8801605f3b14fb66c7", [] @@ -418276,10 +418348,6 @@ "17ab3eb534a2de51218cd16da334bbf79b47e8e2", [] ], - "block-string-assignment-to-DOMWindowTimers-setTimeout-setInterval-expected.txt": [ - "d56d73fac28b44da4bb65d84623235aeb895f186", - [] - ], "block-string-assignment-to-Document-write-expected.txt": [ "6ce2110d82390fcf559e572c70e83a74a90b0555", [] @@ -418368,7 +418436,7 @@ [] ], "DOMWindowTimers-setTimeout-setInterval.js": [ - "e03329cdce03fe2f809f8b4274841da4c899f96c", + "2905c232d313088170b1b4292d27e0918eaa255f", [] ], "HTMLScriptElement-internal-slot-support.html": [ @@ -418396,7 +418464,7 @@ [] ], "WorkerGlobalScope-importScripts.https.js": [ - "a3ecfc481923b5e92e0eca287498086b4448458c", + "06548da2248e02d8327e2b70c52d31f69e78e2cf", [] ], "WorkerGlobalScope-importScripts.https.js.headers": [ @@ -418432,7 +418500,7 @@ [] ], "block-string-assignment-to-DOMWindowTimers-setTimeout-setInterval.js": [ - "3ddefd8d8df329f1f783c859a58d6688c96b077c", + "5660deaf1e45fc5d1342baf9054693127c360a64", [] ], "event-handler-attributes.mjs": [ @@ -429821,7 +429889,7 @@ ], "BlobURL": { "cross-partition-navigation.https.html": [ - "ee879b0d95508a6dfd0f03973903c03f4a1dfa2a", + "37cb3dc452d8ec1d4d3395126775a279ef79ab96", [ null, { @@ -504034,6 +504102,13 @@ {} ] ], + "after-change-style-inherited.html": [ + "75570a90a1947496e7171f9f64afd190d2353bb7", + [ + null, + {} + ] + ], "animations": { "animate-with-color-mix.html": [ "3e630a7a2b1e190e3529de8b98ce239ecbda3f89", @@ -507944,7 +508019,7 @@ ] ], "attr-all-types.html": [ - "47378b4cf436ac55fdc7be8d9fe17ff2a75e7c9a", + "85fa172f39abc800faa27584f342e6e0d5c23b68", [ null, {} @@ -507957,6 +508032,13 @@ {} ] ], + "attr-cycle.tentative.html": [ + "1db82c4cad2fc1ca9dc557508a2a5074385cbf1e", + [ + null, + {} + ] + ], "attr-invalidation.html": [ "8937231826fa09701a05826b89e0a778fe8385d2", [ @@ -509406,6 +509488,13 @@ ] }, "css-view-transitions": { + "auto-name-get-animations.html": [ + "0442255542c0349438ef7e951da7c6b47928c858", + [ + null, + {} + ] + ], "duplicate-tag-rejects-capture.html": [ "951294babc2731eb1f86c32bc90c0beab95d70e4", [ @@ -569517,8 +569606,115 @@ } ] ], + "server-response-private-aggregation.https.window.js": [ + "07d02059105695a0d78f93ec136ab99e6971144e", + [ + "fledge/tentative/server-response-private-aggregation.https.window.html?1-6", + { + "script_metadata": [ + [ + "script", + "/resources/testdriver.js" + ], + [ + "script", + "/resources/testdriver-vendor.js" + ], + [ + "script", + "/common/get-host-info.sub.js" + ], + [ + "script", + "/common/utils.js" + ], + [ + "script", + "resources/ba-fledge-util.sub.js" + ], + [ + "script", + "resources/fledge-util.sub.js" + ], + [ + "script", + "third_party/cbor-js/cbor.js" + ], + [ + "script", + "/common/subset-tests.js" + ], + [ + "timeout", + "long" + ], + [ + "variant", + "?1-6" + ], + [ + "variant", + "?7-last" + ] + ], + "timeout": "long" + } + ], + [ + "fledge/tentative/server-response-private-aggregation.https.window.html?7-last", + { + "script_metadata": [ + [ + "script", + "/resources/testdriver.js" + ], + [ + "script", + "/resources/testdriver-vendor.js" + ], + [ + "script", + "/common/get-host-info.sub.js" + ], + [ + "script", + "/common/utils.js" + ], + [ + "script", + "resources/ba-fledge-util.sub.js" + ], + [ + "script", + "resources/fledge-util.sub.js" + ], + [ + "script", + "third_party/cbor-js/cbor.js" + ], + [ + "script", + "/common/subset-tests.js" + ], + [ + "timeout", + "long" + ], + [ + "variant", + "?1-6" + ], + [ + "variant", + "?7-last" + ] + ], + "timeout": "long" + } + ] + ], "server-response.https.window.js": [ - "9806b8d9b5df4c1de6ca83e6b6c03863e764e957", + "1e379452b30b085a92753ed3f3d1ce4bc6def767", [ "fledge/tentative/server-response.https.window.html?1-6", { @@ -625136,7 +625332,7 @@ ] ], "radio-disconnected-group-owner.html": [ - "60feb2b0ba9b14554c39a1f633d7652a2d19bd28", + "8e2c988403d791ac853cbd74b3a98bbfeafab3d7", [ null, {} @@ -707235,7 +707431,7 @@ ] ], "trusted-types-eval-reporting.html": [ - "fbe9425dbef6b2fccbd0c8e7beea35034676da42", + "0f4d406980b24ba977e5ee5917e60137d0bcf701", [ null, {} @@ -725853,7 +726049,7 @@ ] ], "different-contexts.html": [ - "f763d3478784a3e4e7255d67726ec5cfdfad5214", + "0b54c472cf071edd86654b0027fb81bf00fdc02c", [ null, {} @@ -772183,7 +772379,7 @@ ] ], "h265-level-id.https.html": [ - "1a71f3988e78052ef1c9f1f8443123d90e105971", + "fe55dedd5739d1d7692814b5e7d85b434140dbbb", [ null, {}
diff --git a/third_party/blink/web_tests/external/wpt/css/css-fonts/font-face-local-not-family-ref.html b/third_party/blink/web_tests/external/wpt/css/css-fonts/font-face-local-not-family-ref.html new file mode 100644 index 0000000..e51cb80 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-fonts/font-face-local-not-family-ref.html
@@ -0,0 +1,19 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>@font-face src:local() reference</title> + +<style> +@font-face { + /* Load the regular face of Arial, or if not present, harmlessly fall back to Ahem + (but the test will then be pointless). */ + font-family: "LocalArial"; + src: local("Arial"), + local("ArialMT"), + local(Ahem), + url(/fonts/Ahem.ttf); +} +</style> + +<p style="font: 24px LocalArial">These two lines should look the same</p> + +<p style="font: 24px LocalArial">These two lines should look the same</p>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-fonts/font-face-local-not-family.html b/third_party/blink/web_tests/external/wpt/css/css-fonts/font-face-local-not-family.html new file mode 100644 index 0000000..6b6d5c9 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-fonts/font-face-local-not-family.html
@@ -0,0 +1,25 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>@font-face src:local() test</title> +<meta name="assert" content="src:local() loads an individual face, not an entire font family"> +<link rel="help" href="https://drafts.csswg.org/css-fonts-4/#local-font-fallback"> +<link rel="match" href="font-face-local-not-family-ref.html"> + +<style> +@font-face { + /* Load the regular face of Arial, or if not present, harmlessly fall back to Ahem + (but the test will then be pointless). */ + font-family: "LocalArial"; + src: local("Arial"), + local("ArialMT"), + local(Ahem), + url(/fonts/Ahem.ttf); +} +</style> + +<p style="font: 24px LocalArial">These two lines should look the same</p> + +<!-- Because we only defined a single face in the LocalArial family, and disabled any synthesis, + the 'bold' here must have no effect; in particular, it does NOT access any installed + Arial-Bold face. --> +<p style="font: bold 24px LocalArial; font-synthesis: none">These two lines should look the same</p>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-masking/animations/clip-path-interpolation-shape-control-points.tentative-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-masking/animations/clip-path-interpolation-shape-control-points.tentative-expected.txt index 4d3dc659..ce0d856 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-masking/animations/clip-path-interpolation-shape-control-points.tentative-expected.txt +++ b/third_party/blink/web_tests/external/wpt/css/css-masking/animations/clip-path-interpolation-shape-control-points.tentative-expected.txt
@@ -1,616 +1,100 @@ This is a testharness.js-based test. -Found 306 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 48 FAIL, 0 TIMEOUT, 0 NOTRUN. [FAIL] CSS Transitions: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from origin / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , curve to 100 % 50 % with 20px 30px / 40px 50px ) " but got "shape ( from 0 % 0 % , curve to 100 % 50 % with 20px 30px / 40px 150px ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from origin / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.5) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 100px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from origin / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (1) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , curve to 100 % 50 % with 20px 30px / 40px 100px ) " but got "shape ( from 0 % 0 % , curve to 100 % 50 % with 20px 30px / 40px 150px ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from origin / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , curve to 100 % 50 % with 20px 30px / 40px 50px ) " but got "shape ( from 0 % 0 % , curve to 100 % 50 % with 20px 30px / 40px 150px ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from origin / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.5) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 100px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from origin / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (1) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from origin / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , curve to 100 % 50 % with 20px 30px / 40px 100px ) " but got "shape ( from 0 % 0 % , curve to 100 % 50 % with 20px 30px / 40px 150px ) " [FAIL] CSS Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from origin / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.5) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 100px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from origin / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (1) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from origin / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , curve to 100 % 50 % with 20px 30px / 40px 100px ) " but got "shape ( from 0 % 0 % , curve to 100 % 50 % with 20px 30px / 40px 150px ) " [FAIL] Web Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from origin / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.5) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 100px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from origin / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (1) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , curve to 100 % 50 % with 20px 30px / 40px 100px ) " but got "shape ( from 0 % 0 % , curve to 100 % 50 % with 20px 30px / 40px 150px ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 150px from origin)] at (0) should be [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , curve to 100 % 50 % with 20px 30px from start / 40px 50px ) " but got "shape ( from 0 % 0 % , curve to 100 % 50 % with 20px 30px from start / 40px 150px ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 150px from origin)] at (0.5) should be [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 100px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 150px from origin)] at (1) should be [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 150px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , curve to 100 % 50 % with 20px 30px from start / 40px 100px ) " but got "shape ( from 0 % 0 % , curve to 100 % 50 % with 20px 30px from start / 40px 150px ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 150px from origin)] at (0) should be [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , curve to 100 % 50 % with 20px 30px from start / 40px 50px ) " but got "shape ( from 0 % 0 % , curve to 100 % 50 % with 20px 30px from start / 40px 150px ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 150px from origin)] at (0.5) should be [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 100px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 150px from origin)] at (1) should be [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 150px from origin)] at (0) should be [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , curve to 100 % 50 % with 20px 30px from start / 40px 100px ) " but got "shape ( from 0 % 0 % , curve to 100 % 50 % with 20px 30px from start / 40px 150px ) " [FAIL] CSS Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 150px from origin)] at (0.5) should be [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 100px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 150px from origin)] at (1) should be [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 150px from origin)] at (0) should be [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , curve to 100 % 50 % with 20px 30px from start / 40px 100px ) " but got "shape ( from 0 % 0 % , curve to 100 % 50 % with 20px 30px from start / 40px 150px ) " [FAIL] Web Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 150px from origin)] at (0.5) should be [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 100px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 150px from origin)] at (1) should be [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 150px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , curve to 100 % 50 % with 20px 30px from start / 40px 100px ) " but got "shape ( from 0 % 0 % , curve to 100 % 50 % with 20px 30px from start / 40px 150px ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px)] at (0) should be [shape(from top left, curve by 100% 50% with 20px 30px / 40px 50px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px / 40px 50px ) " but got "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px / 40px 150px ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px)] at (0.5) should be [shape(from top left, curve by 100% 50% with 20px 30px / 40px 100px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px)] at (1) should be [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px / 40px 100px ) " but got "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px / 40px 150px ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px)] at (0) should be [shape(from top left, curve by 100% 50% with 20px 30px / 40px 50px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px / 40px 50px ) " but got "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px / 40px 150px ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px)] at (0.5) should be [shape(from top left, curve by 100% 50% with 20px 30px / 40px 100px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px)] at (1) should be [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px)] at (0) should be [shape(from top left, curve by 100% 50% with 20px 30px / 40px 50px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px / 40px 100px ) " but got "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px / 40px 150px ) " [FAIL] CSS Animations: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px)] at (0.5) should be [shape(from top left, curve by 100% 50% with 20px 30px / 40px 100px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px)] at (1) should be [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px)] at (0) should be [shape(from top left, curve by 100% 50% with 20px 30px / 40px 50px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px / 40px 100px ) " but got "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px / 40px 150px ) " [FAIL] Web Animations: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px)] at (0.5) should be [shape(from top left, curve by 100% 50% with 20px 30px / 40px 100px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px)] at (1) should be [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px / 40px 100px ) " but got "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px / 40px 150px ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px / 40px 50px from start)] to [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px)] at (0) should be [shape(from top left, curve by 100% 50% with 20px 30px / 40px 50px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px / 40px 50px ) " but got "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px / 40px 150px ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px / 40px 50px from start)] to [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px)] at (0.5) should be [shape(from top left, curve by 100% 50% with 20px 30px / 40px 100px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px / 40px 50px from start)] to [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px)] at (1) should be [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px / 40px 100px ) " but got "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px / 40px 150px ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px / 40px 50px from start)] to [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px)] at (0) should be [shape(from top left, curve by 100% 50% with 20px 30px / 40px 50px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px / 40px 50px ) " but got "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px / 40px 150px ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px / 40px 50px from start)] to [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px)] at (0.5) should be [shape(from top left, curve by 100% 50% with 20px 30px / 40px 100px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px / 40px 50px from start)] to [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px)] at (1) should be [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px / 40px 50px from start)] to [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px)] at (0) should be [shape(from top left, curve by 100% 50% with 20px 30px / 40px 50px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px / 40px 100px ) " but got "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px / 40px 150px ) " [FAIL] CSS Animations: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px / 40px 50px from start)] to [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px)] at (0.5) should be [shape(from top left, curve by 100% 50% with 20px 30px / 40px 100px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px / 40px 50px from start)] to [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px)] at (1) should be [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px / 40px 50px from start)] to [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px)] at (0) should be [shape(from top left, curve by 100% 50% with 20px 30px / 40px 50px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px / 40px 100px ) " but got "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px / 40px 150px ) " [FAIL] Web Animations: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px / 40px 50px from start)] to [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px)] at (0.5) should be [shape(from top left, curve by 100% 50% with 20px 30px / 40px 100px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px / 40px 50px from start)] to [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px)] at (1) should be [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px / 40px 100px ) " but got "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px / 40px 150px ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px / 40px 50px from origin)] to [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px from origin)] at (0) should be [shape(from top left, curve by 100% 50% with 20px 30px / 40px 50px from origin)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px / 40px 50px from origin ) " but got "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px / 40px 150px from origin ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px / 40px 50px from origin)] to [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px from origin)] at (0.5) should be [shape(from top left, curve by 100% 50% with 20px 30px / 40px 100px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px / 40px 50px from origin)] to [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px from origin)] at (1) should be [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px / 40px 100px from origin ) " but got "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px / 40px 150px from origin ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px / 40px 50px from origin)] to [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px from origin)] at (0) should be [shape(from top left, curve by 100% 50% with 20px 30px / 40px 50px from origin)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px / 40px 50px from origin ) " but got "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px / 40px 150px from origin ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px / 40px 50px from origin)] to [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px from origin)] at (0.5) should be [shape(from top left, curve by 100% 50% with 20px 30px / 40px 100px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px / 40px 50px from origin)] to [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px from origin)] at (1) should be [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px / 40px 50px from origin)] to [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px from origin)] at (0) should be [shape(from top left, curve by 100% 50% with 20px 30px / 40px 50px from origin)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px / 40px 100px from origin ) " but got "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px / 40px 150px from origin ) " [FAIL] CSS Animations: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px / 40px 50px from origin)] to [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px from origin)] at (0.5) should be [shape(from top left, curve by 100% 50% with 20px 30px / 40px 100px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px / 40px 50px from origin)] to [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px from origin)] at (1) should be [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px / 40px 50px from origin)] to [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px from origin)] at (0) should be [shape(from top left, curve by 100% 50% with 20px 30px / 40px 50px from origin)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px / 40px 100px from origin ) " but got "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px / 40px 150px from origin ) " [FAIL] Web Animations: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px / 40px 50px from origin)] to [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px from origin)] at (0.5) should be [shape(from top left, curve by 100% 50% with 20px 30px / 40px 100px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px / 40px 50px from origin)] to [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px from origin)] at (1) should be [shape(from top left, curve by 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px / 40px 100px from origin ) " but got "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px / 40px 150px from origin ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve by 100% 50% with 20px 30px from end / 40px 150px)] at (0) should be [shape(from top left, curve by 100% 50% with 20px 30px from end / 40px 50px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px from end / 40px 50px ) " but got "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px from end / 40px 150px ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve by 100% 50% with 20px 30px from end / 40px 150px)] at (0.5) should be [shape(from top left, curve by 100% 50% with 20px 30px from end / 40px 100px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve by 100% 50% with 20px 30px from end / 40px 150px)] at (1) should be [shape(from top left, curve by 100% 50% with 20px 30px from end / 40px 150px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px from end / 40px 100px ) " but got "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px from end / 40px 150px ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve by 100% 50% with 20px 30px from end / 40px 150px)] at (0) should be [shape(from top left, curve by 100% 50% with 20px 30px from end / 40px 50px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px from end / 40px 50px ) " but got "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px from end / 40px 150px ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve by 100% 50% with 20px 30px from end / 40px 150px)] at (0.5) should be [shape(from top left, curve by 100% 50% with 20px 30px from end / 40px 100px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve by 100% 50% with 20px 30px from end / 40px 150px)] at (1) should be [shape(from top left, curve by 100% 50% with 20px 30px from end / 40px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve by 100% 50% with 20px 30px from end / 40px 150px)] at (0) should be [shape(from top left, curve by 100% 50% with 20px 30px from end / 40px 50px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px from end / 40px 100px ) " but got "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px from end / 40px 150px ) " [FAIL] CSS Animations: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve by 100% 50% with 20px 30px from end / 40px 150px)] at (0.5) should be [shape(from top left, curve by 100% 50% with 20px 30px from end / 40px 100px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve by 100% 50% with 20px 30px from end / 40px 150px)] at (1) should be [shape(from top left, curve by 100% 50% with 20px 30px from end / 40px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve by 100% 50% with 20px 30px from end / 40px 150px)] at (0) should be [shape(from top left, curve by 100% 50% with 20px 30px from end / 40px 50px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px from end / 40px 100px ) " but got "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px from end / 40px 150px ) " [FAIL] Web Animations: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve by 100% 50% with 20px 30px from end / 40px 150px)] at (0.5) should be [shape(from top left, curve by 100% 50% with 20px 30px from end / 40px 100px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, curve by 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve by 100% 50% with 20px 30px from end / 40px 150px)] at (1) should be [shape(from top left, curve by 100% 50% with 20px 30px from end / 40px 150px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px from end / 40px 100px ) " but got "shape ( from 0 % 0 % , curve by 100 % 50 % with 20px 30px from end / 40px 150px ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px)] to [shape(from top left, smooth to 100% 50% with 20px 150px from origin)] at (0) should be [shape(from top left, smooth to 100% 50% with 20px 50px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , smooth to 100 % 50 % with 20px 50px ) " but got "shape ( from 0 % 0 % , smooth to 100 % 50 % with 20px 150px ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px)] to [shape(from top left, smooth to 100% 50% with 20px 150px from origin)] at (0.5) should be [shape(from top left, smooth to 100% 50% with 20px 100px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px)] to [shape(from top left, smooth to 100% 50% with 20px 150px from origin)] at (1) should be [shape(from top left, smooth to 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , smooth to 100 % 50 % with 20px 100px ) " but got "shape ( from 0 % 0 % , smooth to 100 % 50 % with 20px 150px ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px)] to [shape(from top left, smooth to 100% 50% with 20px 150px from origin)] at (0) should be [shape(from top left, smooth to 100% 50% with 20px 50px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , smooth to 100 % 50 % with 20px 50px ) " but got "shape ( from 0 % 0 % , smooth to 100 % 50 % with 20px 150px ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px)] to [shape(from top left, smooth to 100% 50% with 20px 150px from origin)] at (0.5) should be [shape(from top left, smooth to 100% 50% with 20px 100px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px)] to [shape(from top left, smooth to 100% 50% with 20px 150px from origin)] at (1) should be [shape(from top left, smooth to 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px)] to [shape(from top left, smooth to 100% 50% with 20px 150px from origin)] at (0) should be [shape(from top left, smooth to 100% 50% with 20px 50px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , smooth to 100 % 50 % with 20px 100px ) " but got "shape ( from 0 % 0 % , smooth to 100 % 50 % with 20px 150px ) " [FAIL] CSS Animations: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px)] to [shape(from top left, smooth to 100% 50% with 20px 150px from origin)] at (0.5) should be [shape(from top left, smooth to 100% 50% with 20px 100px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px)] to [shape(from top left, smooth to 100% 50% with 20px 150px from origin)] at (1) should be [shape(from top left, smooth to 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px)] to [shape(from top left, smooth to 100% 50% with 20px 150px from origin)] at (0) should be [shape(from top left, smooth to 100% 50% with 20px 50px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , smooth to 100 % 50 % with 20px 100px ) " but got "shape ( from 0 % 0 % , smooth to 100 % 50 % with 20px 150px ) " [FAIL] Web Animations: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px)] to [shape(from top left, smooth to 100% 50% with 20px 150px from origin)] at (0.5) should be [shape(from top left, smooth to 100% 50% with 20px 100px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px)] to [shape(from top left, smooth to 100% 50% with 20px 150px from origin)] at (1) should be [shape(from top left, smooth to 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , smooth to 100 % 50 % with 20px 100px ) " but got "shape ( from 0 % 0 % , smooth to 100 % 50 % with 20px 150px ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px from start)] at (0) should be [shape(from top left, smooth to 100% 50% with 20px 50px from start)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , smooth to 100 % 50 % with 20px 50px from start ) " but got "shape ( from 0 % 0 % , smooth to 100 % 50 % with 20px 150px from start ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px from start)] at (0.5) should be [shape(from top left, smooth to 100% 50% with 20px 100px from start)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px from start)] at (1) should be [shape(from top left, smooth to 100% 50% with 20px 150px from start)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , smooth to 100 % 50 % with 20px 100px from start ) " but got "shape ( from 0 % 0 % , smooth to 100 % 50 % with 20px 150px from start ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px from start)] at (0) should be [shape(from top left, smooth to 100% 50% with 20px 50px from start)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , smooth to 100 % 50 % with 20px 50px from start ) " but got "shape ( from 0 % 0 % , smooth to 100 % 50 % with 20px 150px from start ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px from start)] at (0.5) should be [shape(from top left, smooth to 100% 50% with 20px 100px from start)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px from start)] at (1) should be [shape(from top left, smooth to 100% 50% with 20px 150px from start)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px from start)] at (0) should be [shape(from top left, smooth to 100% 50% with 20px 50px from start)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , smooth to 100 % 50 % with 20px 100px from start ) " but got "shape ( from 0 % 0 % , smooth to 100 % 50 % with 20px 150px from start ) " [FAIL] CSS Animations: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px from start)] at (0.5) should be [shape(from top left, smooth to 100% 50% with 20px 100px from start)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px from start)] at (1) should be [shape(from top left, smooth to 100% 50% with 20px 150px from start)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px from start)] at (0) should be [shape(from top left, smooth to 100% 50% with 20px 50px from start)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , smooth to 100 % 50 % with 20px 100px from start ) " but got "shape ( from 0 % 0 % , smooth to 100 % 50 % with 20px 150px from start ) " [FAIL] Web Animations: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px from start)] at (0.5) should be [shape(from top left, smooth to 100% 50% with 20px 100px from start)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px from start)] at (1) should be [shape(from top left, smooth to 100% 50% with 20px 150px from start)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-behavior:allow-discrete: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (-0.3) should be [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-behavior:allow-discrete: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0) should be [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-behavior:allow-discrete: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.3) should be [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-behavior:allow-discrete: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.5) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-behavior:allow-discrete: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.6) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-behavior:allow-discrete: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (1) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-behavior:allow-discrete: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (1.5) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-property:all and transition-behavor:allow-discrete: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (-0.3) should be [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-property:all and transition-behavor:allow-discrete: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0) should be [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-property:all and transition-behavor:allow-discrete: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.3) should be [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-property:all and transition-behavor:allow-discrete: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.5) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-property:all and transition-behavor:allow-discrete: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.6) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-property:all and transition-behavor:allow-discrete: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (1) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-property:all and transition-behavor:allow-discrete: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (1.5) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (-0.3) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.3) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.5) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.6) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (1) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (1.5) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (-0.3) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.3) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.5) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.6) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (1) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (1.5) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (-0.3) should be [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0) should be [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.3) should be [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.5) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.6) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (1) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (1.5) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (-0.3) should be [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0) should be [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.3) should be [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.5) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.6) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (1) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from start / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (1.5) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-behavior:allow-discrete: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (-0.3) should be [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-behavior:allow-discrete: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0) should be [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-behavior:allow-discrete: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.3) should be [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-behavior:allow-discrete: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.5) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-behavior:allow-discrete: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.6) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-behavior:allow-discrete: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (1) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-behavior:allow-discrete: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (1.5) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-property:all and transition-behavor:allow-discrete: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (-0.3) should be [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-property:all and transition-behavor:allow-discrete: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0) should be [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-property:all and transition-behavor:allow-discrete: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.3) should be [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-property:all and transition-behavor:allow-discrete: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.5) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-property:all and transition-behavor:allow-discrete: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.6) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-property:all and transition-behavor:allow-discrete: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (1) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-property:all and transition-behavor:allow-discrete: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (1.5) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (-0.3) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.3) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.5) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.6) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (1) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (1.5) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (-0.3) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.3) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.5) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.6) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (1) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (1.5) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (-0.3) should be [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0) should be [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.3) should be [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.5) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.6) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (1) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (1.5) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (-0.3) should be [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0) should be [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.3) should be [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.5) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.6) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (1) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px from end / 40px 50px)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (1.5) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-behavior:allow-discrete: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (-0.3) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-behavior:allow-discrete: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-behavior:allow-discrete: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.3) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-behavior:allow-discrete: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.5) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-behavior:allow-discrete: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.6) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-behavior:allow-discrete: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (1) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-behavior:allow-discrete: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (1.5) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-property:all and transition-behavor:allow-discrete: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (-0.3) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-property:all and transition-behavor:allow-discrete: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-property:all and transition-behavor:allow-discrete: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.3) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-property:all and transition-behavor:allow-discrete: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.5) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-property:all and transition-behavor:allow-discrete: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.6) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-property:all and transition-behavor:allow-discrete: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (1) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-property:all and transition-behavor:allow-discrete: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (1.5) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (-0.3) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.3) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.5) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.6) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (1) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (1.5) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (-0.3) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.3) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.5) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.6) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (1) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (1.5) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (-0.3) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.3) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.5) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.6) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (1) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (1.5) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (-0.3) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.3) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.5) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (0.6) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (1) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, curve to 100% 50% with 20px 30px / 40px 50px from end)] to [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] at (1.5) should be [shape(from top left, curve to 100% 50% with 20px 30px / 40px 150px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-behavior:allow-discrete: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px)] at (-0.3) should be [shape(from top left, smooth to 100% 50% with 20px 50px from start)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-behavior:allow-discrete: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px)] at (0) should be [shape(from top left, smooth to 100% 50% with 20px 50px from start)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-behavior:allow-discrete: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px)] at (0.3) should be [shape(from top left, smooth to 100% 50% with 20px 50px from start)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-behavior:allow-discrete: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px)] at (0.5) should be [shape(from top left, smooth to 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-behavior:allow-discrete: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px)] at (0.6) should be [shape(from top left, smooth to 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-behavior:allow-discrete: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px)] at (1) should be [shape(from top left, smooth to 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-behavior:allow-discrete: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px)] at (1.5) should be [shape(from top left, smooth to 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-property:all and transition-behavor:allow-discrete: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px)] at (-0.3) should be [shape(from top left, smooth to 100% 50% with 20px 50px from start)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-property:all and transition-behavor:allow-discrete: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px)] at (0) should be [shape(from top left, smooth to 100% 50% with 20px 50px from start)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-property:all and transition-behavor:allow-discrete: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px)] at (0.3) should be [shape(from top left, smooth to 100% 50% with 20px 50px from start)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-property:all and transition-behavor:allow-discrete: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px)] at (0.5) should be [shape(from top left, smooth to 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-property:all and transition-behavor:allow-discrete: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px)] at (0.6) should be [shape(from top left, smooth to 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-property:all and transition-behavor:allow-discrete: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px)] at (1) should be [shape(from top left, smooth to 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-property:all and transition-behavor:allow-discrete: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px)] at (1.5) should be [shape(from top left, smooth to 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px)] at (-0.3) should be [shape(from top left, smooth to 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px)] at (0) should be [shape(from top left, smooth to 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px)] at (0.3) should be [shape(from top left, smooth to 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px)] at (0.5) should be [shape(from top left, smooth to 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px)] at (0.6) should be [shape(from top left, smooth to 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px)] at (1) should be [shape(from top left, smooth to 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px)] at (1.5) should be [shape(from top left, smooth to 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px)] at (-0.3) should be [shape(from top left, smooth to 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px)] at (0) should be [shape(from top left, smooth to 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px)] at (0.3) should be [shape(from top left, smooth to 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px)] at (0.5) should be [shape(from top left, smooth to 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px)] at (0.6) should be [shape(from top left, smooth to 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px)] at (1) should be [shape(from top left, smooth to 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px)] at (1.5) should be [shape(from top left, smooth to 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px)] at (-0.3) should be [shape(from top left, smooth to 100% 50% with 20px 50px from start)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px)] at (0) should be [shape(from top left, smooth to 100% 50% with 20px 50px from start)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px)] at (0.3) should be [shape(from top left, smooth to 100% 50% with 20px 50px from start)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px)] at (0.5) should be [shape(from top left, smooth to 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px)] at (0.6) should be [shape(from top left, smooth to 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px)] at (1) should be [shape(from top left, smooth to 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px)] at (1.5) should be [shape(from top left, smooth to 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px)] at (-0.3) should be [shape(from top left, smooth to 100% 50% with 20px 50px from start)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px)] at (0) should be [shape(from top left, smooth to 100% 50% with 20px 50px from start)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px)] at (0.3) should be [shape(from top left, smooth to 100% 50% with 20px 50px from start)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px)] at (0.5) should be [shape(from top left, smooth to 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px)] at (0.6) should be [shape(from top left, smooth to 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px)] at (1) should be [shape(from top left, smooth to 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, smooth to 100% 50% with 20px 50px from start)] to [shape(from top left, smooth to 100% 50% with 20px 150px)] at (1.5) should be [shape(from top left, smooth to 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-behavior:allow-discrete: property <clip-path> from [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] to [shape(from top left, smooth by 100% 50% with 20px 150px)] at (-0.3) should be [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-behavior:allow-discrete: property <clip-path> from [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] to [shape(from top left, smooth by 100% 50% with 20px 150px)] at (0) should be [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-behavior:allow-discrete: property <clip-path> from [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] to [shape(from top left, smooth by 100% 50% with 20px 150px)] at (0.3) should be [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-behavior:allow-discrete: property <clip-path> from [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] to [shape(from top left, smooth by 100% 50% with 20px 150px)] at (0.5) should be [shape(from top left, smooth by 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-behavior:allow-discrete: property <clip-path> from [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] to [shape(from top left, smooth by 100% 50% with 20px 150px)] at (0.6) should be [shape(from top left, smooth by 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-behavior:allow-discrete: property <clip-path> from [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] to [shape(from top left, smooth by 100% 50% with 20px 150px)] at (1) should be [shape(from top left, smooth by 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-behavior:allow-discrete: property <clip-path> from [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] to [shape(from top left, smooth by 100% 50% with 20px 150px)] at (1.5) should be [shape(from top left, smooth by 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-property:all and transition-behavor:allow-discrete: property <clip-path> from [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] to [shape(from top left, smooth by 100% 50% with 20px 150px)] at (-0.3) should be [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-property:all and transition-behavor:allow-discrete: property <clip-path> from [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] to [shape(from top left, smooth by 100% 50% with 20px 150px)] at (0) should be [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-property:all and transition-behavor:allow-discrete: property <clip-path> from [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] to [shape(from top left, smooth by 100% 50% with 20px 150px)] at (0.3) should be [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-property:all and transition-behavor:allow-discrete: property <clip-path> from [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] to [shape(from top left, smooth by 100% 50% with 20px 150px)] at (0.5) should be [shape(from top left, smooth by 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-property:all and transition-behavor:allow-discrete: property <clip-path> from [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] to [shape(from top left, smooth by 100% 50% with 20px 150px)] at (0.6) should be [shape(from top left, smooth by 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-property:all and transition-behavor:allow-discrete: property <clip-path> from [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] to [shape(from top left, smooth by 100% 50% with 20px 150px)] at (1) should be [shape(from top left, smooth by 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition-property:all and transition-behavor:allow-discrete: property <clip-path> from [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] to [shape(from top left, smooth by 100% 50% with 20px 150px)] at (1.5) should be [shape(from top left, smooth by 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] to [shape(from top left, smooth by 100% 50% with 20px 150px)] at (-0.3) should be [shape(from top left, smooth by 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] to [shape(from top left, smooth by 100% 50% with 20px 150px)] at (0) should be [shape(from top left, smooth by 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] to [shape(from top left, smooth by 100% 50% with 20px 150px)] at (0.3) should be [shape(from top left, smooth by 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] to [shape(from top left, smooth by 100% 50% with 20px 150px)] at (0.5) should be [shape(from top left, smooth by 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] to [shape(from top left, smooth by 100% 50% with 20px 150px)] at (0.6) should be [shape(from top left, smooth by 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] to [shape(from top left, smooth by 100% 50% with 20px 150px)] at (1) should be [shape(from top left, smooth by 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] to [shape(from top left, smooth by 100% 50% with 20px 150px)] at (1.5) should be [shape(from top left, smooth by 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] to [shape(from top left, smooth by 100% 50% with 20px 150px)] at (-0.3) should be [shape(from top left, smooth by 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] to [shape(from top left, smooth by 100% 50% with 20px 150px)] at (0) should be [shape(from top left, smooth by 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] to [shape(from top left, smooth by 100% 50% with 20px 150px)] at (0.3) should be [shape(from top left, smooth by 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] to [shape(from top left, smooth by 100% 50% with 20px 150px)] at (0.5) should be [shape(from top left, smooth by 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] to [shape(from top left, smooth by 100% 50% with 20px 150px)] at (0.6) should be [shape(from top left, smooth by 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] to [shape(from top left, smooth by 100% 50% with 20px 150px)] at (1) should be [shape(from top left, smooth by 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] to [shape(from top left, smooth by 100% 50% with 20px 150px)] at (1.5) should be [shape(from top left, smooth by 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] to [shape(from top left, smooth by 100% 50% with 20px 150px)] at (-0.3) should be [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] to [shape(from top left, smooth by 100% 50% with 20px 150px)] at (0) should be [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] to [shape(from top left, smooth by 100% 50% with 20px 150px)] at (0.3) should be [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] to [shape(from top left, smooth by 100% 50% with 20px 150px)] at (0.5) should be [shape(from top left, smooth by 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] to [shape(from top left, smooth by 100% 50% with 20px 150px)] at (0.6) should be [shape(from top left, smooth by 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] to [shape(from top left, smooth by 100% 50% with 20px 150px)] at (1) should be [shape(from top left, smooth by 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] to [shape(from top left, smooth by 100% 50% with 20px 150px)] at (1.5) should be [shape(from top left, smooth by 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] to [shape(from top left, smooth by 100% 50% with 20px 150px)] at (-0.3) should be [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] to [shape(from top left, smooth by 100% 50% with 20px 150px)] at (0) should be [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] to [shape(from top left, smooth by 100% 50% with 20px 150px)] at (0.3) should be [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] to [shape(from top left, smooth by 100% 50% with 20px 150px)] at (0.5) should be [shape(from top left, smooth by 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] to [shape(from top left, smooth by 100% 50% with 20px 150px)] at (0.6) should be [shape(from top left, smooth by 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] to [shape(from top left, smooth by 100% 50% with 20px 150px)] at (1) should be [shape(from top left, smooth by 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from top left, smooth by 100% 50% with 20px 50px from origin)] to [shape(from top left, smooth by 100% 50% with 20px 150px)] at (1.5) should be [shape(from top left, smooth by 100% 50% with 20px 150px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 0 % 0 % , smooth to 100 % 50 % with 20px 100px from start ) " but got "shape ( from 0 % 0 % , smooth to 100 % 50 % with 20px 150px from start ) " Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/css/css-masking/animations/clip-path-interpolation-shape-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-masking/animations/clip-path-interpolation-shape-expected.txt index 0fccd134..4fb9216 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-masking/animations/clip-path-interpolation-shape-expected.txt +++ b/third_party/blink/web_tests/external/wpt/css/css-masking/animations/clip-path-interpolation-shape-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 302 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 266 FAIL, 0 TIMEOUT, 0 NOTRUN. [FAIL] CSS Transitions: property <clip-path> from neutral to [shape(from -5px 5px, line to 20px 20%)] at (-0.3) should be [shape(from 8px 5px, line to 7px 7%)] assert_equals: expected "shape ( from 8px 5px , line to 7px 7 % ) " but got "shape ( from - 5px 5px , line to 20px 20 % ) " [FAIL] CSS Transitions: property <clip-path> from neutral to [shape(from -5px 5px, line to 20px 20%)] at (0) should be [shape(from 5px 5px, line to 10px 10%)] @@ -89,201 +89,153 @@ [FAIL] Web Animations: property <clip-path> from [shape(from 5% 5px, hline to 5%, vline to -5px, close)] to [shape(from 15% 15px, hline to 25%, vline to -15px, close)] at (1.5) should be [shape(from 20% 20px, hline to 35%, vline to -20px, close)] assert_equals: expected "shape ( from 20 % 20px , hline to 35 % , vline to - 20px , close ) " but got "shape ( from 15 % 15px , hline to 25 % , vline to - 15px , close ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] to [shape(from 15% 15px, curve to 20% 0px with 10% 60px, curve to 20% 30px with 30% 40px / -5% 100px)] at (-0.3) should be [shape(from 2% 2px, curve to 7% 13px with -3% 86px, curve to 33% 17px with 17% 53px / 34% 61px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 2 % 2px , curve to 7 % 13px with - 3 % 86px , curve to 33 % 17px with 17 % 53px / 34 % 61px ) " but got "shape ( from 15 % 15px , curve to 20 % 0px with 10 % 60px , curve to 20 % 30px with 30 % 40px / - 5 % 100px ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] to [shape(from 15% 15px, curve to 20% 0px with 10% 60px, curve to 20% 30px with 30% 40px / -5% 100px)] at (0) should be [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 5 % 5px , curve to 10 % 10px with 0 % 80px , curve to 30 % 20px with 20 % 50px / 25 % 70px ) " but got "shape ( from 15 % 15px , curve to 20 % 0px with 10 % 60px , curve to 20 % 30px with 30 % 40px / - 5 % 100px ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] to [shape(from 15% 15px, curve to 20% 0px with 10% 60px, curve to 20% 30px with 30% 40px / -5% 100px)] at (0.5) should be [shape(from 10% 10px, curve to 15% 5px with 5% 70px, curve to 25% 25px with 25% 45px / 10% 85px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] to [shape(from 15% 15px, curve to 20% 0px with 10% 60px, curve to 20% 30px with 30% 40px / -5% 100px)] at (1) should be [shape(from 15% 15px, curve to 20% 0px with 10% 60px, curve to 20% 30px with 30% 40px / -5% 100px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 10 % 10px , curve to 15 % 5px with 5 % 70px , curve to 25 % 25px with 25 % 45px / 10 % 85px ) " but got "shape ( from 15 % 15px , curve to 20 % 0px with 10 % 60px , curve to 20 % 30px with 30 % 40px / - 5 % 100px ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] to [shape(from 15% 15px, curve to 20% 0px with 10% 60px, curve to 20% 30px with 30% 40px / -5% 100px)] at (1.5) should be [shape(from 20% 20px, curve to 25% -5px with 15% 50px, curve to 15% 35px with 35% 35px / -20% 115px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 20 % 20px , curve to 25 % - 5px with 15 % 50px , curve to 15 % 35px with 35 % 35px / - 20 % 115px ) " but got "shape ( from 15 % 15px , curve to 20 % 0px with 10 % 60px , curve to 20 % 30px with 30 % 40px / - 5 % 100px ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] to [shape(from 15% 15px, curve to 20% 0px with 10% 60px, curve to 20% 30px with 30% 40px / -5% 100px)] at (-0.3) should be [shape(from 2% 2px, curve to 7% 13px with -3% 86px, curve to 33% 17px with 17% 53px / 34% 61px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 2 % 2px , curve to 7 % 13px with - 3 % 86px , curve to 33 % 17px with 17 % 53px / 34 % 61px ) " but got "shape ( from 15 % 15px , curve to 20 % 0px with 10 % 60px , curve to 20 % 30px with 30 % 40px / - 5 % 100px ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] to [shape(from 15% 15px, curve to 20% 0px with 10% 60px, curve to 20% 30px with 30% 40px / -5% 100px)] at (0) should be [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 5 % 5px , curve to 10 % 10px with 0 % 80px , curve to 30 % 20px with 20 % 50px / 25 % 70px ) " but got "shape ( from 15 % 15px , curve to 20 % 0px with 10 % 60px , curve to 20 % 30px with 30 % 40px / - 5 % 100px ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] to [shape(from 15% 15px, curve to 20% 0px with 10% 60px, curve to 20% 30px with 30% 40px / -5% 100px)] at (0.5) should be [shape(from 10% 10px, curve to 15% 5px with 5% 70px, curve to 25% 25px with 25% 45px / 10% 85px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] to [shape(from 15% 15px, curve to 20% 0px with 10% 60px, curve to 20% 30px with 30% 40px / -5% 100px)] at (1) should be [shape(from 15% 15px, curve to 20% 0px with 10% 60px, curve to 20% 30px with 30% 40px / -5% 100px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 10 % 10px , curve to 15 % 5px with 5 % 70px , curve to 25 % 25px with 25 % 45px / 10 % 85px ) " but got "shape ( from 15 % 15px , curve to 20 % 0px with 10 % 60px , curve to 20 % 30px with 30 % 40px / - 5 % 100px ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] to [shape(from 15% 15px, curve to 20% 0px with 10% 60px, curve to 20% 30px with 30% 40px / -5% 100px)] at (1.5) should be [shape(from 20% 20px, curve to 25% -5px with 15% 50px, curve to 15% 35px with 35% 35px / -20% 115px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 20 % 20px , curve to 25 % - 5px with 15 % 50px , curve to 15 % 35px with 35 % 35px / - 20 % 115px ) " but got "shape ( from 15 % 15px , curve to 20 % 0px with 10 % 60px , curve to 20 % 30px with 30 % 40px / - 5 % 100px ) " [FAIL] CSS Animations: property <clip-path> from [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] to [shape(from 15% 15px, curve to 20% 0px with 10% 60px, curve to 20% 30px with 30% 40px / -5% 100px)] at (-0.3) should be [shape(from 2% 2px, curve to 7% 13px with -3% 86px, curve to 33% 17px with 17% 53px / 34% 61px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] to [shape(from 15% 15px, curve to 20% 0px with 10% 60px, curve to 20% 30px with 30% 40px / -5% 100px)] at (0) should be [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 2 % 2px , curve to 7 % 13px with - 3 % 86px , curve to 33 % 17px with 17 % 53px / 34 % 61px ) " but got "shape ( from 5 % 5px , curve to 10 % 10px with 0 % 80px , curve to 30 % 20px with 20 % 50px / 25 % 70px ) " [FAIL] CSS Animations: property <clip-path> from [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] to [shape(from 15% 15px, curve to 20% 0px with 10% 60px, curve to 20% 30px with 30% 40px / -5% 100px)] at (0.5) should be [shape(from 10% 10px, curve to 15% 5px with 5% 70px, curve to 25% 25px with 25% 45px / 10% 85px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] to [shape(from 15% 15px, curve to 20% 0px with 10% 60px, curve to 20% 30px with 30% 40px / -5% 100px)] at (1) should be [shape(from 15% 15px, curve to 20% 0px with 10% 60px, curve to 20% 30px with 30% 40px / -5% 100px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 10 % 10px , curve to 15 % 5px with 5 % 70px , curve to 25 % 25px with 25 % 45px / 10 % 85px ) " but got "shape ( from 15 % 15px , curve to 20 % 0px with 10 % 60px , curve to 20 % 30px with 30 % 40px / - 5 % 100px ) " [FAIL] CSS Animations: property <clip-path> from [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] to [shape(from 15% 15px, curve to 20% 0px with 10% 60px, curve to 20% 30px with 30% 40px / -5% 100px)] at (1.5) should be [shape(from 20% 20px, curve to 25% -5px with 15% 50px, curve to 15% 35px with 35% 35px / -20% 115px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 20 % 20px , curve to 25 % - 5px with 15 % 50px , curve to 15 % 35px with 35 % 35px / - 20 % 115px ) " but got "shape ( from 15 % 15px , curve to 20 % 0px with 10 % 60px , curve to 20 % 30px with 30 % 40px / - 5 % 100px ) " [FAIL] Web Animations: property <clip-path> from [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] to [shape(from 15% 15px, curve to 20% 0px with 10% 60px, curve to 20% 30px with 30% 40px / -5% 100px)] at (-0.3) should be [shape(from 2% 2px, curve to 7% 13px with -3% 86px, curve to 33% 17px with 17% 53px / 34% 61px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] to [shape(from 15% 15px, curve to 20% 0px with 10% 60px, curve to 20% 30px with 30% 40px / -5% 100px)] at (0) should be [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 2 % 2px , curve to 7 % 13px with - 3 % 86px , curve to 33 % 17px with 17 % 53px / 34 % 61px ) " but got "shape ( from 5 % 5px , curve to 10 % 10px with 0 % 80px , curve to 30 % 20px with 20 % 50px / 25 % 70px ) " [FAIL] Web Animations: property <clip-path> from [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] to [shape(from 15% 15px, curve to 20% 0px with 10% 60px, curve to 20% 30px with 30% 40px / -5% 100px)] at (0.5) should be [shape(from 10% 10px, curve to 15% 5px with 5% 70px, curve to 25% 25px with 25% 45px / 10% 85px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] to [shape(from 15% 15px, curve to 20% 0px with 10% 60px, curve to 20% 30px with 30% 40px / -5% 100px)] at (1) should be [shape(from 15% 15px, curve to 20% 0px with 10% 60px, curve to 20% 30px with 30% 40px / -5% 100px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 10 % 10px , curve to 15 % 5px with 5 % 70px , curve to 25 % 25px with 25 % 45px / 10 % 85px ) " but got "shape ( from 15 % 15px , curve to 20 % 0px with 10 % 60px , curve to 20 % 30px with 30 % 40px / - 5 % 100px ) " [FAIL] Web Animations: property <clip-path> from [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] to [shape(from 15% 15px, curve to 20% 0px with 10% 60px, curve to 20% 30px with 30% 40px / -5% 100px)] at (1.5) should be [shape(from 20% 20px, curve to 25% -5px with 15% 50px, curve to 15% 35px with 35% 35px / -20% 115px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 20 % 20px , curve to 25 % - 5px with 15 % 50px , curve to 15 % 35px with 35 % 35px / - 20 % 115px ) " but got "shape ( from 15 % 15px , curve to 20 % 0px with 10 % 60px , curve to 20 % 30px with 30 % 40px / - 5 % 100px ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from 5% 5px, curve by 10% 10px with 0% 80px, curve by 30% 20px with 20% 50px / 25% 70px)] to [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] at (-0.3) should be [shape(from 2% 2px, curve by 7% 13px with -3% 86px, curve by 33% 17px with 17% 53px / 34% 61px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 2 % 2px , curve by 7 % 13px with - 3 % 86px , curve by 33 % 17px with 17 % 53px / 34 % 61px ) " but got "shape ( from 15 % 15px , curve by 20 % 0px with 10 % 60px , curve by 20 % 30px with 30 % 40px / - 5 % 100px ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from 5% 5px, curve by 10% 10px with 0% 80px, curve by 30% 20px with 20% 50px / 25% 70px)] to [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] at (0) should be [shape(from 5% 5px, curve by 10% 10px with 0% 80px, curve by 30% 20px with 20% 50px / 25% 70px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 5 % 5px , curve by 10 % 10px with 0 % 80px , curve by 30 % 20px with 20 % 50px / 25 % 70px ) " but got "shape ( from 15 % 15px , curve by 20 % 0px with 10 % 60px , curve by 20 % 30px with 30 % 40px / - 5 % 100px ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from 5% 5px, curve by 10% 10px with 0% 80px, curve by 30% 20px with 20% 50px / 25% 70px)] to [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] at (0.5) should be [shape(from 10% 10px, curve by 15% 5px with 5% 70px, curve by 25% 25px with 25% 45px / 10% 85px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from 5% 5px, curve by 10% 10px with 0% 80px, curve by 30% 20px with 20% 50px / 25% 70px)] to [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] at (1) should be [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 10 % 10px , curve by 15 % 5px with 5 % 70px , curve by 25 % 25px with 25 % 45px / 10 % 85px ) " but got "shape ( from 15 % 15px , curve by 20 % 0px with 10 % 60px , curve by 20 % 30px with 30 % 40px / - 5 % 100px ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from 5% 5px, curve by 10% 10px with 0% 80px, curve by 30% 20px with 20% 50px / 25% 70px)] to [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] at (1.5) should be [shape(from 20% 20px, curve by 25% -5px with 15% 50px, curve by 15% 35px with 35% 35px / -20% 115px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 20 % 20px , curve by 25 % - 5px with 15 % 50px , curve by 15 % 35px with 35 % 35px / - 20 % 115px ) " but got "shape ( from 15 % 15px , curve by 20 % 0px with 10 % 60px , curve by 20 % 30px with 30 % 40px / - 5 % 100px ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from 5% 5px, curve by 10% 10px with 0% 80px, curve by 30% 20px with 20% 50px / 25% 70px)] to [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] at (-0.3) should be [shape(from 2% 2px, curve by 7% 13px with -3% 86px, curve by 33% 17px with 17% 53px / 34% 61px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 2 % 2px , curve by 7 % 13px with - 3 % 86px , curve by 33 % 17px with 17 % 53px / 34 % 61px ) " but got "shape ( from 15 % 15px , curve by 20 % 0px with 10 % 60px , curve by 20 % 30px with 30 % 40px / - 5 % 100px ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from 5% 5px, curve by 10% 10px with 0% 80px, curve by 30% 20px with 20% 50px / 25% 70px)] to [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] at (0) should be [shape(from 5% 5px, curve by 10% 10px with 0% 80px, curve by 30% 20px with 20% 50px / 25% 70px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 5 % 5px , curve by 10 % 10px with 0 % 80px , curve by 30 % 20px with 20 % 50px / 25 % 70px ) " but got "shape ( from 15 % 15px , curve by 20 % 0px with 10 % 60px , curve by 20 % 30px with 30 % 40px / - 5 % 100px ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from 5% 5px, curve by 10% 10px with 0% 80px, curve by 30% 20px with 20% 50px / 25% 70px)] to [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] at (0.5) should be [shape(from 10% 10px, curve by 15% 5px with 5% 70px, curve by 25% 25px with 25% 45px / 10% 85px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from 5% 5px, curve by 10% 10px with 0% 80px, curve by 30% 20px with 20% 50px / 25% 70px)] to [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] at (1) should be [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 10 % 10px , curve by 15 % 5px with 5 % 70px , curve by 25 % 25px with 25 % 45px / 10 % 85px ) " but got "shape ( from 15 % 15px , curve by 20 % 0px with 10 % 60px , curve by 20 % 30px with 30 % 40px / - 5 % 100px ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from 5% 5px, curve by 10% 10px with 0% 80px, curve by 30% 20px with 20% 50px / 25% 70px)] to [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] at (1.5) should be [shape(from 20% 20px, curve by 25% -5px with 15% 50px, curve by 15% 35px with 35% 35px / -20% 115px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 20 % 20px , curve by 25 % - 5px with 15 % 50px , curve by 15 % 35px with 35 % 35px / - 20 % 115px ) " but got "shape ( from 15 % 15px , curve by 20 % 0px with 10 % 60px , curve by 20 % 30px with 30 % 40px / - 5 % 100px ) " [FAIL] CSS Animations: property <clip-path> from [shape(from 5% 5px, curve by 10% 10px with 0% 80px, curve by 30% 20px with 20% 50px / 25% 70px)] to [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] at (-0.3) should be [shape(from 2% 2px, curve by 7% 13px with -3% 86px, curve by 33% 17px with 17% 53px / 34% 61px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from 5% 5px, curve by 10% 10px with 0% 80px, curve by 30% 20px with 20% 50px / 25% 70px)] to [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] at (0) should be [shape(from 5% 5px, curve by 10% 10px with 0% 80px, curve by 30% 20px with 20% 50px / 25% 70px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 2 % 2px , curve by 7 % 13px with - 3 % 86px , curve by 33 % 17px with 17 % 53px / 34 % 61px ) " but got "shape ( from 5 % 5px , curve by 10 % 10px with 0 % 80px , curve by 30 % 20px with 20 % 50px / 25 % 70px ) " [FAIL] CSS Animations: property <clip-path> from [shape(from 5% 5px, curve by 10% 10px with 0% 80px, curve by 30% 20px with 20% 50px / 25% 70px)] to [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] at (0.5) should be [shape(from 10% 10px, curve by 15% 5px with 5% 70px, curve by 25% 25px with 25% 45px / 10% 85px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from 5% 5px, curve by 10% 10px with 0% 80px, curve by 30% 20px with 20% 50px / 25% 70px)] to [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] at (1) should be [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 10 % 10px , curve by 15 % 5px with 5 % 70px , curve by 25 % 25px with 25 % 45px / 10 % 85px ) " but got "shape ( from 15 % 15px , curve by 20 % 0px with 10 % 60px , curve by 20 % 30px with 30 % 40px / - 5 % 100px ) " [FAIL] CSS Animations: property <clip-path> from [shape(from 5% 5px, curve by 10% 10px with 0% 80px, curve by 30% 20px with 20% 50px / 25% 70px)] to [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] at (1.5) should be [shape(from 20% 20px, curve by 25% -5px with 15% 50px, curve by 15% 35px with 35% 35px / -20% 115px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 20 % 20px , curve by 25 % - 5px with 15 % 50px , curve by 15 % 35px with 35 % 35px / - 20 % 115px ) " but got "shape ( from 15 % 15px , curve by 20 % 0px with 10 % 60px , curve by 20 % 30px with 30 % 40px / - 5 % 100px ) " [FAIL] Web Animations: property <clip-path> from [shape(from 5% 5px, curve by 10% 10px with 0% 80px, curve by 30% 20px with 20% 50px / 25% 70px)] to [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] at (-0.3) should be [shape(from 2% 2px, curve by 7% 13px with -3% 86px, curve by 33% 17px with 17% 53px / 34% 61px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from 5% 5px, curve by 10% 10px with 0% 80px, curve by 30% 20px with 20% 50px / 25% 70px)] to [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] at (0) should be [shape(from 5% 5px, curve by 10% 10px with 0% 80px, curve by 30% 20px with 20% 50px / 25% 70px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 2 % 2px , curve by 7 % 13px with - 3 % 86px , curve by 33 % 17px with 17 % 53px / 34 % 61px ) " but got "shape ( from 5 % 5px , curve by 10 % 10px with 0 % 80px , curve by 30 % 20px with 20 % 50px / 25 % 70px ) " [FAIL] Web Animations: property <clip-path> from [shape(from 5% 5px, curve by 10% 10px with 0% 80px, curve by 30% 20px with 20% 50px / 25% 70px)] to [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] at (0.5) should be [shape(from 10% 10px, curve by 15% 5px with 5% 70px, curve by 25% 25px with 25% 45px / 10% 85px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from 5% 5px, curve by 10% 10px with 0% 80px, curve by 30% 20px with 20% 50px / 25% 70px)] to [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] at (1) should be [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 10 % 10px , curve by 15 % 5px with 5 % 70px , curve by 25 % 25px with 25 % 45px / 10 % 85px ) " but got "shape ( from 15 % 15px , curve by 20 % 0px with 10 % 60px , curve by 20 % 30px with 30 % 40px / - 5 % 100px ) " [FAIL] Web Animations: property <clip-path> from [shape(from 5% 5px, curve by 10% 10px with 0% 80px, curve by 30% 20px with 20% 50px / 25% 70px)] to [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] at (1.5) should be [shape(from 20% 20px, curve by 25% -5px with 15% 50px, curve by 15% 35px with 35% 35px / -20% 115px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 20 % 20px , curve by 25 % - 5px with 15 % 50px , curve by 15 % 35px with 35 % 35px / - 20 % 115px ) " but got "shape ( from 15 % 15px , curve by 20 % 0px with 10 % 60px , curve by 20 % 30px with 30 % 40px / - 5 % 100px ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] to [shape(from 15% 15px, smooth to 20% 0px with 10% 60px, smooth to 20% 30px)] at (-0.3) should be [shape(from 2% 2px, smooth to 7% 13px with -3% 86px, smooth to 33% 17px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 2 % 2px , smooth to 7 % 13px with - 3 % 86px , smooth to 33 % 17px ) " but got "shape ( from 15 % 15px , smooth to 20 % 0px with 10 % 60px , smooth to 20 % 30px ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] to [shape(from 15% 15px, smooth to 20% 0px with 10% 60px, smooth to 20% 30px)] at (0) should be [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 5 % 5px , smooth to 10 % 10px with 0 % 80px , smooth to 30 % 20px ) " but got "shape ( from 15 % 15px , smooth to 20 % 0px with 10 % 60px , smooth to 20 % 30px ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] to [shape(from 15% 15px, smooth to 20% 0px with 10% 60px, smooth to 20% 30px)] at (0.5) should be [shape(from 10% 10px, smooth to 15% 5px with 5% 70px, smooth to 25% 25px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] to [shape(from 15% 15px, smooth to 20% 0px with 10% 60px, smooth to 20% 30px)] at (1) should be [shape(from 15% 15px, smooth to 20% 0px with 10% 60px, smooth to 20% 30px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 10 % 10px , smooth to 15 % 5px with 5 % 70px , smooth to 25 % 25px ) " but got "shape ( from 15 % 15px , smooth to 20 % 0px with 10 % 60px , smooth to 20 % 30px ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] to [shape(from 15% 15px, smooth to 20% 0px with 10% 60px, smooth to 20% 30px)] at (1.5) should be [shape(from 20% 20px, smooth to 25% -5px with 15% 50px, smooth to 15% 35px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 20 % 20px , smooth to 25 % - 5px with 15 % 50px , smooth to 15 % 35px ) " but got "shape ( from 15 % 15px , smooth to 20 % 0px with 10 % 60px , smooth to 20 % 30px ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] to [shape(from 15% 15px, smooth to 20% 0px with 10% 60px, smooth to 20% 30px)] at (-0.3) should be [shape(from 2% 2px, smooth to 7% 13px with -3% 86px, smooth to 33% 17px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 2 % 2px , smooth to 7 % 13px with - 3 % 86px , smooth to 33 % 17px ) " but got "shape ( from 15 % 15px , smooth to 20 % 0px with 10 % 60px , smooth to 20 % 30px ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] to [shape(from 15% 15px, smooth to 20% 0px with 10% 60px, smooth to 20% 30px)] at (0) should be [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 5 % 5px , smooth to 10 % 10px with 0 % 80px , smooth to 30 % 20px ) " but got "shape ( from 15 % 15px , smooth to 20 % 0px with 10 % 60px , smooth to 20 % 30px ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] to [shape(from 15% 15px, smooth to 20% 0px with 10% 60px, smooth to 20% 30px)] at (0.5) should be [shape(from 10% 10px, smooth to 15% 5px with 5% 70px, smooth to 25% 25px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] to [shape(from 15% 15px, smooth to 20% 0px with 10% 60px, smooth to 20% 30px)] at (1) should be [shape(from 15% 15px, smooth to 20% 0px with 10% 60px, smooth to 20% 30px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 10 % 10px , smooth to 15 % 5px with 5 % 70px , smooth to 25 % 25px ) " but got "shape ( from 15 % 15px , smooth to 20 % 0px with 10 % 60px , smooth to 20 % 30px ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] to [shape(from 15% 15px, smooth to 20% 0px with 10% 60px, smooth to 20% 30px)] at (1.5) should be [shape(from 20% 20px, smooth to 25% -5px with 15% 50px, smooth to 15% 35px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 20 % 20px , smooth to 25 % - 5px with 15 % 50px , smooth to 15 % 35px ) " but got "shape ( from 15 % 15px , smooth to 20 % 0px with 10 % 60px , smooth to 20 % 30px ) " [FAIL] CSS Animations: property <clip-path> from [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] to [shape(from 15% 15px, smooth to 20% 0px with 10% 60px, smooth to 20% 30px)] at (-0.3) should be [shape(from 2% 2px, smooth to 7% 13px with -3% 86px, smooth to 33% 17px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] to [shape(from 15% 15px, smooth to 20% 0px with 10% 60px, smooth to 20% 30px)] at (0) should be [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 2 % 2px , smooth to 7 % 13px with - 3 % 86px , smooth to 33 % 17px ) " but got "shape ( from 5 % 5px , smooth to 10 % 10px with 0 % 80px , smooth to 30 % 20px ) " [FAIL] CSS Animations: property <clip-path> from [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] to [shape(from 15% 15px, smooth to 20% 0px with 10% 60px, smooth to 20% 30px)] at (0.5) should be [shape(from 10% 10px, smooth to 15% 5px with 5% 70px, smooth to 25% 25px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] to [shape(from 15% 15px, smooth to 20% 0px with 10% 60px, smooth to 20% 30px)] at (1) should be [shape(from 15% 15px, smooth to 20% 0px with 10% 60px, smooth to 20% 30px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 10 % 10px , smooth to 15 % 5px with 5 % 70px , smooth to 25 % 25px ) " but got "shape ( from 15 % 15px , smooth to 20 % 0px with 10 % 60px , smooth to 20 % 30px ) " [FAIL] CSS Animations: property <clip-path> from [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] to [shape(from 15% 15px, smooth to 20% 0px with 10% 60px, smooth to 20% 30px)] at (1.5) should be [shape(from 20% 20px, smooth to 25% -5px with 15% 50px, smooth to 15% 35px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 20 % 20px , smooth to 25 % - 5px with 15 % 50px , smooth to 15 % 35px ) " but got "shape ( from 15 % 15px , smooth to 20 % 0px with 10 % 60px , smooth to 20 % 30px ) " [FAIL] Web Animations: property <clip-path> from [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] to [shape(from 15% 15px, smooth to 20% 0px with 10% 60px, smooth to 20% 30px)] at (-0.3) should be [shape(from 2% 2px, smooth to 7% 13px with -3% 86px, smooth to 33% 17px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] to [shape(from 15% 15px, smooth to 20% 0px with 10% 60px, smooth to 20% 30px)] at (0) should be [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 2 % 2px , smooth to 7 % 13px with - 3 % 86px , smooth to 33 % 17px ) " but got "shape ( from 5 % 5px , smooth to 10 % 10px with 0 % 80px , smooth to 30 % 20px ) " [FAIL] Web Animations: property <clip-path> from [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] to [shape(from 15% 15px, smooth to 20% 0px with 10% 60px, smooth to 20% 30px)] at (0.5) should be [shape(from 10% 10px, smooth to 15% 5px with 5% 70px, smooth to 25% 25px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] to [shape(from 15% 15px, smooth to 20% 0px with 10% 60px, smooth to 20% 30px)] at (1) should be [shape(from 15% 15px, smooth to 20% 0px with 10% 60px, smooth to 20% 30px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 10 % 10px , smooth to 15 % 5px with 5 % 70px , smooth to 25 % 25px ) " but got "shape ( from 15 % 15px , smooth to 20 % 0px with 10 % 60px , smooth to 20 % 30px ) " [FAIL] Web Animations: property <clip-path> from [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] to [shape(from 15% 15px, smooth to 20% 0px with 10% 60px, smooth to 20% 30px)] at (1.5) should be [shape(from 20% 20px, smooth to 25% -5px with 15% 50px, smooth to 15% 35px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 20 % 20px , smooth to 25 % - 5px with 15 % 50px , smooth to 15 % 35px ) " but got "shape ( from 15 % 15px , smooth to 20 % 0px with 10 % 60px , smooth to 20 % 30px ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from 5% 5px, smooth by 10% 10px with 0% 80px, smooth by 30% 20px)] to [shape(from 15% 15px, smooth by 20% 0px with 10% 60px, smooth by 20% 30px)] at (-0.3) should be [shape(from 2% 2px, smooth by 7% 13px with -3% 86px, smooth by 33% 17px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 2 % 2px , smooth by 7 % 13px with - 3 % 86px , smooth by 33 % 17px ) " but got "shape ( from 15 % 15px , smooth by 20 % 0px with 10 % 60px , smooth by 20 % 30px ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from 5% 5px, smooth by 10% 10px with 0% 80px, smooth by 30% 20px)] to [shape(from 15% 15px, smooth by 20% 0px with 10% 60px, smooth by 20% 30px)] at (0) should be [shape(from 5% 5px, smooth by 10% 10px with 0% 80px, smooth by 30% 20px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 5 % 5px , smooth by 10 % 10px with 0 % 80px , smooth by 30 % 20px ) " but got "shape ( from 15 % 15px , smooth by 20 % 0px with 10 % 60px , smooth by 20 % 30px ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from 5% 5px, smooth by 10% 10px with 0% 80px, smooth by 30% 20px)] to [shape(from 15% 15px, smooth by 20% 0px with 10% 60px, smooth by 20% 30px)] at (0.5) should be [shape(from 10% 10px, smooth by 15% 5px with 5% 70px, smooth by 25% 25px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [shape(from 5% 5px, smooth by 10% 10px with 0% 80px, smooth by 30% 20px)] to [shape(from 15% 15px, smooth by 20% 0px with 10% 60px, smooth by 20% 30px)] at (1) should be [shape(from 15% 15px, smooth by 20% 0px with 10% 60px, smooth by 20% 30px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 10 % 10px , smooth by 15 % 5px with 5 % 70px , smooth by 25 % 25px ) " but got "shape ( from 15 % 15px , smooth by 20 % 0px with 10 % 60px , smooth by 20 % 30px ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from 5% 5px, smooth by 10% 10px with 0% 80px, smooth by 30% 20px)] to [shape(from 15% 15px, smooth by 20% 0px with 10% 60px, smooth by 20% 30px)] at (1.5) should be [shape(from 20% 20px, smooth by 25% -5px with 15% 50px, smooth by 15% 35px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 20 % 20px , smooth by 25 % - 5px with 15 % 50px , smooth by 15 % 35px ) " but got "shape ( from 15 % 15px , smooth by 20 % 0px with 10 % 60px , smooth by 20 % 30px ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from 5% 5px, smooth by 10% 10px with 0% 80px, smooth by 30% 20px)] to [shape(from 15% 15px, smooth by 20% 0px with 10% 60px, smooth by 20% 30px)] at (-0.3) should be [shape(from 2% 2px, smooth by 7% 13px with -3% 86px, smooth by 33% 17px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 2 % 2px , smooth by 7 % 13px with - 3 % 86px , smooth by 33 % 17px ) " but got "shape ( from 15 % 15px , smooth by 20 % 0px with 10 % 60px , smooth by 20 % 30px ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from 5% 5px, smooth by 10% 10px with 0% 80px, smooth by 30% 20px)] to [shape(from 15% 15px, smooth by 20% 0px with 10% 60px, smooth by 20% 30px)] at (0) should be [shape(from 5% 5px, smooth by 10% 10px with 0% 80px, smooth by 30% 20px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 5 % 5px , smooth by 10 % 10px with 0 % 80px , smooth by 30 % 20px ) " but got "shape ( from 15 % 15px , smooth by 20 % 0px with 10 % 60px , smooth by 20 % 30px ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from 5% 5px, smooth by 10% 10px with 0% 80px, smooth by 30% 20px)] to [shape(from 15% 15px, smooth by 20% 0px with 10% 60px, smooth by 20% 30px)] at (0.5) should be [shape(from 10% 10px, smooth by 15% 5px with 5% 70px, smooth by 25% 25px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from 5% 5px, smooth by 10% 10px with 0% 80px, smooth by 30% 20px)] to [shape(from 15% 15px, smooth by 20% 0px with 10% 60px, smooth by 20% 30px)] at (1) should be [shape(from 15% 15px, smooth by 20% 0px with 10% 60px, smooth by 20% 30px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 10 % 10px , smooth by 15 % 5px with 5 % 70px , smooth by 25 % 25px ) " but got "shape ( from 15 % 15px , smooth by 20 % 0px with 10 % 60px , smooth by 20 % 30px ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from 5% 5px, smooth by 10% 10px with 0% 80px, smooth by 30% 20px)] to [shape(from 15% 15px, smooth by 20% 0px with 10% 60px, smooth by 20% 30px)] at (1.5) should be [shape(from 20% 20px, smooth by 25% -5px with 15% 50px, smooth by 15% 35px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 20 % 20px , smooth by 25 % - 5px with 15 % 50px , smooth by 15 % 35px ) " but got "shape ( from 15 % 15px , smooth by 20 % 0px with 10 % 60px , smooth by 20 % 30px ) " [FAIL] CSS Animations: property <clip-path> from [shape(from 5% 5px, smooth by 10% 10px with 0% 80px, smooth by 30% 20px)] to [shape(from 15% 15px, smooth by 20% 0px with 10% 60px, smooth by 20% 30px)] at (-0.3) should be [shape(from 2% 2px, smooth by 7% 13px with -3% 86px, smooth by 33% 17px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from 5% 5px, smooth by 10% 10px with 0% 80px, smooth by 30% 20px)] to [shape(from 15% 15px, smooth by 20% 0px with 10% 60px, smooth by 20% 30px)] at (0) should be [shape(from 5% 5px, smooth by 10% 10px with 0% 80px, smooth by 30% 20px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 2 % 2px , smooth by 7 % 13px with - 3 % 86px , smooth by 33 % 17px ) " but got "shape ( from 5 % 5px , smooth by 10 % 10px with 0 % 80px , smooth by 30 % 20px ) " [FAIL] CSS Animations: property <clip-path> from [shape(from 5% 5px, smooth by 10% 10px with 0% 80px, smooth by 30% 20px)] to [shape(from 15% 15px, smooth by 20% 0px with 10% 60px, smooth by 20% 30px)] at (0.5) should be [shape(from 10% 10px, smooth by 15% 5px with 5% 70px, smooth by 25% 25px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from 5% 5px, smooth by 10% 10px with 0% 80px, smooth by 30% 20px)] to [shape(from 15% 15px, smooth by 20% 0px with 10% 60px, smooth by 20% 30px)] at (1) should be [shape(from 15% 15px, smooth by 20% 0px with 10% 60px, smooth by 20% 30px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 10 % 10px , smooth by 15 % 5px with 5 % 70px , smooth by 25 % 25px ) " but got "shape ( from 15 % 15px , smooth by 20 % 0px with 10 % 60px , smooth by 20 % 30px ) " [FAIL] CSS Animations: property <clip-path> from [shape(from 5% 5px, smooth by 10% 10px with 0% 80px, smooth by 30% 20px)] to [shape(from 15% 15px, smooth by 20% 0px with 10% 60px, smooth by 20% 30px)] at (1.5) should be [shape(from 20% 20px, smooth by 25% -5px with 15% 50px, smooth by 15% 35px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 20 % 20px , smooth by 25 % - 5px with 15 % 50px , smooth by 15 % 35px ) " but got "shape ( from 15 % 15px , smooth by 20 % 0px with 10 % 60px , smooth by 20 % 30px ) " [FAIL] Web Animations: property <clip-path> from [shape(from 5% 5px, smooth by 10% 10px with 0% 80px, smooth by 30% 20px)] to [shape(from 15% 15px, smooth by 20% 0px with 10% 60px, smooth by 20% 30px)] at (-0.3) should be [shape(from 2% 2px, smooth by 7% 13px with -3% 86px, smooth by 33% 17px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from 5% 5px, smooth by 10% 10px with 0% 80px, smooth by 30% 20px)] to [shape(from 15% 15px, smooth by 20% 0px with 10% 60px, smooth by 20% 30px)] at (0) should be [shape(from 5% 5px, smooth by 10% 10px with 0% 80px, smooth by 30% 20px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 2 % 2px , smooth by 7 % 13px with - 3 % 86px , smooth by 33 % 17px ) " but got "shape ( from 5 % 5px , smooth by 10 % 10px with 0 % 80px , smooth by 30 % 20px ) " [FAIL] Web Animations: property <clip-path> from [shape(from 5% 5px, smooth by 10% 10px with 0% 80px, smooth by 30% 20px)] to [shape(from 15% 15px, smooth by 20% 0px with 10% 60px, smooth by 20% 30px)] at (0.5) should be [shape(from 10% 10px, smooth by 15% 5px with 5% 70px, smooth by 25% 25px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from 5% 5px, smooth by 10% 10px with 0% 80px, smooth by 30% 20px)] to [shape(from 15% 15px, smooth by 20% 0px with 10% 60px, smooth by 20% 30px)] at (1) should be [shape(from 15% 15px, smooth by 20% 0px with 10% 60px, smooth by 20% 30px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 10 % 10px , smooth by 15 % 5px with 5 % 70px , smooth by 25 % 25px ) " but got "shape ( from 15 % 15px , smooth by 20 % 0px with 10 % 60px , smooth by 20 % 30px ) " [FAIL] Web Animations: property <clip-path> from [shape(from 5% 5px, smooth by 10% 10px with 0% 80px, smooth by 30% 20px)] to [shape(from 15% 15px, smooth by 20% 0px with 10% 60px, smooth by 20% 30px)] at (1.5) should be [shape(from 20% 20px, smooth by 25% -5px with 15% 50px, smooth by 15% 35px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 20 % 20px , smooth by 25 % - 5px with 15 % 50px , smooth by 15 % 35px ) " but got "shape ( from 15 % 15px , smooth by 20 % 0px with 10 % 60px , smooth by 20 % 30px ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] to [shape(from 15% 15px, arc to 5% -25px of 20px 30px, arc by 25% -15px of 20px cw rotate 270deg small, arc to 25% 20px of 10px 5px small cw)] at (-0.3) should be [shape(from 2% 2px, arc to 18% -12px of 7px 17px ccw small, arc by 12% -2px of 33px 33px rotate -42deg cw large , arc to 25% 20px of 10px 5px ccw small)] - assert_equals: expected "shape ( from 2 % 2px , arc to 18 % - 12px of 7px 17px , arc by 12 % - 2px of 33px rotate - 42deg , arc to 25 % 20px of 10px 5px ) " but got "shape ( from 15 % 15px , arc to 5 % - 25px of 20px 30px , arc by 25 % - 15px of 20px rotate 270deg , arc to 25 % 20px of 10px 5px ) " + assert_equals: expected "shape ( from 2 % 2px , arc to 18 % - 12px of 7px 17px , arc by 12 % - 2px of 33px cw large rotate - 42deg , arc to 25 % 20px of 10px 5px ) " but got "shape ( from 15 % 15px , arc to 5 % - 25px of 20px 30px , arc by 25 % - 15px of 20px cw rotate 270deg , arc to 25 % 20px of 10px 5px cw ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] to [shape(from 15% 15px, arc to 5% -25px of 20px 30px, arc by 25% -15px of 20px cw rotate 270deg small, arc to 25% 20px of 10px 5px small cw)] at (0) should be [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] - assert_equals: expected "shape ( from 5 % 5px , arc to 15 % - 15px of 10px 20px , arc by 15 % - 5px of 30px rotate 30deg , arc to 25 % 20px of 10px 5px ) " but got "shape ( from 15 % 15px , arc to 5 % - 25px of 20px 30px , arc by 25 % - 15px of 20px rotate 270deg , arc to 25 % 20px of 10px 5px ) " + assert_equals: expected "shape ( from 5 % 5px , arc to 15 % - 15px of 10px 20px , arc by 15 % - 5px of 30px cw large rotate 30deg , arc to 25 % 20px of 10px 5px ) " but got "shape ( from 15 % 15px , arc to 5 % - 25px of 20px 30px , arc by 25 % - 15px of 20px cw rotate 270deg , arc to 25 % 20px of 10px 5px cw ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] to [shape(from 15% 15px, arc to 5% -25px of 20px 30px, arc by 25% -15px of 20px cw rotate 270deg small, arc to 25% 20px of 10px 5px small cw)] at (0.3) should be [shape(from 8% 8px, arc to 12% -18px of 13px 23px ccw small, arc by 18% -8px of 27px 27px rotate 102deg cw large, arc to 25% 20px of 10px 5px cw small )] - assert_equals: expected "shape ( from 8 % 8px , arc to 12 % - 18px of 13px 23px , arc by 18 % - 8px of 27px rotate 102deg , arc to 25 % 20px of 10px 5px ) " but got "shape ( from 15 % 15px , arc to 5 % - 25px of 20px 30px , arc by 25 % - 15px of 20px rotate 270deg , arc to 25 % 20px of 10px 5px ) " + assert_equals: expected "shape ( from 8 % 8px , arc to 12 % - 18px of 13px 23px , arc by 18 % - 8px of 27px cw large rotate 102deg , arc to 25 % 20px of 10px 5px cw ) " but got "shape ( from 15 % 15px , arc to 5 % - 25px of 20px 30px , arc by 25 % - 15px of 20px cw rotate 270deg , arc to 25 % 20px of 10px 5px cw ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] to [shape(from 15% 15px, arc to 5% -25px of 20px 30px, arc by 25% -15px of 20px cw rotate 270deg small, arc to 25% 20px of 10px 5px small cw)] at (0.5) should be [shape(from 10% 10px, arc to 10% -20px of 15px 25px ccw small, arc by 20% -10px of 25px rotate 150deg cw large, arc to 25% 20px of 10px 5px cw small)] - assert_equals: expected "shape ( from 10 % 10px , arc to 10 % - 20px of 15px 25px , arc by 20 % - 10px of 25px rotate 150deg , arc to 25 % 20px of 10px 5px ) " but got "shape ( from 15 % 15px , arc to 5 % - 25px of 20px 30px , arc by 25 % - 15px of 20px rotate 270deg , arc to 25 % 20px of 10px 5px ) " + assert_equals: expected "shape ( from 10 % 10px , arc to 10 % - 20px of 15px 25px , arc by 20 % - 10px of 25px cw large rotate 150deg , arc to 25 % 20px of 10px 5px cw ) " but got "shape ( from 15 % 15px , arc to 5 % - 25px of 20px 30px , arc by 25 % - 15px of 20px cw rotate 270deg , arc to 25 % 20px of 10px 5px cw ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] to [shape(from 15% 15px, arc to 5% -25px of 20px 30px, arc by 25% -15px of 20px cw rotate 270deg small, arc to 25% 20px of 10px 5px small cw)] at (1.5) should be [shape(from 20% 20px, arc to 0% -30px of 25px 35px ccw small, arc by 30% -20px of 15px rotate 390deg cw small, arc to 25% 20px of 10px 5px cw small)] - assert_equals: expected "shape ( from 20 % 20px , arc to 0 % - 30px of 25px 35px , arc by 30 % - 20px of 15px rotate 390deg , arc to 25 % 20px of 10px 5px ) " but got "shape ( from 15 % 15px , arc to 5 % - 25px of 20px 30px , arc by 25 % - 15px of 20px rotate 270deg , arc to 25 % 20px of 10px 5px ) " + assert_equals: expected "shape ( from 20 % 20px , arc to 0 % - 30px of 25px 35px , arc by 30 % - 20px of 15px cw rotate 390deg , arc to 25 % 20px of 10px 5px cw ) " but got "shape ( from 15 % 15px , arc to 5 % - 25px of 20px 30px , arc by 25 % - 15px of 20px cw rotate 270deg , arc to 25 % 20px of 10px 5px cw ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] to [shape(from 15% 15px, arc to 5% -25px of 20px 30px, arc by 25% -15px of 20px cw rotate 270deg small, arc to 25% 20px of 10px 5px small cw)] at (-0.3) should be [shape(from 2% 2px, arc to 18% -12px of 7px 17px ccw small, arc by 12% -2px of 33px 33px rotate -42deg cw large , arc to 25% 20px of 10px 5px ccw small)] - assert_equals: expected "shape ( from 2 % 2px , arc to 18 % - 12px of 7px 17px , arc by 12 % - 2px of 33px rotate - 42deg , arc to 25 % 20px of 10px 5px ) " but got "shape ( from 15 % 15px , arc to 5 % - 25px of 20px 30px , arc by 25 % - 15px of 20px rotate 270deg , arc to 25 % 20px of 10px 5px ) " + assert_equals: expected "shape ( from 2 % 2px , arc to 18 % - 12px of 7px 17px , arc by 12 % - 2px of 33px cw large rotate - 42deg , arc to 25 % 20px of 10px 5px ) " but got "shape ( from 15 % 15px , arc to 5 % - 25px of 20px 30px , arc by 25 % - 15px of 20px cw rotate 270deg , arc to 25 % 20px of 10px 5px cw ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] to [shape(from 15% 15px, arc to 5% -25px of 20px 30px, arc by 25% -15px of 20px cw rotate 270deg small, arc to 25% 20px of 10px 5px small cw)] at (0) should be [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] - assert_equals: expected "shape ( from 5 % 5px , arc to 15 % - 15px of 10px 20px , arc by 15 % - 5px of 30px rotate 30deg , arc to 25 % 20px of 10px 5px ) " but got "shape ( from 15 % 15px , arc to 5 % - 25px of 20px 30px , arc by 25 % - 15px of 20px rotate 270deg , arc to 25 % 20px of 10px 5px ) " + assert_equals: expected "shape ( from 5 % 5px , arc to 15 % - 15px of 10px 20px , arc by 15 % - 5px of 30px cw large rotate 30deg , arc to 25 % 20px of 10px 5px ) " but got "shape ( from 15 % 15px , arc to 5 % - 25px of 20px 30px , arc by 25 % - 15px of 20px cw rotate 270deg , arc to 25 % 20px of 10px 5px cw ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] to [shape(from 15% 15px, arc to 5% -25px of 20px 30px, arc by 25% -15px of 20px cw rotate 270deg small, arc to 25% 20px of 10px 5px small cw)] at (0.3) should be [shape(from 8% 8px, arc to 12% -18px of 13px 23px ccw small, arc by 18% -8px of 27px 27px rotate 102deg cw large, arc to 25% 20px of 10px 5px cw small )] - assert_equals: expected "shape ( from 8 % 8px , arc to 12 % - 18px of 13px 23px , arc by 18 % - 8px of 27px rotate 102deg , arc to 25 % 20px of 10px 5px ) " but got "shape ( from 15 % 15px , arc to 5 % - 25px of 20px 30px , arc by 25 % - 15px of 20px rotate 270deg , arc to 25 % 20px of 10px 5px ) " + assert_equals: expected "shape ( from 8 % 8px , arc to 12 % - 18px of 13px 23px , arc by 18 % - 8px of 27px cw large rotate 102deg , arc to 25 % 20px of 10px 5px cw ) " but got "shape ( from 15 % 15px , arc to 5 % - 25px of 20px 30px , arc by 25 % - 15px of 20px cw rotate 270deg , arc to 25 % 20px of 10px 5px cw ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] to [shape(from 15% 15px, arc to 5% -25px of 20px 30px, arc by 25% -15px of 20px cw rotate 270deg small, arc to 25% 20px of 10px 5px small cw)] at (0.5) should be [shape(from 10% 10px, arc to 10% -20px of 15px 25px ccw small, arc by 20% -10px of 25px rotate 150deg cw large, arc to 25% 20px of 10px 5px cw small)] - assert_equals: expected "shape ( from 10 % 10px , arc to 10 % - 20px of 15px 25px , arc by 20 % - 10px of 25px rotate 150deg , arc to 25 % 20px of 10px 5px ) " but got "shape ( from 15 % 15px , arc to 5 % - 25px of 20px 30px , arc by 25 % - 15px of 20px rotate 270deg , arc to 25 % 20px of 10px 5px ) " + assert_equals: expected "shape ( from 10 % 10px , arc to 10 % - 20px of 15px 25px , arc by 20 % - 10px of 25px cw large rotate 150deg , arc to 25 % 20px of 10px 5px cw ) " but got "shape ( from 15 % 15px , arc to 5 % - 25px of 20px 30px , arc by 25 % - 15px of 20px cw rotate 270deg , arc to 25 % 20px of 10px 5px cw ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] to [shape(from 15% 15px, arc to 5% -25px of 20px 30px, arc by 25% -15px of 20px cw rotate 270deg small, arc to 25% 20px of 10px 5px small cw)] at (1.5) should be [shape(from 20% 20px, arc to 0% -30px of 25px 35px ccw small, arc by 30% -20px of 15px rotate 390deg cw small, arc to 25% 20px of 10px 5px cw small)] - assert_equals: expected "shape ( from 20 % 20px , arc to 0 % - 30px of 25px 35px , arc by 30 % - 20px of 15px rotate 390deg , arc to 25 % 20px of 10px 5px ) " but got "shape ( from 15 % 15px , arc to 5 % - 25px of 20px 30px , arc by 25 % - 15px of 20px rotate 270deg , arc to 25 % 20px of 10px 5px ) " + assert_equals: expected "shape ( from 20 % 20px , arc to 0 % - 30px of 25px 35px , arc by 30 % - 20px of 15px cw rotate 390deg , arc to 25 % 20px of 10px 5px cw ) " but got "shape ( from 15 % 15px , arc to 5 % - 25px of 20px 30px , arc by 25 % - 15px of 20px cw rotate 270deg , arc to 25 % 20px of 10px 5px cw ) " [FAIL] CSS Animations: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] to [shape(from 15% 15px, arc to 5% -25px of 20px 30px, arc by 25% -15px of 20px cw rotate 270deg small, arc to 25% 20px of 10px 5px small cw)] at (-0.3) should be [shape(from 2% 2px, arc to 18% -12px of 7px 17px ccw small, arc by 12% -2px of 33px 33px rotate -42deg cw large , arc to 25% 20px of 10px 5px ccw small)] - assert_equals: expected "shape ( from 2 % 2px , arc to 18 % - 12px of 7px 17px , arc by 12 % - 2px of 33px rotate - 42deg , arc to 25 % 20px of 10px 5px ) " but got "shape ( from 5 % 5px , arc to 15 % - 15px of 10px 20px , arc by 15 % - 5px of 30px rotate 30deg , arc to 25 % 20px of 10px 5px ) " + assert_equals: expected "shape ( from 2 % 2px , arc to 18 % - 12px of 7px 17px , arc by 12 % - 2px of 33px cw large rotate - 42deg , arc to 25 % 20px of 10px 5px ) " but got "shape ( from 5 % 5px , arc to 15 % - 15px of 10px 20px , arc by 15 % - 5px of 30px cw large rotate 30deg , arc to 25 % 20px of 10px 5px ) " [FAIL] CSS Animations: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] to [shape(from 15% 15px, arc to 5% -25px of 20px 30px, arc by 25% -15px of 20px cw rotate 270deg small, arc to 25% 20px of 10px 5px small cw)] at (0.3) should be [shape(from 8% 8px, arc to 12% -18px of 13px 23px ccw small, arc by 18% -8px of 27px 27px rotate 102deg cw large, arc to 25% 20px of 10px 5px cw small )] - assert_equals: expected "shape ( from 8 % 8px , arc to 12 % - 18px of 13px 23px , arc by 18 % - 8px of 27px rotate 102deg , arc to 25 % 20px of 10px 5px ) " but got "shape ( from 5 % 5px , arc to 15 % - 15px of 10px 20px , arc by 15 % - 5px of 30px rotate 30deg , arc to 25 % 20px of 10px 5px ) " + assert_equals: expected "shape ( from 8 % 8px , arc to 12 % - 18px of 13px 23px , arc by 18 % - 8px of 27px cw large rotate 102deg , arc to 25 % 20px of 10px 5px cw ) " but got "shape ( from 5 % 5px , arc to 15 % - 15px of 10px 20px , arc by 15 % - 5px of 30px cw large rotate 30deg , arc to 25 % 20px of 10px 5px ) " [FAIL] CSS Animations: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] to [shape(from 15% 15px, arc to 5% -25px of 20px 30px, arc by 25% -15px of 20px cw rotate 270deg small, arc to 25% 20px of 10px 5px small cw)] at (0.5) should be [shape(from 10% 10px, arc to 10% -20px of 15px 25px ccw small, arc by 20% -10px of 25px rotate 150deg cw large, arc to 25% 20px of 10px 5px cw small)] - assert_equals: expected "shape ( from 10 % 10px , arc to 10 % - 20px of 15px 25px , arc by 20 % - 10px of 25px rotate 150deg , arc to 25 % 20px of 10px 5px ) " but got "shape ( from 15 % 15px , arc to 5 % - 25px of 20px 30px , arc by 25 % - 15px of 20px rotate 270deg , arc to 25 % 20px of 10px 5px ) " + assert_equals: expected "shape ( from 10 % 10px , arc to 10 % - 20px of 15px 25px , arc by 20 % - 10px of 25px cw large rotate 150deg , arc to 25 % 20px of 10px 5px cw ) " but got "shape ( from 15 % 15px , arc to 5 % - 25px of 20px 30px , arc by 25 % - 15px of 20px cw rotate 270deg , arc to 25 % 20px of 10px 5px cw ) " [FAIL] CSS Animations: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] to [shape(from 15% 15px, arc to 5% -25px of 20px 30px, arc by 25% -15px of 20px cw rotate 270deg small, arc to 25% 20px of 10px 5px small cw)] at (1.5) should be [shape(from 20% 20px, arc to 0% -30px of 25px 35px ccw small, arc by 30% -20px of 15px rotate 390deg cw small, arc to 25% 20px of 10px 5px cw small)] - assert_equals: expected "shape ( from 20 % 20px , arc to 0 % - 30px of 25px 35px , arc by 30 % - 20px of 15px rotate 390deg , arc to 25 % 20px of 10px 5px ) " but got "shape ( from 15 % 15px , arc to 5 % - 25px of 20px 30px , arc by 25 % - 15px of 20px rotate 270deg , arc to 25 % 20px of 10px 5px ) " + assert_equals: expected "shape ( from 20 % 20px , arc to 0 % - 30px of 25px 35px , arc by 30 % - 20px of 15px cw rotate 390deg , arc to 25 % 20px of 10px 5px cw ) " but got "shape ( from 15 % 15px , arc to 5 % - 25px of 20px 30px , arc by 25 % - 15px of 20px cw rotate 270deg , arc to 25 % 20px of 10px 5px cw ) " [FAIL] Web Animations: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] to [shape(from 15% 15px, arc to 5% -25px of 20px 30px, arc by 25% -15px of 20px cw rotate 270deg small, arc to 25% 20px of 10px 5px small cw)] at (-0.3) should be [shape(from 2% 2px, arc to 18% -12px of 7px 17px ccw small, arc by 12% -2px of 33px 33px rotate -42deg cw large , arc to 25% 20px of 10px 5px ccw small)] - assert_equals: expected "shape ( from 2 % 2px , arc to 18 % - 12px of 7px 17px , arc by 12 % - 2px of 33px rotate - 42deg , arc to 25 % 20px of 10px 5px ) " but got "shape ( from 5 % 5px , arc to 15 % - 15px of 10px 20px , arc by 15 % - 5px of 30px rotate 30deg , arc to 25 % 20px of 10px 5px ) " + assert_equals: expected "shape ( from 2 % 2px , arc to 18 % - 12px of 7px 17px , arc by 12 % - 2px of 33px cw large rotate - 42deg , arc to 25 % 20px of 10px 5px ) " but got "shape ( from 5 % 5px , arc to 15 % - 15px of 10px 20px , arc by 15 % - 5px of 30px cw large rotate 30deg , arc to 25 % 20px of 10px 5px ) " [FAIL] Web Animations: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] to [shape(from 15% 15px, arc to 5% -25px of 20px 30px, arc by 25% -15px of 20px cw rotate 270deg small, arc to 25% 20px of 10px 5px small cw)] at (0.3) should be [shape(from 8% 8px, arc to 12% -18px of 13px 23px ccw small, arc by 18% -8px of 27px 27px rotate 102deg cw large, arc to 25% 20px of 10px 5px cw small )] - assert_equals: expected "shape ( from 8 % 8px , arc to 12 % - 18px of 13px 23px , arc by 18 % - 8px of 27px rotate 102deg , arc to 25 % 20px of 10px 5px ) " but got "shape ( from 5 % 5px , arc to 15 % - 15px of 10px 20px , arc by 15 % - 5px of 30px rotate 30deg , arc to 25 % 20px of 10px 5px ) " + assert_equals: expected "shape ( from 8 % 8px , arc to 12 % - 18px of 13px 23px , arc by 18 % - 8px of 27px cw large rotate 102deg , arc to 25 % 20px of 10px 5px cw ) " but got "shape ( from 5 % 5px , arc to 15 % - 15px of 10px 20px , arc by 15 % - 5px of 30px cw large rotate 30deg , arc to 25 % 20px of 10px 5px ) " [FAIL] Web Animations: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] to [shape(from 15% 15px, arc to 5% -25px of 20px 30px, arc by 25% -15px of 20px cw rotate 270deg small, arc to 25% 20px of 10px 5px small cw)] at (0.5) should be [shape(from 10% 10px, arc to 10% -20px of 15px 25px ccw small, arc by 20% -10px of 25px rotate 150deg cw large, arc to 25% 20px of 10px 5px cw small)] - assert_equals: expected "shape ( from 10 % 10px , arc to 10 % - 20px of 15px 25px , arc by 20 % - 10px of 25px rotate 150deg , arc to 25 % 20px of 10px 5px ) " but got "shape ( from 15 % 15px , arc to 5 % - 25px of 20px 30px , arc by 25 % - 15px of 20px rotate 270deg , arc to 25 % 20px of 10px 5px ) " + assert_equals: expected "shape ( from 10 % 10px , arc to 10 % - 20px of 15px 25px , arc by 20 % - 10px of 25px cw large rotate 150deg , arc to 25 % 20px of 10px 5px cw ) " but got "shape ( from 15 % 15px , arc to 5 % - 25px of 20px 30px , arc by 25 % - 15px of 20px cw rotate 270deg , arc to 25 % 20px of 10px 5px cw ) " [FAIL] Web Animations: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] to [shape(from 15% 15px, arc to 5% -25px of 20px 30px, arc by 25% -15px of 20px cw rotate 270deg small, arc to 25% 20px of 10px 5px small cw)] at (1.5) should be [shape(from 20% 20px, arc to 0% -30px of 25px 35px ccw small, arc by 30% -20px of 15px rotate 390deg cw small, arc to 25% 20px of 10px 5px cw small)] - assert_equals: expected "shape ( from 20 % 20px , arc to 0 % - 30px of 25px 35px , arc by 30 % - 20px of 15px rotate 390deg , arc to 25 % 20px of 10px 5px ) " but got "shape ( from 15 % 15px , arc to 5 % - 25px of 20px 30px , arc by 25 % - 15px of 20px rotate 270deg , arc to 25 % 20px of 10px 5px ) " + assert_equals: expected "shape ( from 20 % 20px , arc to 0 % - 30px of 25px 35px , arc by 30 % - 20px of 15px cw rotate 390deg , arc to 25 % 20px of 10px 5px cw ) " but got "shape ( from 15 % 15px , arc to 5 % - 25px of 20px 30px , arc by 25 % - 15px of 20px cw rotate 270deg , arc to 25 % 20px of 10px 5px cw ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from 5px -5%, hline to 10px, vline by 10rem, hline by 8.25px, close, vline by 3pt)] to [shape(from -5px 5px, hline to 20px, vline by 10%, hline by 1em, close, vline by 6pt)] at (-0.3) should be [shape(from 8px calc(-6.5% - 1.5px), hline to 7px, vline by calc(-3% + 208px), hline by 5.92px, close, vline by 2.8px)] assert_equals: expected "shape ( from 8px calc ( - 6.5 % - 1.5px ) , hline to 7px , vline by calc ( - 3 % + 208px ) , hline by 5.92px , close , vline by 2.8px ) " but got "shape ( from - 5px 5px , hline to 20px , vline by 10 % , hline by 16px , close , vline by 8px ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from 5px -5%, hline to 10px, vline by 10rem, hline by 8.25px, close, vline by 3pt)] to [shape(from -5px 5px, hline to 20px, vline by 10%, hline by 1em, close, vline by 6pt)] at (0) should be [shape(from 5px -5%, hline to 10px, vline by calc(0% + 160px), hline by 8.25px, close, vline by 4px)] @@ -361,248 +313,224 @@ [FAIL] Web Animations: property <clip-path> from [shape(from 5px 5px, hline to 5px, vline to -5px, close)] to [path("M 15 15 H 25 V -15 Z")] at (1.5) should be [shape(from 20px 20px, hline to 35px, vline to -20px, close)] assert_equals: expected "shape ( from 20px 20px , hline to 35px , vline to - 20px , close ) " but got "path ( \\" M 15 15 H 25 V - 15 Z \\" ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] to [path("M 15 15 Q 10 60 20 0 C 30 40 -5 100 20 30")] at (-0.3) should be [shape(from calc(6.5% - 4.5px) 2px, curve to calc(13% - 6px) 13px with calc(0% - 3px) 86px, curve to calc(39% - 6px) 17px with calc(26% - 9px) 53px / calc(32.5% + 1.5px) 61px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( 6.5 % - 4.5px ) 2px , curve to calc ( 13 % - 6px ) 13px with calc ( 0 % - 3px ) 86px , curve to calc ( 39 % - 6px ) 17px with calc ( 26 % - 9px ) 53px / calc ( 32.5 % + 1.5px ) 61px ) " but got "path ( \\" M 15 15 Q 10 60 20 0 C 30 40 - 5 100 20 30 \\" ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] to [path("M 15 15 Q 10 60 20 0 C 30 40 -5 100 20 30")] at (0) should be [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 5 % 5px , curve to 10 % 10px with 0 % 80px , curve to 30 % 20px with 20 % 50px / 25 % 70px ) " but got "path ( \\" M 15 15 Q 10 60 20 0 C 30 40 - 5 100 20 30 \\" ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] to [path("M 15 15 Q 10 60 20 0 C 30 40 -5 100 20 30")] at (0.5) should be [shape(from calc(2.5% + 7.5px) 10px, curve to calc(5% + 10px) 5px with calc(0% + 5px) 70px, curve to calc(15% + 10px) 25px with calc(10% + 15px) 45px / calc(12.5% - 2.5px) 85px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( 2.5 % + 7.5px ) 10px , curve to calc ( 5 % + 10px ) 5px with calc ( 0 % + 5px ) 70px , curve to calc ( 15 % + 10px ) 25px with calc ( 10 % + 15px ) 45px / calc ( 12.5 % - 2.5px ) 85px ) " but got "path ( \\" M 15 15 Q 10 60 20 0 C 30 40 - 5 100 20 30 \\" ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] to [path("M 15 15 Q 10 60 20 0 C 30 40 -5 100 20 30")] at (1) should be [shape(from calc(0% + 15px) 15px, curve to calc(0% + 20px) 0px with calc(0% + 10px) 60px, curve to calc(0% + 20px) 30px with calc(0% + 30px) 40px / calc(0% - 5px) 100px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( 0 % + 15px ) 15px , curve to calc ( 0 % + 20px ) 0px with calc ( 0 % + 10px ) 60px , curve to calc ( 0 % + 20px ) 30px with calc ( 0 % + 30px ) 40px / calc ( 0 % - 5px ) 100px ) " but got "path ( \\" M 15 15 Q 10 60 20 0 C 30 40 - 5 100 20 30 \\" ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] to [path("M 15 15 Q 10 60 20 0 C 30 40 -5 100 20 30")] at (1.5) should be [shape(from calc(-2.5% + 22.5px) 20px, curve to calc(-5% + 30px) -5px with calc(0% + 15px) 50px, curve to calc(-15% + 30px) 35px with calc(-10% + 45px) 35px / calc(-12.5% - 7.5px) 115px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( - 2.5 % + 22.5px ) 20px , curve to calc ( - 5 % + 30px ) - 5px with calc ( 0 % + 15px ) 50px , curve to calc ( - 15 % + 30px ) 35px with calc ( - 10 % + 45px ) 35px / calc ( - 12.5 % - 7.5px ) 115px ) " but got "path ( \\" M 15 15 Q 10 60 20 0 C 30 40 - 5 100 20 30 \\" ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] to [path("M 15 15 Q 10 60 20 0 C 30 40 -5 100 20 30")] at (-0.3) should be [shape(from calc(6.5% - 4.5px) 2px, curve to calc(13% - 6px) 13px with calc(0% - 3px) 86px, curve to calc(39% - 6px) 17px with calc(26% - 9px) 53px / calc(32.5% + 1.5px) 61px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( 6.5 % - 4.5px ) 2px , curve to calc ( 13 % - 6px ) 13px with calc ( 0 % - 3px ) 86px , curve to calc ( 39 % - 6px ) 17px with calc ( 26 % - 9px ) 53px / calc ( 32.5 % + 1.5px ) 61px ) " but got "path ( \\" M 15 15 Q 10 60 20 0 C 30 40 - 5 100 20 30 \\" ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] to [path("M 15 15 Q 10 60 20 0 C 30 40 -5 100 20 30")] at (0) should be [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 5 % 5px , curve to 10 % 10px with 0 % 80px , curve to 30 % 20px with 20 % 50px / 25 % 70px ) " but got "path ( \\" M 15 15 Q 10 60 20 0 C 30 40 - 5 100 20 30 \\" ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] to [path("M 15 15 Q 10 60 20 0 C 30 40 -5 100 20 30")] at (0.5) should be [shape(from calc(2.5% + 7.5px) 10px, curve to calc(5% + 10px) 5px with calc(0% + 5px) 70px, curve to calc(15% + 10px) 25px with calc(10% + 15px) 45px / calc(12.5% - 2.5px) 85px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( 2.5 % + 7.5px ) 10px , curve to calc ( 5 % + 10px ) 5px with calc ( 0 % + 5px ) 70px , curve to calc ( 15 % + 10px ) 25px with calc ( 10 % + 15px ) 45px / calc ( 12.5 % - 2.5px ) 85px ) " but got "path ( \\" M 15 15 Q 10 60 20 0 C 30 40 - 5 100 20 30 \\" ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] to [path("M 15 15 Q 10 60 20 0 C 30 40 -5 100 20 30")] at (1) should be [shape(from calc(0% + 15px) 15px, curve to calc(0% + 20px) 0px with calc(0% + 10px) 60px, curve to calc(0% + 20px) 30px with calc(0% + 30px) 40px / calc(0% - 5px) 100px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( 0 % + 15px ) 15px , curve to calc ( 0 % + 20px ) 0px with calc ( 0 % + 10px ) 60px , curve to calc ( 0 % + 20px ) 30px with calc ( 0 % + 30px ) 40px / calc ( 0 % - 5px ) 100px ) " but got "path ( \\" M 15 15 Q 10 60 20 0 C 30 40 - 5 100 20 30 \\" ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] to [path("M 15 15 Q 10 60 20 0 C 30 40 -5 100 20 30")] at (1.5) should be [shape(from calc(-2.5% + 22.5px) 20px, curve to calc(-5% + 30px) -5px with calc(0% + 15px) 50px, curve to calc(-15% + 30px) 35px with calc(-10% + 45px) 35px / calc(-12.5% - 7.5px) 115px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( - 2.5 % + 22.5px ) 20px , curve to calc ( - 5 % + 30px ) - 5px with calc ( 0 % + 15px ) 50px , curve to calc ( - 15 % + 30px ) 35px with calc ( - 10 % + 45px ) 35px / calc ( - 12.5 % - 7.5px ) 115px ) " but got "path ( \\" M 15 15 Q 10 60 20 0 C 30 40 - 5 100 20 30 \\" ) " [FAIL] CSS Animations: property <clip-path> from [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] to [path("M 15 15 Q 10 60 20 0 C 30 40 -5 100 20 30")] at (-0.3) should be [shape(from calc(6.5% - 4.5px) 2px, curve to calc(13% - 6px) 13px with calc(0% - 3px) 86px, curve to calc(39% - 6px) 17px with calc(26% - 9px) 53px / calc(32.5% + 1.5px) 61px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] to [path("M 15 15 Q 10 60 20 0 C 30 40 -5 100 20 30")] at (0) should be [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( 6.5 % - 4.5px ) 2px , curve to calc ( 13 % - 6px ) 13px with calc ( 0 % - 3px ) 86px , curve to calc ( 39 % - 6px ) 17px with calc ( 26 % - 9px ) 53px / calc ( 32.5 % + 1.5px ) 61px ) " but got "shape ( from 5 % 5px , curve to 10 % 10px with 0 % 80px , curve to 30 % 20px with 20 % 50px / 25 % 70px ) " [FAIL] CSS Animations: property <clip-path> from [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] to [path("M 15 15 Q 10 60 20 0 C 30 40 -5 100 20 30")] at (0.5) should be [shape(from calc(2.5% + 7.5px) 10px, curve to calc(5% + 10px) 5px with calc(0% + 5px) 70px, curve to calc(15% + 10px) 25px with calc(10% + 15px) 45px / calc(12.5% - 2.5px) 85px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( 2.5 % + 7.5px ) 10px , curve to calc ( 5 % + 10px ) 5px with calc ( 0 % + 5px ) 70px , curve to calc ( 15 % + 10px ) 25px with calc ( 10 % + 15px ) 45px / calc ( 12.5 % - 2.5px ) 85px ) " but got "path ( \\" M 15 15 Q 10 60 20 0 C 30 40 - 5 100 20 30 \\" ) " [FAIL] CSS Animations: property <clip-path> from [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] to [path("M 15 15 Q 10 60 20 0 C 30 40 -5 100 20 30")] at (1) should be [shape(from calc(0% + 15px) 15px, curve to calc(0% + 20px) 0px with calc(0% + 10px) 60px, curve to calc(0% + 20px) 30px with calc(0% + 30px) 40px / calc(0% - 5px) 100px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( 0 % + 15px ) 15px , curve to calc ( 0 % + 20px ) 0px with calc ( 0 % + 10px ) 60px , curve to calc ( 0 % + 20px ) 30px with calc ( 0 % + 30px ) 40px / calc ( 0 % - 5px ) 100px ) " but got "path ( \\" M 15 15 Q 10 60 20 0 C 30 40 - 5 100 20 30 \\" ) " [FAIL] CSS Animations: property <clip-path> from [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] to [path("M 15 15 Q 10 60 20 0 C 30 40 -5 100 20 30")] at (1.5) should be [shape(from calc(-2.5% + 22.5px) 20px, curve to calc(-5% + 30px) -5px with calc(0% + 15px) 50px, curve to calc(-15% + 30px) 35px with calc(-10% + 45px) 35px / calc(-12.5% - 7.5px) 115px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( - 2.5 % + 22.5px ) 20px , curve to calc ( - 5 % + 30px ) - 5px with calc ( 0 % + 15px ) 50px , curve to calc ( - 15 % + 30px ) 35px with calc ( - 10 % + 45px ) 35px / calc ( - 12.5 % - 7.5px ) 115px ) " but got "path ( \\" M 15 15 Q 10 60 20 0 C 30 40 - 5 100 20 30 \\" ) " [FAIL] Web Animations: property <clip-path> from [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] to [path("M 15 15 Q 10 60 20 0 C 30 40 -5 100 20 30")] at (-0.3) should be [shape(from calc(6.5% - 4.5px) 2px, curve to calc(13% - 6px) 13px with calc(0% - 3px) 86px, curve to calc(39% - 6px) 17px with calc(26% - 9px) 53px / calc(32.5% + 1.5px) 61px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] to [path("M 15 15 Q 10 60 20 0 C 30 40 -5 100 20 30")] at (0) should be [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( 6.5 % - 4.5px ) 2px , curve to calc ( 13 % - 6px ) 13px with calc ( 0 % - 3px ) 86px , curve to calc ( 39 % - 6px ) 17px with calc ( 26 % - 9px ) 53px / calc ( 32.5 % + 1.5px ) 61px ) " but got "shape ( from 5 % 5px , curve to 10 % 10px with 0 % 80px , curve to 30 % 20px with 20 % 50px / 25 % 70px ) " [FAIL] Web Animations: property <clip-path> from [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] to [path("M 15 15 Q 10 60 20 0 C 30 40 -5 100 20 30")] at (0.5) should be [shape(from calc(2.5% + 7.5px) 10px, curve to calc(5% + 10px) 5px with calc(0% + 5px) 70px, curve to calc(15% + 10px) 25px with calc(10% + 15px) 45px / calc(12.5% - 2.5px) 85px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( 2.5 % + 7.5px ) 10px , curve to calc ( 5 % + 10px ) 5px with calc ( 0 % + 5px ) 70px , curve to calc ( 15 % + 10px ) 25px with calc ( 10 % + 15px ) 45px / calc ( 12.5 % - 2.5px ) 85px ) " but got "path ( \\" M 15 15 Q 10 60 20 0 C 30 40 - 5 100 20 30 \\" ) " [FAIL] Web Animations: property <clip-path> from [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] to [path("M 15 15 Q 10 60 20 0 C 30 40 -5 100 20 30")] at (1) should be [shape(from calc(0% + 15px) 15px, curve to calc(0% + 20px) 0px with calc(0% + 10px) 60px, curve to calc(0% + 20px) 30px with calc(0% + 30px) 40px / calc(0% - 5px) 100px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( 0 % + 15px ) 15px , curve to calc ( 0 % + 20px ) 0px with calc ( 0 % + 10px ) 60px , curve to calc ( 0 % + 20px ) 30px with calc ( 0 % + 30px ) 40px / calc ( 0 % - 5px ) 100px ) " but got "path ( \\" M 15 15 Q 10 60 20 0 C 30 40 - 5 100 20 30 \\" ) " [FAIL] Web Animations: property <clip-path> from [shape(from 5% 5px, curve to 10% 10px with 0% 80px, curve to 30% 20px with 20% 50px / 25% 70px)] to [path("M 15 15 Q 10 60 20 0 C 30 40 -5 100 20 30")] at (1.5) should be [shape(from calc(-2.5% + 22.5px) 20px, curve to calc(-5% + 30px) -5px with calc(0% + 15px) 50px, curve to calc(-15% + 30px) 35px with calc(-10% + 45px) 35px / calc(-12.5% - 7.5px) 115px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( - 2.5 % + 22.5px ) 20px , curve to calc ( - 5 % + 30px ) - 5px with calc ( 0 % + 15px ) 50px , curve to calc ( - 15 % + 30px ) 35px with calc ( - 10 % + 45px ) 35px / calc ( - 12.5 % - 7.5px ) 115px ) " but got "path ( \\" M 15 15 Q 10 60 20 0 C 30 40 - 5 100 20 30 \\" ) " [FAIL] CSS Transitions: property <clip-path> from [path("M 5 5 q 0 80 10 10 c 20 50 25 70 30 20")] to [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] at (-0.3) should be [shape(from calc(-4.5% + 6.5px) 2px, curve by calc(-6% + 13px) 13px with -3% 86px, curve by calc(-6% + 39px) 17px with calc(-9% + 26px) 53px / calc(1.5% + 32.5px) 61px)] - assert_true: 'to' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( - 4.5 % + 6.5px ) 2px , curve by calc ( - 6 % + 13px ) 13px with - 3 % 86px , curve by calc ( - 6 % + 39px ) 17px with calc ( - 9 % + 26px ) 53px / calc ( 1.5 % + 32.5px ) 61px ) " but got "shape ( from 15 % 15px , curve by 20 % 0px with 10 % 60px , curve by 20 % 30px with 30 % 40px / - 5 % 100px ) " [FAIL] CSS Transitions: property <clip-path> from [path("M 5 5 q 0 80 10 10 c 20 50 25 70 30 20")] to [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] at (0) should be [shape(from calc(0% + 5px) 5px, curve by calc(0% + 10px) 10px with 0% 80px, curve by calc(0% + 30px) 20px with calc(0% + 20px) 50px / calc(0% + 25px) 70px)] - assert_true: 'to' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( 0 % + 5px ) 5px , curve by calc ( 0 % + 10px ) 10px with 0 % 80px , curve by calc ( 0 % + 30px ) 20px with calc ( 0 % + 20px ) 50px / calc ( 0 % + 25px ) 70px ) " but got "shape ( from 15 % 15px , curve by 20 % 0px with 10 % 60px , curve by 20 % 30px with 30 % 40px / - 5 % 100px ) " [FAIL] CSS Transitions: property <clip-path> from [path("M 5 5 q 0 80 10 10 c 20 50 25 70 30 20")] to [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] at (0.5) should be [shape(from calc(7.5% + 2.5px) 10px, curve by calc(10% + 5px) 5px with 5% 70px, curve by calc(10% + 15px) 25px with calc(15% + 10px) 45px / calc(-2.5% + 12.5px) 85px)] - assert_true: 'to' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [path("M 5 5 q 0 80 10 10 c 20 50 25 70 30 20")] to [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] at (1) should be [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] - assert_true: 'to' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( 7.5 % + 2.5px ) 10px , curve by calc ( 10 % + 5px ) 5px with 5 % 70px , curve by calc ( 10 % + 15px ) 25px with calc ( 15 % + 10px ) 45px / calc ( - 2.5 % + 12.5px ) 85px ) " but got "shape ( from 15 % 15px , curve by 20 % 0px with 10 % 60px , curve by 20 % 30px with 30 % 40px / - 5 % 100px ) " [FAIL] CSS Transitions: property <clip-path> from [path("M 5 5 q 0 80 10 10 c 20 50 25 70 30 20")] to [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] at (1.5) should be [shape(from calc(22.5% - 2.5px) 20px, curve by calc(30% - 5px) -5px with 15% 50px, curve by calc(30% - 15px) 35px with calc(45% - 10px) 35px / calc(-7.5% - 12.5px) 115px)] - assert_true: 'to' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( 22.5 % - 2.5px ) 20px , curve by calc ( 30 % - 5px ) - 5px with 15 % 50px , curve by calc ( 30 % - 15px ) 35px with calc ( 45 % - 10px ) 35px / calc ( - 7.5 % - 12.5px ) 115px ) " but got "shape ( from 15 % 15px , curve by 20 % 0px with 10 % 60px , curve by 20 % 30px with 30 % 40px / - 5 % 100px ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [path("M 5 5 q 0 80 10 10 c 20 50 25 70 30 20")] to [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] at (-0.3) should be [shape(from calc(-4.5% + 6.5px) 2px, curve by calc(-6% + 13px) 13px with -3% 86px, curve by calc(-6% + 39px) 17px with calc(-9% + 26px) 53px / calc(1.5% + 32.5px) 61px)] - assert_true: 'to' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( - 4.5 % + 6.5px ) 2px , curve by calc ( - 6 % + 13px ) 13px with - 3 % 86px , curve by calc ( - 6 % + 39px ) 17px with calc ( - 9 % + 26px ) 53px / calc ( 1.5 % + 32.5px ) 61px ) " but got "shape ( from 15 % 15px , curve by 20 % 0px with 10 % 60px , curve by 20 % 30px with 30 % 40px / - 5 % 100px ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [path("M 5 5 q 0 80 10 10 c 20 50 25 70 30 20")] to [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] at (0) should be [shape(from calc(0% + 5px) 5px, curve by calc(0% + 10px) 10px with 0% 80px, curve by calc(0% + 30px) 20px with calc(0% + 20px) 50px / calc(0% + 25px) 70px)] - assert_true: 'to' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( 0 % + 5px ) 5px , curve by calc ( 0 % + 10px ) 10px with 0 % 80px , curve by calc ( 0 % + 30px ) 20px with calc ( 0 % + 20px ) 50px / calc ( 0 % + 25px ) 70px ) " but got "shape ( from 15 % 15px , curve by 20 % 0px with 10 % 60px , curve by 20 % 30px with 30 % 40px / - 5 % 100px ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [path("M 5 5 q 0 80 10 10 c 20 50 25 70 30 20")] to [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] at (0.5) should be [shape(from calc(7.5% + 2.5px) 10px, curve by calc(10% + 5px) 5px with 5% 70px, curve by calc(10% + 15px) 25px with calc(15% + 10px) 45px / calc(-2.5% + 12.5px) 85px)] - assert_true: 'to' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [path("M 5 5 q 0 80 10 10 c 20 50 25 70 30 20")] to [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] at (1) should be [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] - assert_true: 'to' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( 7.5 % + 2.5px ) 10px , curve by calc ( 10 % + 5px ) 5px with 5 % 70px , curve by calc ( 10 % + 15px ) 25px with calc ( 15 % + 10px ) 45px / calc ( - 2.5 % + 12.5px ) 85px ) " but got "shape ( from 15 % 15px , curve by 20 % 0px with 10 % 60px , curve by 20 % 30px with 30 % 40px / - 5 % 100px ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [path("M 5 5 q 0 80 10 10 c 20 50 25 70 30 20")] to [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] at (1.5) should be [shape(from calc(22.5% - 2.5px) 20px, curve by calc(30% - 5px) -5px with 15% 50px, curve by calc(30% - 15px) 35px with calc(45% - 10px) 35px / calc(-7.5% - 12.5px) 115px)] - assert_true: 'to' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( 22.5 % - 2.5px ) 20px , curve by calc ( 30 % - 5px ) - 5px with 15 % 50px , curve by calc ( 30 % - 15px ) 35px with calc ( 45 % - 10px ) 35px / calc ( - 7.5 % - 12.5px ) 115px ) " but got "shape ( from 15 % 15px , curve by 20 % 0px with 10 % 60px , curve by 20 % 30px with 30 % 40px / - 5 % 100px ) " [FAIL] CSS Animations: property <clip-path> from [path("M 5 5 q 0 80 10 10 c 20 50 25 70 30 20")] to [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] at (-0.3) should be [shape(from calc(-4.5% + 6.5px) 2px, curve by calc(-6% + 13px) 13px with -3% 86px, curve by calc(-6% + 39px) 17px with calc(-9% + 26px) 53px / calc(1.5% + 32.5px) 61px)] - assert_true: 'to' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( - 4.5 % + 6.5px ) 2px , curve by calc ( - 6 % + 13px ) 13px with - 3 % 86px , curve by calc ( - 6 % + 39px ) 17px with calc ( - 9 % + 26px ) 53px / calc ( 1.5 % + 32.5px ) 61px ) " but got "path ( \\" M 5 5 Q 5 85 15 15 C 35 65 40 85 45 35 \\" ) " [FAIL] CSS Animations: property <clip-path> from [path("M 5 5 q 0 80 10 10 c 20 50 25 70 30 20")] to [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] at (0) should be [shape(from calc(0% + 5px) 5px, curve by calc(0% + 10px) 10px with 0% 80px, curve by calc(0% + 30px) 20px with calc(0% + 20px) 50px / calc(0% + 25px) 70px)] - assert_true: 'to' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( 0 % + 5px ) 5px , curve by calc ( 0 % + 10px ) 10px with 0 % 80px , curve by calc ( 0 % + 30px ) 20px with calc ( 0 % + 20px ) 50px / calc ( 0 % + 25px ) 70px ) " but got "path ( \\" M 5 5 Q 5 85 15 15 C 35 65 40 85 45 35 \\" ) " [FAIL] CSS Animations: property <clip-path> from [path("M 5 5 q 0 80 10 10 c 20 50 25 70 30 20")] to [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] at (0.5) should be [shape(from calc(7.5% + 2.5px) 10px, curve by calc(10% + 5px) 5px with 5% 70px, curve by calc(10% + 15px) 25px with calc(15% + 10px) 45px / calc(-2.5% + 12.5px) 85px)] - assert_true: 'to' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [path("M 5 5 q 0 80 10 10 c 20 50 25 70 30 20")] to [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] at (1) should be [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] - assert_true: 'to' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( 7.5 % + 2.5px ) 10px , curve by calc ( 10 % + 5px ) 5px with 5 % 70px , curve by calc ( 10 % + 15px ) 25px with calc ( 15 % + 10px ) 45px / calc ( - 2.5 % + 12.5px ) 85px ) " but got "shape ( from 15 % 15px , curve by 20 % 0px with 10 % 60px , curve by 20 % 30px with 30 % 40px / - 5 % 100px ) " [FAIL] CSS Animations: property <clip-path> from [path("M 5 5 q 0 80 10 10 c 20 50 25 70 30 20")] to [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] at (1.5) should be [shape(from calc(22.5% - 2.5px) 20px, curve by calc(30% - 5px) -5px with 15% 50px, curve by calc(30% - 15px) 35px with calc(45% - 10px) 35px / calc(-7.5% - 12.5px) 115px)] - assert_true: 'to' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( 22.5 % - 2.5px ) 20px , curve by calc ( 30 % - 5px ) - 5px with 15 % 50px , curve by calc ( 30 % - 15px ) 35px with calc ( 45 % - 10px ) 35px / calc ( - 7.5 % - 12.5px ) 115px ) " but got "shape ( from 15 % 15px , curve by 20 % 0px with 10 % 60px , curve by 20 % 30px with 30 % 40px / - 5 % 100px ) " [FAIL] Web Animations: property <clip-path> from [path("M 5 5 q 0 80 10 10 c 20 50 25 70 30 20")] to [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] at (-0.3) should be [shape(from calc(-4.5% + 6.5px) 2px, curve by calc(-6% + 13px) 13px with -3% 86px, curve by calc(-6% + 39px) 17px with calc(-9% + 26px) 53px / calc(1.5% + 32.5px) 61px)] - assert_true: 'to' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( - 4.5 % + 6.5px ) 2px , curve by calc ( - 6 % + 13px ) 13px with - 3 % 86px , curve by calc ( - 6 % + 39px ) 17px with calc ( - 9 % + 26px ) 53px / calc ( 1.5 % + 32.5px ) 61px ) " but got "path ( \\" M 5 5 Q 5 85 15 15 C 35 65 40 85 45 35 \\" ) " [FAIL] Web Animations: property <clip-path> from [path("M 5 5 q 0 80 10 10 c 20 50 25 70 30 20")] to [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] at (0) should be [shape(from calc(0% + 5px) 5px, curve by calc(0% + 10px) 10px with 0% 80px, curve by calc(0% + 30px) 20px with calc(0% + 20px) 50px / calc(0% + 25px) 70px)] - assert_true: 'to' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( 0 % + 5px ) 5px , curve by calc ( 0 % + 10px ) 10px with 0 % 80px , curve by calc ( 0 % + 30px ) 20px with calc ( 0 % + 20px ) 50px / calc ( 0 % + 25px ) 70px ) " but got "path ( \\" M 5 5 Q 5 85 15 15 C 35 65 40 85 45 35 \\" ) " [FAIL] Web Animations: property <clip-path> from [path("M 5 5 q 0 80 10 10 c 20 50 25 70 30 20")] to [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] at (0.5) should be [shape(from calc(7.5% + 2.5px) 10px, curve by calc(10% + 5px) 5px with 5% 70px, curve by calc(10% + 15px) 25px with calc(15% + 10px) 45px / calc(-2.5% + 12.5px) 85px)] - assert_true: 'to' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [path("M 5 5 q 0 80 10 10 c 20 50 25 70 30 20")] to [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] at (1) should be [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] - assert_true: 'to' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( 7.5 % + 2.5px ) 10px , curve by calc ( 10 % + 5px ) 5px with 5 % 70px , curve by calc ( 10 % + 15px ) 25px with calc ( 15 % + 10px ) 45px / calc ( - 2.5 % + 12.5px ) 85px ) " but got "shape ( from 15 % 15px , curve by 20 % 0px with 10 % 60px , curve by 20 % 30px with 30 % 40px / - 5 % 100px ) " [FAIL] Web Animations: property <clip-path> from [path("M 5 5 q 0 80 10 10 c 20 50 25 70 30 20")] to [shape(from 15% 15px, curve by 20% 0px with 10% 60px, curve by 20% 30px with 30% 40px / -5% 100px)] at (1.5) should be [shape(from calc(22.5% - 2.5px) 20px, curve by calc(30% - 5px) -5px with 15% 50px, curve by calc(30% - 15px) 35px with calc(45% - 10px) 35px / calc(-7.5% - 12.5px) 115px)] - assert_true: 'to' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( 22.5 % - 2.5px ) 20px , curve by calc ( 30 % - 5px ) - 5px with 15 % 50px , curve by calc ( 30 % - 15px ) 35px with calc ( 45 % - 10px ) 35px / calc ( - 7.5 % - 12.5px ) 115px ) " but got "shape ( from 15 % 15px , curve by 20 % 0px with 10 % 60px , curve by 20 % 30px with 30 % 40px / - 5 % 100px ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] to [path("M 15 15 S 10 60 20 0 T 20 30")] at (-0.3) should be [shape(from calc(6.5% - 4.5px) 2px, smooth to calc(13% - 6px) 13px with calc(0% - 3px) 86px, smooth to calc(39% - 6px) 17px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( 6.5 % - 4.5px ) 2px , smooth to calc ( 13 % - 6px ) 13px with calc ( 0 % - 3px ) 86px , smooth to calc ( 39 % - 6px ) 17px ) " but got "path ( \\" M 15 15 S 10 60 20 0 T 20 30 \\" ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] to [path("M 15 15 S 10 60 20 0 T 20 30")] at (0) should be [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 5 % 5px , smooth to 10 % 10px with 0 % 80px , smooth to 30 % 20px ) " but got "path ( \\" M 15 15 S 10 60 20 0 T 20 30 \\" ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] to [path("M 15 15 S 10 60 20 0 T 20 30")] at (0.5) should be [shape(from calc(2.5% + 7.5px) 10px, smooth to calc(5% + 10px) 5px with calc(0% + 5px) 70px, smooth to calc(15% + 10px) 25px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( 2.5 % + 7.5px ) 10px , smooth to calc ( 5 % + 10px ) 5px with calc ( 0 % + 5px ) 70px , smooth to calc ( 15 % + 10px ) 25px ) " but got "path ( \\" M 15 15 S 10 60 20 0 T 20 30 \\" ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] to [path("M 15 15 S 10 60 20 0 T 20 30")] at (1) should be [shape(from calc(0% + 15px) 15px, smooth to calc(0% + 20px) 0px with calc(0% + 10px) 60px, smooth to calc(0% + 20px) 30px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( 0 % + 15px ) 15px , smooth to calc ( 0 % + 20px ) 0px with calc ( 0 % + 10px ) 60px , smooth to calc ( 0 % + 20px ) 30px ) " but got "path ( \\" M 15 15 S 10 60 20 0 T 20 30 \\" ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] to [path("M 15 15 S 10 60 20 0 T 20 30")] at (1.5) should be [shape(from calc(-2.5% + 22.5px) 20px, smooth to calc(-5% + 30px) -5px with calc(0% + 15px) 50px, smooth to calc(-15% + 30px) 35px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( - 2.5 % + 22.5px ) 20px , smooth to calc ( - 5 % + 30px ) - 5px with calc ( 0 % + 15px ) 50px , smooth to calc ( - 15 % + 30px ) 35px ) " but got "path ( \\" M 15 15 S 10 60 20 0 T 20 30 \\" ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] to [path("M 15 15 S 10 60 20 0 T 20 30")] at (-0.3) should be [shape(from calc(6.5% - 4.5px) 2px, smooth to calc(13% - 6px) 13px with calc(0% - 3px) 86px, smooth to calc(39% - 6px) 17px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( 6.5 % - 4.5px ) 2px , smooth to calc ( 13 % - 6px ) 13px with calc ( 0 % - 3px ) 86px , smooth to calc ( 39 % - 6px ) 17px ) " but got "path ( \\" M 15 15 S 10 60 20 0 T 20 30 \\" ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] to [path("M 15 15 S 10 60 20 0 T 20 30")] at (0) should be [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from 5 % 5px , smooth to 10 % 10px with 0 % 80px , smooth to 30 % 20px ) " but got "path ( \\" M 15 15 S 10 60 20 0 T 20 30 \\" ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] to [path("M 15 15 S 10 60 20 0 T 20 30")] at (0.5) should be [shape(from calc(2.5% + 7.5px) 10px, smooth to calc(5% + 10px) 5px with calc(0% + 5px) 70px, smooth to calc(15% + 10px) 25px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( 2.5 % + 7.5px ) 10px , smooth to calc ( 5 % + 10px ) 5px with calc ( 0 % + 5px ) 70px , smooth to calc ( 15 % + 10px ) 25px ) " but got "path ( \\" M 15 15 S 10 60 20 0 T 20 30 \\" ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] to [path("M 15 15 S 10 60 20 0 T 20 30")] at (1) should be [shape(from calc(0% + 15px) 15px, smooth to calc(0% + 20px) 0px with calc(0% + 10px) 60px, smooth to calc(0% + 20px) 30px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( 0 % + 15px ) 15px , smooth to calc ( 0 % + 20px ) 0px with calc ( 0 % + 10px ) 60px , smooth to calc ( 0 % + 20px ) 30px ) " but got "path ( \\" M 15 15 S 10 60 20 0 T 20 30 \\" ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] to [path("M 15 15 S 10 60 20 0 T 20 30")] at (1.5) should be [shape(from calc(-2.5% + 22.5px) 20px, smooth to calc(-5% + 30px) -5px with calc(0% + 15px) 50px, smooth to calc(-15% + 30px) 35px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( - 2.5 % + 22.5px ) 20px , smooth to calc ( - 5 % + 30px ) - 5px with calc ( 0 % + 15px ) 50px , smooth to calc ( - 15 % + 30px ) 35px ) " but got "path ( \\" M 15 15 S 10 60 20 0 T 20 30 \\" ) " [FAIL] CSS Animations: property <clip-path> from [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] to [path("M 15 15 S 10 60 20 0 T 20 30")] at (-0.3) should be [shape(from calc(6.5% - 4.5px) 2px, smooth to calc(13% - 6px) 13px with calc(0% - 3px) 86px, smooth to calc(39% - 6px) 17px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] to [path("M 15 15 S 10 60 20 0 T 20 30")] at (0) should be [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( 6.5 % - 4.5px ) 2px , smooth to calc ( 13 % - 6px ) 13px with calc ( 0 % - 3px ) 86px , smooth to calc ( 39 % - 6px ) 17px ) " but got "shape ( from 5 % 5px , smooth to 10 % 10px with 0 % 80px , smooth to 30 % 20px ) " [FAIL] CSS Animations: property <clip-path> from [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] to [path("M 15 15 S 10 60 20 0 T 20 30")] at (0.5) should be [shape(from calc(2.5% + 7.5px) 10px, smooth to calc(5% + 10px) 5px with calc(0% + 5px) 70px, smooth to calc(15% + 10px) 25px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( 2.5 % + 7.5px ) 10px , smooth to calc ( 5 % + 10px ) 5px with calc ( 0 % + 5px ) 70px , smooth to calc ( 15 % + 10px ) 25px ) " but got "path ( \\" M 15 15 S 10 60 20 0 T 20 30 \\" ) " [FAIL] CSS Animations: property <clip-path> from [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] to [path("M 15 15 S 10 60 20 0 T 20 30")] at (1) should be [shape(from calc(0% + 15px) 15px, smooth to calc(0% + 20px) 0px with calc(0% + 10px) 60px, smooth to calc(0% + 20px) 30px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( 0 % + 15px ) 15px , smooth to calc ( 0 % + 20px ) 0px with calc ( 0 % + 10px ) 60px , smooth to calc ( 0 % + 20px ) 30px ) " but got "path ( \\" M 15 15 S 10 60 20 0 T 20 30 \\" ) " [FAIL] CSS Animations: property <clip-path> from [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] to [path("M 15 15 S 10 60 20 0 T 20 30")] at (1.5) should be [shape(from calc(-2.5% + 22.5px) 20px, smooth to calc(-5% + 30px) -5px with calc(0% + 15px) 50px, smooth to calc(-15% + 30px) 35px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( - 2.5 % + 22.5px ) 20px , smooth to calc ( - 5 % + 30px ) - 5px with calc ( 0 % + 15px ) 50px , smooth to calc ( - 15 % + 30px ) 35px ) " but got "path ( \\" M 15 15 S 10 60 20 0 T 20 30 \\" ) " [FAIL] Web Animations: property <clip-path> from [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] to [path("M 15 15 S 10 60 20 0 T 20 30")] at (-0.3) should be [shape(from calc(6.5% - 4.5px) 2px, smooth to calc(13% - 6px) 13px with calc(0% - 3px) 86px, smooth to calc(39% - 6px) 17px)] - assert_true: 'from' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] to [path("M 15 15 S 10 60 20 0 T 20 30")] at (0) should be [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( 6.5 % - 4.5px ) 2px , smooth to calc ( 13 % - 6px ) 13px with calc ( 0 % - 3px ) 86px , smooth to calc ( 39 % - 6px ) 17px ) " but got "shape ( from 5 % 5px , smooth to 10 % 10px with 0 % 80px , smooth to 30 % 20px ) " [FAIL] Web Animations: property <clip-path> from [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] to [path("M 15 15 S 10 60 20 0 T 20 30")] at (0.5) should be [shape(from calc(2.5% + 7.5px) 10px, smooth to calc(5% + 10px) 5px with calc(0% + 5px) 70px, smooth to calc(15% + 10px) 25px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( 2.5 % + 7.5px ) 10px , smooth to calc ( 5 % + 10px ) 5px with calc ( 0 % + 5px ) 70px , smooth to calc ( 15 % + 10px ) 25px ) " but got "path ( \\" M 15 15 S 10 60 20 0 T 20 30 \\" ) " [FAIL] Web Animations: property <clip-path> from [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] to [path("M 15 15 S 10 60 20 0 T 20 30")] at (1) should be [shape(from calc(0% + 15px) 15px, smooth to calc(0% + 20px) 0px with calc(0% + 10px) 60px, smooth to calc(0% + 20px) 30px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( 0 % + 15px ) 15px , smooth to calc ( 0 % + 20px ) 0px with calc ( 0 % + 10px ) 60px , smooth to calc ( 0 % + 20px ) 30px ) " but got "path ( \\" M 15 15 S 10 60 20 0 T 20 30 \\" ) " [FAIL] Web Animations: property <clip-path> from [shape(from 5% 5px, smooth to 10% 10px with 0% 80px, smooth to 30% 20px)] to [path("M 15 15 S 10 60 20 0 T 20 30")] at (1.5) should be [shape(from calc(-2.5% + 22.5px) 20px, smooth to calc(-5% + 30px) -5px with calc(0% + 15px) 50px, smooth to calc(-15% + 30px) 35px)] - assert_true: 'from' value should be supported expected true got false + assert_equals: expected "shape ( from calc ( - 2.5 % + 22.5px ) 20px , smooth to calc ( - 5 % + 30px ) - 5px with calc ( 0 % + 15px ) 50px , smooth to calc ( - 15 % + 30px ) 35px ) " but got "path ( \\" M 15 15 S 10 60 20 0 T 20 30 \\" ) " [FAIL] CSS Transitions: property <clip-path> from [path("M 5 5 s 0 80 10 10 t 30 20")] to [shape(from 15px 15px, smooth by 20px 0px with 10px 60px, smooth by 20px 30px)] at (-0.3) should be [shape(from 2px 2px, smooth by 7px 13px with -3px 86px, smooth by 33px 17px)] - assert_true: 'to' value should be supported expected true got false + assert_equals: expected "shape ( from 2px 2px , smooth by 7px 13px with - 3px 86px , smooth by 33px 17px ) " but got "shape ( from 15px 15px , smooth by 20px 0px with 10px 60px , smooth by 20px 30px ) " [FAIL] CSS Transitions: property <clip-path> from [path("M 5 5 s 0 80 10 10 t 30 20")] to [shape(from 15px 15px, smooth by 20px 0px with 10px 60px, smooth by 20px 30px)] at (0) should be [shape(from 5px 5px, smooth by 10px 10px with 0px 80px, smooth by 30px 20px)] - assert_true: 'to' value should be supported expected true got false + assert_equals: expected "shape ( from 5px 5px , smooth by 10px 10px with 0px 80px , smooth by 30px 20px ) " but got "shape ( from 15px 15px , smooth by 20px 0px with 10px 60px , smooth by 20px 30px ) " [FAIL] CSS Transitions: property <clip-path> from [path("M 5 5 s 0 80 10 10 t 30 20")] to [shape(from 15px 15px, smooth by 20px 0px with 10px 60px, smooth by 20px 30px)] at (0.5) should be [shape(from 10px 10px, smooth by 15px 5px with 5px 70px, smooth by 25px 25px)] - assert_true: 'to' value should be supported expected true got false -[FAIL] CSS Transitions: property <clip-path> from [path("M 5 5 s 0 80 10 10 t 30 20")] to [shape(from 15px 15px, smooth by 20px 0px with 10px 60px, smooth by 20px 30px)] at (1) should be [shape(from 15px 15px, smooth by 20px 0px with 10px 60px, smooth by 20px 30px)] - assert_true: 'to' value should be supported expected true got false + assert_equals: expected "shape ( from 10px 10px , smooth by 15px 5px with 5px 70px , smooth by 25px 25px ) " but got "shape ( from 15px 15px , smooth by 20px 0px with 10px 60px , smooth by 20px 30px ) " [FAIL] CSS Transitions: property <clip-path> from [path("M 5 5 s 0 80 10 10 t 30 20")] to [shape(from 15px 15px, smooth by 20px 0px with 10px 60px, smooth by 20px 30px)] at (1.5) should be [shape(from 20px 20px, smooth by 25px -5px with 15px 50px, smooth by 15px 35px)] - assert_true: 'to' value should be supported expected true got false + assert_equals: expected "shape ( from 20px 20px , smooth by 25px - 5px with 15px 50px , smooth by 15px 35px ) " but got "shape ( from 15px 15px , smooth by 20px 0px with 10px 60px , smooth by 20px 30px ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [path("M 5 5 s 0 80 10 10 t 30 20")] to [shape(from 15px 15px, smooth by 20px 0px with 10px 60px, smooth by 20px 30px)] at (-0.3) should be [shape(from 2px 2px, smooth by 7px 13px with -3px 86px, smooth by 33px 17px)] - assert_true: 'to' value should be supported expected true got false + assert_equals: expected "shape ( from 2px 2px , smooth by 7px 13px with - 3px 86px , smooth by 33px 17px ) " but got "shape ( from 15px 15px , smooth by 20px 0px with 10px 60px , smooth by 20px 30px ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [path("M 5 5 s 0 80 10 10 t 30 20")] to [shape(from 15px 15px, smooth by 20px 0px with 10px 60px, smooth by 20px 30px)] at (0) should be [shape(from 5px 5px, smooth by 10px 10px with 0px 80px, smooth by 30px 20px)] - assert_true: 'to' value should be supported expected true got false + assert_equals: expected "shape ( from 5px 5px , smooth by 10px 10px with 0px 80px , smooth by 30px 20px ) " but got "shape ( from 15px 15px , smooth by 20px 0px with 10px 60px , smooth by 20px 30px ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [path("M 5 5 s 0 80 10 10 t 30 20")] to [shape(from 15px 15px, smooth by 20px 0px with 10px 60px, smooth by 20px 30px)] at (0.5) should be [shape(from 10px 10px, smooth by 15px 5px with 5px 70px, smooth by 25px 25px)] - assert_true: 'to' value should be supported expected true got false -[FAIL] CSS Transitions with transition: all: property <clip-path> from [path("M 5 5 s 0 80 10 10 t 30 20")] to [shape(from 15px 15px, smooth by 20px 0px with 10px 60px, smooth by 20px 30px)] at (1) should be [shape(from 15px 15px, smooth by 20px 0px with 10px 60px, smooth by 20px 30px)] - assert_true: 'to' value should be supported expected true got false + assert_equals: expected "shape ( from 10px 10px , smooth by 15px 5px with 5px 70px , smooth by 25px 25px ) " but got "shape ( from 15px 15px , smooth by 20px 0px with 10px 60px , smooth by 20px 30px ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [path("M 5 5 s 0 80 10 10 t 30 20")] to [shape(from 15px 15px, smooth by 20px 0px with 10px 60px, smooth by 20px 30px)] at (1.5) should be [shape(from 20px 20px, smooth by 25px -5px with 15px 50px, smooth by 15px 35px)] - assert_true: 'to' value should be supported expected true got false + assert_equals: expected "shape ( from 20px 20px , smooth by 25px - 5px with 15px 50px , smooth by 15px 35px ) " but got "shape ( from 15px 15px , smooth by 20px 0px with 10px 60px , smooth by 20px 30px ) " [FAIL] CSS Animations: property <clip-path> from [path("M 5 5 s 0 80 10 10 t 30 20")] to [shape(from 15px 15px, smooth by 20px 0px with 10px 60px, smooth by 20px 30px)] at (-0.3) should be [shape(from 2px 2px, smooth by 7px 13px with -3px 86px, smooth by 33px 17px)] - assert_true: 'to' value should be supported expected true got false + assert_equals: expected "shape ( from 2px 2px , smooth by 7px 13px with - 3px 86px , smooth by 33px 17px ) " but got "path ( \\" M 5 5 S 5 85 15 15 T 45 35 \\" ) " [FAIL] CSS Animations: property <clip-path> from [path("M 5 5 s 0 80 10 10 t 30 20")] to [shape(from 15px 15px, smooth by 20px 0px with 10px 60px, smooth by 20px 30px)] at (0) should be [shape(from 5px 5px, smooth by 10px 10px with 0px 80px, smooth by 30px 20px)] - assert_true: 'to' value should be supported expected true got false + assert_equals: expected "shape ( from 5px 5px , smooth by 10px 10px with 0px 80px , smooth by 30px 20px ) " but got "path ( \\" M 5 5 S 5 85 15 15 T 45 35 \\" ) " [FAIL] CSS Animations: property <clip-path> from [path("M 5 5 s 0 80 10 10 t 30 20")] to [shape(from 15px 15px, smooth by 20px 0px with 10px 60px, smooth by 20px 30px)] at (0.5) should be [shape(from 10px 10px, smooth by 15px 5px with 5px 70px, smooth by 25px 25px)] - assert_true: 'to' value should be supported expected true got false -[FAIL] CSS Animations: property <clip-path> from [path("M 5 5 s 0 80 10 10 t 30 20")] to [shape(from 15px 15px, smooth by 20px 0px with 10px 60px, smooth by 20px 30px)] at (1) should be [shape(from 15px 15px, smooth by 20px 0px with 10px 60px, smooth by 20px 30px)] - assert_true: 'to' value should be supported expected true got false + assert_equals: expected "shape ( from 10px 10px , smooth by 15px 5px with 5px 70px , smooth by 25px 25px ) " but got "shape ( from 15px 15px , smooth by 20px 0px with 10px 60px , smooth by 20px 30px ) " [FAIL] CSS Animations: property <clip-path> from [path("M 5 5 s 0 80 10 10 t 30 20")] to [shape(from 15px 15px, smooth by 20px 0px with 10px 60px, smooth by 20px 30px)] at (1.5) should be [shape(from 20px 20px, smooth by 25px -5px with 15px 50px, smooth by 15px 35px)] - assert_true: 'to' value should be supported expected true got false + assert_equals: expected "shape ( from 20px 20px , smooth by 25px - 5px with 15px 50px , smooth by 15px 35px ) " but got "shape ( from 15px 15px , smooth by 20px 0px with 10px 60px , smooth by 20px 30px ) " [FAIL] Web Animations: property <clip-path> from [path("M 5 5 s 0 80 10 10 t 30 20")] to [shape(from 15px 15px, smooth by 20px 0px with 10px 60px, smooth by 20px 30px)] at (-0.3) should be [shape(from 2px 2px, smooth by 7px 13px with -3px 86px, smooth by 33px 17px)] - assert_true: 'to' value should be supported expected true got false + assert_equals: expected "shape ( from 2px 2px , smooth by 7px 13px with - 3px 86px , smooth by 33px 17px ) " but got "path ( \\" M 5 5 S 5 85 15 15 T 45 35 \\" ) " [FAIL] Web Animations: property <clip-path> from [path("M 5 5 s 0 80 10 10 t 30 20")] to [shape(from 15px 15px, smooth by 20px 0px with 10px 60px, smooth by 20px 30px)] at (0) should be [shape(from 5px 5px, smooth by 10px 10px with 0px 80px, smooth by 30px 20px)] - assert_true: 'to' value should be supported expected true got false + assert_equals: expected "shape ( from 5px 5px , smooth by 10px 10px with 0px 80px , smooth by 30px 20px ) " but got "path ( \\" M 5 5 S 5 85 15 15 T 45 35 \\" ) " [FAIL] Web Animations: property <clip-path> from [path("M 5 5 s 0 80 10 10 t 30 20")] to [shape(from 15px 15px, smooth by 20px 0px with 10px 60px, smooth by 20px 30px)] at (0.5) should be [shape(from 10px 10px, smooth by 15px 5px with 5px 70px, smooth by 25px 25px)] - assert_true: 'to' value should be supported expected true got false -[FAIL] Web Animations: property <clip-path> from [path("M 5 5 s 0 80 10 10 t 30 20")] to [shape(from 15px 15px, smooth by 20px 0px with 10px 60px, smooth by 20px 30px)] at (1) should be [shape(from 15px 15px, smooth by 20px 0px with 10px 60px, smooth by 20px 30px)] - assert_true: 'to' value should be supported expected true got false + assert_equals: expected "shape ( from 10px 10px , smooth by 15px 5px with 5px 70px , smooth by 25px 25px ) " but got "shape ( from 15px 15px , smooth by 20px 0px with 10px 60px , smooth by 20px 30px ) " [FAIL] Web Animations: property <clip-path> from [path("M 5 5 s 0 80 10 10 t 30 20")] to [shape(from 15px 15px, smooth by 20px 0px with 10px 60px, smooth by 20px 30px)] at (1.5) should be [shape(from 20px 20px, smooth by 25px -5px with 15px 50px, smooth by 15px 35px)] - assert_true: 'to' value should be supported expected true got false + assert_equals: expected "shape ( from 20px 20px , smooth by 25px - 5px with 15px 50px , smooth by 15px 35px ) " but got "shape ( from 15px 15px , smooth by 20px 0px with 10px 60px , smooth by 20px 30px ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] to [path("M 15 15 A 20,30 0 0,0 5,-25 a 20,20 270 0,1 25,-15 A 10,5 0 0,0 25 20")] at (-0.3) should be [shape(from calc(6.5% - 4.5px) 2px, arc to calc(19.5% - 1.5px) -12px of 7px 17px, arc by calc(19.5% - 7.5px) -2px of 33px cw large rotate -42deg, arc to calc(32.5% - 7.5px) 20px of 10px 5px)] - assert_equals: expected "shape ( from calc ( 6.5 % - 4.5px ) 2px , arc to calc ( 19.5 % - 1.5px ) - 12px of 7px 17px , arc by calc ( 19.5 % - 7.5px ) - 2px of 33px rotate - 42deg , arc to calc ( 32.5 % - 7.5px ) 20px of 10px 5px ) " but got "path ( \\" M 15 15 A 20 30 0 0 0 5 - 25 A 20 20 270 0 1 30 - 40 A 10 5 0 0 0 25 20 \\" ) " + assert_equals: expected "shape ( from calc ( 6.5 % - 4.5px ) 2px , arc to calc ( 19.5 % - 1.5px ) - 12px of 7px 17px , arc by calc ( 19.5 % - 7.5px ) - 2px of 33px cw large rotate - 42deg , arc to calc ( 32.5 % - 7.5px ) 20px of 10px 5px ) " but got "path ( \\" M 15 15 A 20 30 0 0 0 5 - 25 A 20 20 270 0 1 30 - 40 A 10 5 0 0 0 25 20 \\" ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] to [path("M 15 15 A 20,30 0 0,0 5,-25 a 20,20 270 0,1 25,-15 A 10,5 0 0,0 25 20")] at (0) should be [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] - assert_equals: expected "shape ( from 5 % 5px , arc to 15 % - 15px of 10px 20px , arc by 15 % - 5px of 30px rotate 30deg , arc to 25 % 20px of 10px 5px ) " but got "path ( \\" M 15 15 A 20 30 0 0 0 5 - 25 A 20 20 270 0 1 30 - 40 A 10 5 0 0 0 25 20 \\" ) " + assert_equals: expected "shape ( from 5 % 5px , arc to 15 % - 15px of 10px 20px , arc by 15 % - 5px of 30px cw large rotate 30deg , arc to 25 % 20px of 10px 5px ) " but got "path ( \\" M 15 15 A 20 30 0 0 0 5 - 25 A 20 20 270 0 1 30 - 40 A 10 5 0 0 0 25 20 \\" ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] to [path("M 15 15 A 20,30 0 0,0 5,-25 a 20,20 270 0,1 25,-15 A 10,5 0 0,0 25 20")] at (0.3) should be [shape(from calc(3.5% + 4.5px) 8px, arc to calc(10.5% + 1.5px) -18px of 13px 23px, arc by calc(10.5% + 7.5px) -8px of 27px cw large rotate 102deg, arc to calc(17.5% + 7.5px) 20px of 10px 5px)] - assert_equals: expected "shape ( from calc ( 3.5 % + 4.5px ) 8px , arc to calc ( 10.5 % + 1.5px ) - 18px of 13px 23px , arc by calc ( 10.5 % + 7.5px ) - 8px of 27px rotate 102deg , arc to calc ( 17.5 % + 7.5px ) 20px of 10px 5px ) " but got "path ( \\" M 15 15 A 20 30 0 0 0 5 - 25 A 20 20 270 0 1 30 - 40 A 10 5 0 0 0 25 20 \\" ) " + assert_equals: expected "shape ( from calc ( 3.5 % + 4.5px ) 8px , arc to calc ( 10.5 % + 1.5px ) - 18px of 13px 23px , arc by calc ( 10.5 % + 7.5px ) - 8px of 27px cw large rotate 102deg , arc to calc ( 17.5 % + 7.5px ) 20px of 10px 5px ) " but got "path ( \\" M 15 15 A 20 30 0 0 0 5 - 25 A 20 20 270 0 1 30 - 40 A 10 5 0 0 0 25 20 \\" ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] to [path("M 15 15 A 20,30 0 0,0 5,-25 a 20,20 270 0,1 25,-15 A 10,5 0 0,0 25 20")] at (0.5) should be [shape(from calc(2.5% + 7.5px) 10px, arc to calc(7.5% + 2.5px) -20px of 15px 25px, arc by calc(7.5% + 12.5px) -10px of 25px cw large rotate 150deg, arc to calc(12.5% + 12.5px) 20px of 10px 5px)] - assert_equals: expected "shape ( from calc ( 2.5 % + 7.5px ) 10px , arc to calc ( 7.5 % + 2.5px ) - 20px of 15px 25px , arc by calc ( 7.5 % + 12.5px ) - 10px of 25px rotate 150deg , arc to calc ( 12.5 % + 12.5px ) 20px of 10px 5px ) " but got "path ( \\" M 15 15 A 20 30 0 0 0 5 - 25 A 20 20 270 0 1 30 - 40 A 10 5 0 0 0 25 20 \\" ) " + assert_equals: expected "shape ( from calc ( 2.5 % + 7.5px ) 10px , arc to calc ( 7.5 % + 2.5px ) - 20px of 15px 25px , arc by calc ( 7.5 % + 12.5px ) - 10px of 25px cw large rotate 150deg , arc to calc ( 12.5 % + 12.5px ) 20px of 10px 5px ) " but got "path ( \\" M 15 15 A 20 30 0 0 0 5 - 25 A 20 20 270 0 1 30 - 40 A 10 5 0 0 0 25 20 \\" ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] to [path("M 15 15 A 20,30 0 0,0 5,-25 a 20,20 270 0,1 25,-15 A 10,5 0 0,0 25 20")] at (1) should be [shape(from calc(0% + 15px) 15px, arc to calc(0% + 5px) -25px of 20px 30px, arc by calc(0% + 25px) -15px of 20px cw rotate 270deg, arc to calc(0% + 25px) 20px of 10px 5px)] - assert_equals: expected "shape ( from calc ( 0 % + 15px ) 15px , arc to calc ( 0 % + 5px ) - 25px of 20px 30px , arc by calc ( 0 % + 25px ) - 15px of 20px rotate 270deg , arc to calc ( 0 % + 25px ) 20px of 10px 5px ) " but got "path ( \\" M 15 15 A 20 30 0 0 0 5 - 25 A 20 20 270 0 1 30 - 40 A 10 5 0 0 0 25 20 \\" ) " + assert_equals: expected "shape ( from calc ( 0 % + 15px ) 15px , arc to calc ( 0 % + 5px ) - 25px of 20px 30px , arc by calc ( 0 % + 25px ) - 15px of 20px cw rotate 270deg , arc to calc ( 0 % + 25px ) 20px of 10px 5px ) " but got "path ( \\" M 15 15 A 20 30 0 0 0 5 - 25 A 20 20 270 0 1 30 - 40 A 10 5 0 0 0 25 20 \\" ) " [FAIL] CSS Transitions: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] to [path("M 15 15 A 20,30 0 0,0 5,-25 a 20,20 270 0,1 25,-15 A 10,5 0 0,0 25 20")] at (1.5) should be [shape(from calc(-2.5% + 22.5px) 20px, arc to calc(-7.5% + 7.5px) -30px of 25px 35px, arc by calc(-7.5% + 37.5px) -20px of 15px cw rotate 390deg, arc to calc(-12.5% + 37.5px) 20px of 10px 5px)] - assert_equals: expected "shape ( from calc ( - 2.5 % + 22.5px ) 20px , arc to calc ( - 7.5 % + 7.5px ) - 30px of 25px 35px , arc by calc ( - 7.5 % + 37.5px ) - 20px of 15px rotate 390deg , arc to calc ( - 12.5 % + 37.5px ) 20px of 10px 5px ) " but got "path ( \\" M 15 15 A 20 30 0 0 0 5 - 25 A 20 20 270 0 1 30 - 40 A 10 5 0 0 0 25 20 \\" ) " + assert_equals: expected "shape ( from calc ( - 2.5 % + 22.5px ) 20px , arc to calc ( - 7.5 % + 7.5px ) - 30px of 25px 35px , arc by calc ( - 7.5 % + 37.5px ) - 20px of 15px cw rotate 390deg , arc to calc ( - 12.5 % + 37.5px ) 20px of 10px 5px ) " but got "path ( \\" M 15 15 A 20 30 0 0 0 5 - 25 A 20 20 270 0 1 30 - 40 A 10 5 0 0 0 25 20 \\" ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] to [path("M 15 15 A 20,30 0 0,0 5,-25 a 20,20 270 0,1 25,-15 A 10,5 0 0,0 25 20")] at (-0.3) should be [shape(from calc(6.5% - 4.5px) 2px, arc to calc(19.5% - 1.5px) -12px of 7px 17px, arc by calc(19.5% - 7.5px) -2px of 33px cw large rotate -42deg, arc to calc(32.5% - 7.5px) 20px of 10px 5px)] - assert_equals: expected "shape ( from calc ( 6.5 % - 4.5px ) 2px , arc to calc ( 19.5 % - 1.5px ) - 12px of 7px 17px , arc by calc ( 19.5 % - 7.5px ) - 2px of 33px rotate - 42deg , arc to calc ( 32.5 % - 7.5px ) 20px of 10px 5px ) " but got "path ( \\" M 15 15 A 20 30 0 0 0 5 - 25 A 20 20 270 0 1 30 - 40 A 10 5 0 0 0 25 20 \\" ) " + assert_equals: expected "shape ( from calc ( 6.5 % - 4.5px ) 2px , arc to calc ( 19.5 % - 1.5px ) - 12px of 7px 17px , arc by calc ( 19.5 % - 7.5px ) - 2px of 33px cw large rotate - 42deg , arc to calc ( 32.5 % - 7.5px ) 20px of 10px 5px ) " but got "path ( \\" M 15 15 A 20 30 0 0 0 5 - 25 A 20 20 270 0 1 30 - 40 A 10 5 0 0 0 25 20 \\" ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] to [path("M 15 15 A 20,30 0 0,0 5,-25 a 20,20 270 0,1 25,-15 A 10,5 0 0,0 25 20")] at (0) should be [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] - assert_equals: expected "shape ( from 5 % 5px , arc to 15 % - 15px of 10px 20px , arc by 15 % - 5px of 30px rotate 30deg , arc to 25 % 20px of 10px 5px ) " but got "path ( \\" M 15 15 A 20 30 0 0 0 5 - 25 A 20 20 270 0 1 30 - 40 A 10 5 0 0 0 25 20 \\" ) " + assert_equals: expected "shape ( from 5 % 5px , arc to 15 % - 15px of 10px 20px , arc by 15 % - 5px of 30px cw large rotate 30deg , arc to 25 % 20px of 10px 5px ) " but got "path ( \\" M 15 15 A 20 30 0 0 0 5 - 25 A 20 20 270 0 1 30 - 40 A 10 5 0 0 0 25 20 \\" ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] to [path("M 15 15 A 20,30 0 0,0 5,-25 a 20,20 270 0,1 25,-15 A 10,5 0 0,0 25 20")] at (0.3) should be [shape(from calc(3.5% + 4.5px) 8px, arc to calc(10.5% + 1.5px) -18px of 13px 23px, arc by calc(10.5% + 7.5px) -8px of 27px cw large rotate 102deg, arc to calc(17.5% + 7.5px) 20px of 10px 5px)] - assert_equals: expected "shape ( from calc ( 3.5 % + 4.5px ) 8px , arc to calc ( 10.5 % + 1.5px ) - 18px of 13px 23px , arc by calc ( 10.5 % + 7.5px ) - 8px of 27px rotate 102deg , arc to calc ( 17.5 % + 7.5px ) 20px of 10px 5px ) " but got "path ( \\" M 15 15 A 20 30 0 0 0 5 - 25 A 20 20 270 0 1 30 - 40 A 10 5 0 0 0 25 20 \\" ) " + assert_equals: expected "shape ( from calc ( 3.5 % + 4.5px ) 8px , arc to calc ( 10.5 % + 1.5px ) - 18px of 13px 23px , arc by calc ( 10.5 % + 7.5px ) - 8px of 27px cw large rotate 102deg , arc to calc ( 17.5 % + 7.5px ) 20px of 10px 5px ) " but got "path ( \\" M 15 15 A 20 30 0 0 0 5 - 25 A 20 20 270 0 1 30 - 40 A 10 5 0 0 0 25 20 \\" ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] to [path("M 15 15 A 20,30 0 0,0 5,-25 a 20,20 270 0,1 25,-15 A 10,5 0 0,0 25 20")] at (0.5) should be [shape(from calc(2.5% + 7.5px) 10px, arc to calc(7.5% + 2.5px) -20px of 15px 25px, arc by calc(7.5% + 12.5px) -10px of 25px cw large rotate 150deg, arc to calc(12.5% + 12.5px) 20px of 10px 5px)] - assert_equals: expected "shape ( from calc ( 2.5 % + 7.5px ) 10px , arc to calc ( 7.5 % + 2.5px ) - 20px of 15px 25px , arc by calc ( 7.5 % + 12.5px ) - 10px of 25px rotate 150deg , arc to calc ( 12.5 % + 12.5px ) 20px of 10px 5px ) " but got "path ( \\" M 15 15 A 20 30 0 0 0 5 - 25 A 20 20 270 0 1 30 - 40 A 10 5 0 0 0 25 20 \\" ) " + assert_equals: expected "shape ( from calc ( 2.5 % + 7.5px ) 10px , arc to calc ( 7.5 % + 2.5px ) - 20px of 15px 25px , arc by calc ( 7.5 % + 12.5px ) - 10px of 25px cw large rotate 150deg , arc to calc ( 12.5 % + 12.5px ) 20px of 10px 5px ) " but got "path ( \\" M 15 15 A 20 30 0 0 0 5 - 25 A 20 20 270 0 1 30 - 40 A 10 5 0 0 0 25 20 \\" ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] to [path("M 15 15 A 20,30 0 0,0 5,-25 a 20,20 270 0,1 25,-15 A 10,5 0 0,0 25 20")] at (1) should be [shape(from calc(0% + 15px) 15px, arc to calc(0% + 5px) -25px of 20px 30px, arc by calc(0% + 25px) -15px of 20px cw rotate 270deg, arc to calc(0% + 25px) 20px of 10px 5px)] - assert_equals: expected "shape ( from calc ( 0 % + 15px ) 15px , arc to calc ( 0 % + 5px ) - 25px of 20px 30px , arc by calc ( 0 % + 25px ) - 15px of 20px rotate 270deg , arc to calc ( 0 % + 25px ) 20px of 10px 5px ) " but got "path ( \\" M 15 15 A 20 30 0 0 0 5 - 25 A 20 20 270 0 1 30 - 40 A 10 5 0 0 0 25 20 \\" ) " + assert_equals: expected "shape ( from calc ( 0 % + 15px ) 15px , arc to calc ( 0 % + 5px ) - 25px of 20px 30px , arc by calc ( 0 % + 25px ) - 15px of 20px cw rotate 270deg , arc to calc ( 0 % + 25px ) 20px of 10px 5px ) " but got "path ( \\" M 15 15 A 20 30 0 0 0 5 - 25 A 20 20 270 0 1 30 - 40 A 10 5 0 0 0 25 20 \\" ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] to [path("M 15 15 A 20,30 0 0,0 5,-25 a 20,20 270 0,1 25,-15 A 10,5 0 0,0 25 20")] at (1.5) should be [shape(from calc(-2.5% + 22.5px) 20px, arc to calc(-7.5% + 7.5px) -30px of 25px 35px, arc by calc(-7.5% + 37.5px) -20px of 15px cw rotate 390deg, arc to calc(-12.5% + 37.5px) 20px of 10px 5px)] - assert_equals: expected "shape ( from calc ( - 2.5 % + 22.5px ) 20px , arc to calc ( - 7.5 % + 7.5px ) - 30px of 25px 35px , arc by calc ( - 7.5 % + 37.5px ) - 20px of 15px rotate 390deg , arc to calc ( - 12.5 % + 37.5px ) 20px of 10px 5px ) " but got "path ( \\" M 15 15 A 20 30 0 0 0 5 - 25 A 20 20 270 0 1 30 - 40 A 10 5 0 0 0 25 20 \\" ) " + assert_equals: expected "shape ( from calc ( - 2.5 % + 22.5px ) 20px , arc to calc ( - 7.5 % + 7.5px ) - 30px of 25px 35px , arc by calc ( - 7.5 % + 37.5px ) - 20px of 15px cw rotate 390deg , arc to calc ( - 12.5 % + 37.5px ) 20px of 10px 5px ) " but got "path ( \\" M 15 15 A 20 30 0 0 0 5 - 25 A 20 20 270 0 1 30 - 40 A 10 5 0 0 0 25 20 \\" ) " [FAIL] CSS Animations: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] to [path("M 15 15 A 20,30 0 0,0 5,-25 a 20,20 270 0,1 25,-15 A 10,5 0 0,0 25 20")] at (-0.3) should be [shape(from calc(6.5% - 4.5px) 2px, arc to calc(19.5% - 1.5px) -12px of 7px 17px, arc by calc(19.5% - 7.5px) -2px of 33px cw large rotate -42deg, arc to calc(32.5% - 7.5px) 20px of 10px 5px)] - assert_equals: expected "shape ( from calc ( 6.5 % - 4.5px ) 2px , arc to calc ( 19.5 % - 1.5px ) - 12px of 7px 17px , arc by calc ( 19.5 % - 7.5px ) - 2px of 33px rotate - 42deg , arc to calc ( 32.5 % - 7.5px ) 20px of 10px 5px ) " but got "shape ( from 5 % 5px , arc to 15 % - 15px of 10px 20px , arc by 15 % - 5px of 30px rotate 30deg , arc to 25 % 20px of 10px 5px ) " + assert_equals: expected "shape ( from calc ( 6.5 % - 4.5px ) 2px , arc to calc ( 19.5 % - 1.5px ) - 12px of 7px 17px , arc by calc ( 19.5 % - 7.5px ) - 2px of 33px cw large rotate - 42deg , arc to calc ( 32.5 % - 7.5px ) 20px of 10px 5px ) " but got "shape ( from 5 % 5px , arc to 15 % - 15px of 10px 20px , arc by 15 % - 5px of 30px cw large rotate 30deg , arc to 25 % 20px of 10px 5px ) " [FAIL] CSS Animations: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] to [path("M 15 15 A 20,30 0 0,0 5,-25 a 20,20 270 0,1 25,-15 A 10,5 0 0,0 25 20")] at (0.3) should be [shape(from calc(3.5% + 4.5px) 8px, arc to calc(10.5% + 1.5px) -18px of 13px 23px, arc by calc(10.5% + 7.5px) -8px of 27px cw large rotate 102deg, arc to calc(17.5% + 7.5px) 20px of 10px 5px)] - assert_equals: expected "shape ( from calc ( 3.5 % + 4.5px ) 8px , arc to calc ( 10.5 % + 1.5px ) - 18px of 13px 23px , arc by calc ( 10.5 % + 7.5px ) - 8px of 27px rotate 102deg , arc to calc ( 17.5 % + 7.5px ) 20px of 10px 5px ) " but got "shape ( from 5 % 5px , arc to 15 % - 15px of 10px 20px , arc by 15 % - 5px of 30px rotate 30deg , arc to 25 % 20px of 10px 5px ) " + assert_equals: expected "shape ( from calc ( 3.5 % + 4.5px ) 8px , arc to calc ( 10.5 % + 1.5px ) - 18px of 13px 23px , arc by calc ( 10.5 % + 7.5px ) - 8px of 27px cw large rotate 102deg , arc to calc ( 17.5 % + 7.5px ) 20px of 10px 5px ) " but got "shape ( from 5 % 5px , arc to 15 % - 15px of 10px 20px , arc by 15 % - 5px of 30px cw large rotate 30deg , arc to 25 % 20px of 10px 5px ) " [FAIL] CSS Animations: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] to [path("M 15 15 A 20,30 0 0,0 5,-25 a 20,20 270 0,1 25,-15 A 10,5 0 0,0 25 20")] at (0.5) should be [shape(from calc(2.5% + 7.5px) 10px, arc to calc(7.5% + 2.5px) -20px of 15px 25px, arc by calc(7.5% + 12.5px) -10px of 25px cw large rotate 150deg, arc to calc(12.5% + 12.5px) 20px of 10px 5px)] - assert_equals: expected "shape ( from calc ( 2.5 % + 7.5px ) 10px , arc to calc ( 7.5 % + 2.5px ) - 20px of 15px 25px , arc by calc ( 7.5 % + 12.5px ) - 10px of 25px rotate 150deg , arc to calc ( 12.5 % + 12.5px ) 20px of 10px 5px ) " but got "path ( \\" M 15 15 A 20 30 0 0 0 5 - 25 A 20 20 270 0 1 30 - 40 A 10 5 0 0 0 25 20 \\" ) " + assert_equals: expected "shape ( from calc ( 2.5 % + 7.5px ) 10px , arc to calc ( 7.5 % + 2.5px ) - 20px of 15px 25px , arc by calc ( 7.5 % + 12.5px ) - 10px of 25px cw large rotate 150deg , arc to calc ( 12.5 % + 12.5px ) 20px of 10px 5px ) " but got "path ( \\" M 15 15 A 20 30 0 0 0 5 - 25 A 20 20 270 0 1 30 - 40 A 10 5 0 0 0 25 20 \\" ) " [FAIL] CSS Animations: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] to [path("M 15 15 A 20,30 0 0,0 5,-25 a 20,20 270 0,1 25,-15 A 10,5 0 0,0 25 20")] at (1) should be [shape(from calc(0% + 15px) 15px, arc to calc(0% + 5px) -25px of 20px 30px, arc by calc(0% + 25px) -15px of 20px cw rotate 270deg, arc to calc(0% + 25px) 20px of 10px 5px)] - assert_equals: expected "shape ( from calc ( 0 % + 15px ) 15px , arc to calc ( 0 % + 5px ) - 25px of 20px 30px , arc by calc ( 0 % + 25px ) - 15px of 20px rotate 270deg , arc to calc ( 0 % + 25px ) 20px of 10px 5px ) " but got "path ( \\" M 15 15 A 20 30 0 0 0 5 - 25 A 20 20 270 0 1 30 - 40 A 10 5 0 0 0 25 20 \\" ) " + assert_equals: expected "shape ( from calc ( 0 % + 15px ) 15px , arc to calc ( 0 % + 5px ) - 25px of 20px 30px , arc by calc ( 0 % + 25px ) - 15px of 20px cw rotate 270deg , arc to calc ( 0 % + 25px ) 20px of 10px 5px ) " but got "path ( \\" M 15 15 A 20 30 0 0 0 5 - 25 A 20 20 270 0 1 30 - 40 A 10 5 0 0 0 25 20 \\" ) " [FAIL] CSS Animations: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] to [path("M 15 15 A 20,30 0 0,0 5,-25 a 20,20 270 0,1 25,-15 A 10,5 0 0,0 25 20")] at (1.5) should be [shape(from calc(-2.5% + 22.5px) 20px, arc to calc(-7.5% + 7.5px) -30px of 25px 35px, arc by calc(-7.5% + 37.5px) -20px of 15px cw rotate 390deg, arc to calc(-12.5% + 37.5px) 20px of 10px 5px)] - assert_equals: expected "shape ( from calc ( - 2.5 % + 22.5px ) 20px , arc to calc ( - 7.5 % + 7.5px ) - 30px of 25px 35px , arc by calc ( - 7.5 % + 37.5px ) - 20px of 15px rotate 390deg , arc to calc ( - 12.5 % + 37.5px ) 20px of 10px 5px ) " but got "path ( \\" M 15 15 A 20 30 0 0 0 5 - 25 A 20 20 270 0 1 30 - 40 A 10 5 0 0 0 25 20 \\" ) " + assert_equals: expected "shape ( from calc ( - 2.5 % + 22.5px ) 20px , arc to calc ( - 7.5 % + 7.5px ) - 30px of 25px 35px , arc by calc ( - 7.5 % + 37.5px ) - 20px of 15px cw rotate 390deg , arc to calc ( - 12.5 % + 37.5px ) 20px of 10px 5px ) " but got "path ( \\" M 15 15 A 20 30 0 0 0 5 - 25 A 20 20 270 0 1 30 - 40 A 10 5 0 0 0 25 20 \\" ) " [FAIL] Web Animations: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] to [path("M 15 15 A 20,30 0 0,0 5,-25 a 20,20 270 0,1 25,-15 A 10,5 0 0,0 25 20")] at (-0.3) should be [shape(from calc(6.5% - 4.5px) 2px, arc to calc(19.5% - 1.5px) -12px of 7px 17px, arc by calc(19.5% - 7.5px) -2px of 33px cw large rotate -42deg, arc to calc(32.5% - 7.5px) 20px of 10px 5px)] - assert_equals: expected "shape ( from calc ( 6.5 % - 4.5px ) 2px , arc to calc ( 19.5 % - 1.5px ) - 12px of 7px 17px , arc by calc ( 19.5 % - 7.5px ) - 2px of 33px rotate - 42deg , arc to calc ( 32.5 % - 7.5px ) 20px of 10px 5px ) " but got "shape ( from 5 % 5px , arc to 15 % - 15px of 10px 20px , arc by 15 % - 5px of 30px rotate 30deg , arc to 25 % 20px of 10px 5px ) " + assert_equals: expected "shape ( from calc ( 6.5 % - 4.5px ) 2px , arc to calc ( 19.5 % - 1.5px ) - 12px of 7px 17px , arc by calc ( 19.5 % - 7.5px ) - 2px of 33px cw large rotate - 42deg , arc to calc ( 32.5 % - 7.5px ) 20px of 10px 5px ) " but got "shape ( from 5 % 5px , arc to 15 % - 15px of 10px 20px , arc by 15 % - 5px of 30px cw large rotate 30deg , arc to 25 % 20px of 10px 5px ) " [FAIL] Web Animations: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] to [path("M 15 15 A 20,30 0 0,0 5,-25 a 20,20 270 0,1 25,-15 A 10,5 0 0,0 25 20")] at (0.3) should be [shape(from calc(3.5% + 4.5px) 8px, arc to calc(10.5% + 1.5px) -18px of 13px 23px, arc by calc(10.5% + 7.5px) -8px of 27px cw large rotate 102deg, arc to calc(17.5% + 7.5px) 20px of 10px 5px)] - assert_equals: expected "shape ( from calc ( 3.5 % + 4.5px ) 8px , arc to calc ( 10.5 % + 1.5px ) - 18px of 13px 23px , arc by calc ( 10.5 % + 7.5px ) - 8px of 27px rotate 102deg , arc to calc ( 17.5 % + 7.5px ) 20px of 10px 5px ) " but got "shape ( from 5 % 5px , arc to 15 % - 15px of 10px 20px , arc by 15 % - 5px of 30px rotate 30deg , arc to 25 % 20px of 10px 5px ) " + assert_equals: expected "shape ( from calc ( 3.5 % + 4.5px ) 8px , arc to calc ( 10.5 % + 1.5px ) - 18px of 13px 23px , arc by calc ( 10.5 % + 7.5px ) - 8px of 27px cw large rotate 102deg , arc to calc ( 17.5 % + 7.5px ) 20px of 10px 5px ) " but got "shape ( from 5 % 5px , arc to 15 % - 15px of 10px 20px , arc by 15 % - 5px of 30px cw large rotate 30deg , arc to 25 % 20px of 10px 5px ) " [FAIL] Web Animations: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] to [path("M 15 15 A 20,30 0 0,0 5,-25 a 20,20 270 0,1 25,-15 A 10,5 0 0,0 25 20")] at (0.5) should be [shape(from calc(2.5% + 7.5px) 10px, arc to calc(7.5% + 2.5px) -20px of 15px 25px, arc by calc(7.5% + 12.5px) -10px of 25px cw large rotate 150deg, arc to calc(12.5% + 12.5px) 20px of 10px 5px)] - assert_equals: expected "shape ( from calc ( 2.5 % + 7.5px ) 10px , arc to calc ( 7.5 % + 2.5px ) - 20px of 15px 25px , arc by calc ( 7.5 % + 12.5px ) - 10px of 25px rotate 150deg , arc to calc ( 12.5 % + 12.5px ) 20px of 10px 5px ) " but got "path ( \\" M 15 15 A 20 30 0 0 0 5 - 25 A 20 20 270 0 1 30 - 40 A 10 5 0 0 0 25 20 \\" ) " + assert_equals: expected "shape ( from calc ( 2.5 % + 7.5px ) 10px , arc to calc ( 7.5 % + 2.5px ) - 20px of 15px 25px , arc by calc ( 7.5 % + 12.5px ) - 10px of 25px cw large rotate 150deg , arc to calc ( 12.5 % + 12.5px ) 20px of 10px 5px ) " but got "path ( \\" M 15 15 A 20 30 0 0 0 5 - 25 A 20 20 270 0 1 30 - 40 A 10 5 0 0 0 25 20 \\" ) " [FAIL] Web Animations: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] to [path("M 15 15 A 20,30 0 0,0 5,-25 a 20,20 270 0,1 25,-15 A 10,5 0 0,0 25 20")] at (1) should be [shape(from calc(0% + 15px) 15px, arc to calc(0% + 5px) -25px of 20px 30px, arc by calc(0% + 25px) -15px of 20px cw rotate 270deg, arc to calc(0% + 25px) 20px of 10px 5px)] - assert_equals: expected "shape ( from calc ( 0 % + 15px ) 15px , arc to calc ( 0 % + 5px ) - 25px of 20px 30px , arc by calc ( 0 % + 25px ) - 15px of 20px rotate 270deg , arc to calc ( 0 % + 25px ) 20px of 10px 5px ) " but got "path ( \\" M 15 15 A 20 30 0 0 0 5 - 25 A 20 20 270 0 1 30 - 40 A 10 5 0 0 0 25 20 \\" ) " + assert_equals: expected "shape ( from calc ( 0 % + 15px ) 15px , arc to calc ( 0 % + 5px ) - 25px of 20px 30px , arc by calc ( 0 % + 25px ) - 15px of 20px cw rotate 270deg , arc to calc ( 0 % + 25px ) 20px of 10px 5px ) " but got "path ( \\" M 15 15 A 20 30 0 0 0 5 - 25 A 20 20 270 0 1 30 - 40 A 10 5 0 0 0 25 20 \\" ) " [FAIL] Web Animations: property <clip-path> from [shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)] to [path("M 15 15 A 20,30 0 0,0 5,-25 a 20,20 270 0,1 25,-15 A 10,5 0 0,0 25 20")] at (1.5) should be [shape(from calc(-2.5% + 22.5px) 20px, arc to calc(-7.5% + 7.5px) -30px of 25px 35px, arc by calc(-7.5% + 37.5px) -20px of 15px cw rotate 390deg, arc to calc(-12.5% + 37.5px) 20px of 10px 5px)] - assert_equals: expected "shape ( from calc ( - 2.5 % + 22.5px ) 20px , arc to calc ( - 7.5 % + 7.5px ) - 30px of 25px 35px , arc by calc ( - 7.5 % + 37.5px ) - 20px of 15px rotate 390deg , arc to calc ( - 12.5 % + 37.5px ) 20px of 10px 5px ) " but got "path ( \\" M 15 15 A 20 30 0 0 0 5 - 25 A 20 20 270 0 1 30 - 40 A 10 5 0 0 0 25 20 \\" ) " + assert_equals: expected "shape ( from calc ( - 2.5 % + 22.5px ) 20px , arc to calc ( - 7.5 % + 7.5px ) - 30px of 25px 35px , arc by calc ( - 7.5 % + 37.5px ) - 20px of 15px cw rotate 390deg , arc to calc ( - 12.5 % + 37.5px ) 20px of 10px 5px ) " but got "path ( \\" M 15 15 A 20 30 0 0 0 5 - 25 A 20 20 270 0 1 30 - 40 A 10 5 0 0 0 25 20 \\" ) " [FAIL] CSS Transitions: property <clip-path> from [path("M 5 5 A 10,20 0 0,0 15,-15 a 30,30 30 1,1 15,-5 A 10,5 0 0,0 25 20")] to [shape(from 15px 15px, arc to 5px -25px of 20px 30px, arc by 25px -15px of 20px cw rotate 270deg small, arc to 25px 20px of 10px 5px small cw)] at (-0.3) should be [shape(from 2px 2px, arc to 18px -12px of 7px 17px ccw small, arc by 12px -2px of 33px 33px rotate -42deg cw large, arc to 25px 20px of 10px 5px ccw small)] - assert_equals: expected "shape ( from 2px 2px , arc to 18px - 12px of 7px 17px , arc by 12px - 2px of 33px rotate - 42deg , arc to 25px 20px of 10px 5px ) " but got "shape ( from 15px 15px , arc to 5px - 25px of 20px 30px , arc by 25px - 15px of 20px rotate 270deg , arc to 25px 20px of 10px 5px ) " + assert_equals: expected "shape ( from 2px 2px , arc to 18px - 12px of 7px 17px , arc by 12px - 2px of 33px cw large rotate - 42deg , arc to 25px 20px of 10px 5px ) " but got "shape ( from 15px 15px , arc to 5px - 25px of 20px 30px , arc by 25px - 15px of 20px cw rotate 270deg , arc to 25px 20px of 10px 5px cw ) " [FAIL] CSS Transitions: property <clip-path> from [path("M 5 5 A 10,20 0 0,0 15,-15 a 30,30 30 1,1 15,-5 A 10,5 0 0,0 25 20")] to [shape(from 15px 15px, arc to 5px -25px of 20px 30px, arc by 25px -15px of 20px cw rotate 270deg small, arc to 25px 20px of 10px 5px small cw)] at (0) should be [shape(from 5px 5px, arc to 15px -15px of 10px 20px, arc by 15px -5px of 30px cw rotate 30deg large, arc to 25px 20px of 10px 5px small)] - assert_equals: expected "shape ( from 5px 5px , arc to 15px - 15px of 10px 20px , arc by 15px - 5px of 30px rotate 30deg , arc to 25px 20px of 10px 5px ) " but got "shape ( from 15px 15px , arc to 5px - 25px of 20px 30px , arc by 25px - 15px of 20px rotate 270deg , arc to 25px 20px of 10px 5px ) " + assert_equals: expected "shape ( from 5px 5px , arc to 15px - 15px of 10px 20px , arc by 15px - 5px of 30px cw large rotate 30deg , arc to 25px 20px of 10px 5px ) " but got "shape ( from 15px 15px , arc to 5px - 25px of 20px 30px , arc by 25px - 15px of 20px cw rotate 270deg , arc to 25px 20px of 10px 5px cw ) " [FAIL] CSS Transitions: property <clip-path> from [path("M 5 5 A 10,20 0 0,0 15,-15 a 30,30 30 1,1 15,-5 A 10,5 0 0,0 25 20")] to [shape(from 15px 15px, arc to 5px -25px of 20px 30px, arc by 25px -15px of 20px cw rotate 270deg small, arc to 25px 20px of 10px 5px small cw)] at (0.3) should be [shape(from 8px 8px, arc to 12px -18px of 13px 23px ccw small, arc by 18px -8px of 27px 27px rotate 102deg cw large, arc to 25px 20px of 10px 5px cw small )] - assert_equals: expected "shape ( from 8px 8px , arc to 12px - 18px of 13px 23px , arc by 18px - 8px of 27px rotate 102deg , arc to 25px 20px of 10px 5px ) " but got "shape ( from 15px 15px , arc to 5px - 25px of 20px 30px , arc by 25px - 15px of 20px rotate 270deg , arc to 25px 20px of 10px 5px ) " + assert_equals: expected "shape ( from 8px 8px , arc to 12px - 18px of 13px 23px , arc by 18px - 8px of 27px cw large rotate 102deg , arc to 25px 20px of 10px 5px cw ) " but got "shape ( from 15px 15px , arc to 5px - 25px of 20px 30px , arc by 25px - 15px of 20px cw rotate 270deg , arc to 25px 20px of 10px 5px cw ) " [FAIL] CSS Transitions: property <clip-path> from [path("M 5 5 A 10,20 0 0,0 15,-15 a 30,30 30 1,1 15,-5 A 10,5 0 0,0 25 20")] to [shape(from 15px 15px, arc to 5px -25px of 20px 30px, arc by 25px -15px of 20px cw rotate 270deg small, arc to 25px 20px of 10px 5px small cw)] at (0.5) should be [shape(from 10px 10px, arc to 10px -20px of 15px 25px ccw small, arc by 20px -10px of 25px rotate 150deg cw large, arc to 25px 20px of 10px 5px cw small)] - assert_equals: expected "shape ( from 10px 10px , arc to 10px - 20px of 15px 25px , arc by 20px - 10px of 25px rotate 150deg , arc to 25px 20px of 10px 5px ) " but got "shape ( from 15px 15px , arc to 5px - 25px of 20px 30px , arc by 25px - 15px of 20px rotate 270deg , arc to 25px 20px of 10px 5px ) " + assert_equals: expected "shape ( from 10px 10px , arc to 10px - 20px of 15px 25px , arc by 20px - 10px of 25px cw large rotate 150deg , arc to 25px 20px of 10px 5px cw ) " but got "shape ( from 15px 15px , arc to 5px - 25px of 20px 30px , arc by 25px - 15px of 20px cw rotate 270deg , arc to 25px 20px of 10px 5px cw ) " [FAIL] CSS Transitions: property <clip-path> from [path("M 5 5 A 10,20 0 0,0 15,-15 a 30,30 30 1,1 15,-5 A 10,5 0 0,0 25 20")] to [shape(from 15px 15px, arc to 5px -25px of 20px 30px, arc by 25px -15px of 20px cw rotate 270deg small, arc to 25px 20px of 10px 5px small cw)] at (1.5) should be [shape(from 20px 20px, arc to 0px -30px of 25px 35px ccw small, arc by 30px -20px of 15px rotate 390deg cw small, arc to 25px 20px of 10px 5px cw small)] - assert_equals: expected "shape ( from 20px 20px , arc to 0px - 30px of 25px 35px , arc by 30px - 20px of 15px rotate 390deg , arc to 25px 20px of 10px 5px ) " but got "shape ( from 15px 15px , arc to 5px - 25px of 20px 30px , arc by 25px - 15px of 20px rotate 270deg , arc to 25px 20px of 10px 5px ) " + assert_equals: expected "shape ( from 20px 20px , arc to 0px - 30px of 25px 35px , arc by 30px - 20px of 15px cw rotate 390deg , arc to 25px 20px of 10px 5px cw ) " but got "shape ( from 15px 15px , arc to 5px - 25px of 20px 30px , arc by 25px - 15px of 20px cw rotate 270deg , arc to 25px 20px of 10px 5px cw ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [path("M 5 5 A 10,20 0 0,0 15,-15 a 30,30 30 1,1 15,-5 A 10,5 0 0,0 25 20")] to [shape(from 15px 15px, arc to 5px -25px of 20px 30px, arc by 25px -15px of 20px cw rotate 270deg small, arc to 25px 20px of 10px 5px small cw)] at (-0.3) should be [shape(from 2px 2px, arc to 18px -12px of 7px 17px ccw small, arc by 12px -2px of 33px 33px rotate -42deg cw large, arc to 25px 20px of 10px 5px ccw small)] - assert_equals: expected "shape ( from 2px 2px , arc to 18px - 12px of 7px 17px , arc by 12px - 2px of 33px rotate - 42deg , arc to 25px 20px of 10px 5px ) " but got "shape ( from 15px 15px , arc to 5px - 25px of 20px 30px , arc by 25px - 15px of 20px rotate 270deg , arc to 25px 20px of 10px 5px ) " + assert_equals: expected "shape ( from 2px 2px , arc to 18px - 12px of 7px 17px , arc by 12px - 2px of 33px cw large rotate - 42deg , arc to 25px 20px of 10px 5px ) " but got "shape ( from 15px 15px , arc to 5px - 25px of 20px 30px , arc by 25px - 15px of 20px cw rotate 270deg , arc to 25px 20px of 10px 5px cw ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [path("M 5 5 A 10,20 0 0,0 15,-15 a 30,30 30 1,1 15,-5 A 10,5 0 0,0 25 20")] to [shape(from 15px 15px, arc to 5px -25px of 20px 30px, arc by 25px -15px of 20px cw rotate 270deg small, arc to 25px 20px of 10px 5px small cw)] at (0) should be [shape(from 5px 5px, arc to 15px -15px of 10px 20px, arc by 15px -5px of 30px cw rotate 30deg large, arc to 25px 20px of 10px 5px small)] - assert_equals: expected "shape ( from 5px 5px , arc to 15px - 15px of 10px 20px , arc by 15px - 5px of 30px rotate 30deg , arc to 25px 20px of 10px 5px ) " but got "shape ( from 15px 15px , arc to 5px - 25px of 20px 30px , arc by 25px - 15px of 20px rotate 270deg , arc to 25px 20px of 10px 5px ) " + assert_equals: expected "shape ( from 5px 5px , arc to 15px - 15px of 10px 20px , arc by 15px - 5px of 30px cw large rotate 30deg , arc to 25px 20px of 10px 5px ) " but got "shape ( from 15px 15px , arc to 5px - 25px of 20px 30px , arc by 25px - 15px of 20px cw rotate 270deg , arc to 25px 20px of 10px 5px cw ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [path("M 5 5 A 10,20 0 0,0 15,-15 a 30,30 30 1,1 15,-5 A 10,5 0 0,0 25 20")] to [shape(from 15px 15px, arc to 5px -25px of 20px 30px, arc by 25px -15px of 20px cw rotate 270deg small, arc to 25px 20px of 10px 5px small cw)] at (0.3) should be [shape(from 8px 8px, arc to 12px -18px of 13px 23px ccw small, arc by 18px -8px of 27px 27px rotate 102deg cw large, arc to 25px 20px of 10px 5px cw small )] - assert_equals: expected "shape ( from 8px 8px , arc to 12px - 18px of 13px 23px , arc by 18px - 8px of 27px rotate 102deg , arc to 25px 20px of 10px 5px ) " but got "shape ( from 15px 15px , arc to 5px - 25px of 20px 30px , arc by 25px - 15px of 20px rotate 270deg , arc to 25px 20px of 10px 5px ) " + assert_equals: expected "shape ( from 8px 8px , arc to 12px - 18px of 13px 23px , arc by 18px - 8px of 27px cw large rotate 102deg , arc to 25px 20px of 10px 5px cw ) " but got "shape ( from 15px 15px , arc to 5px - 25px of 20px 30px , arc by 25px - 15px of 20px cw rotate 270deg , arc to 25px 20px of 10px 5px cw ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [path("M 5 5 A 10,20 0 0,0 15,-15 a 30,30 30 1,1 15,-5 A 10,5 0 0,0 25 20")] to [shape(from 15px 15px, arc to 5px -25px of 20px 30px, arc by 25px -15px of 20px cw rotate 270deg small, arc to 25px 20px of 10px 5px small cw)] at (0.5) should be [shape(from 10px 10px, arc to 10px -20px of 15px 25px ccw small, arc by 20px -10px of 25px rotate 150deg cw large, arc to 25px 20px of 10px 5px cw small)] - assert_equals: expected "shape ( from 10px 10px , arc to 10px - 20px of 15px 25px , arc by 20px - 10px of 25px rotate 150deg , arc to 25px 20px of 10px 5px ) " but got "shape ( from 15px 15px , arc to 5px - 25px of 20px 30px , arc by 25px - 15px of 20px rotate 270deg , arc to 25px 20px of 10px 5px ) " + assert_equals: expected "shape ( from 10px 10px , arc to 10px - 20px of 15px 25px , arc by 20px - 10px of 25px cw large rotate 150deg , arc to 25px 20px of 10px 5px cw ) " but got "shape ( from 15px 15px , arc to 5px - 25px of 20px 30px , arc by 25px - 15px of 20px cw rotate 270deg , arc to 25px 20px of 10px 5px cw ) " [FAIL] CSS Transitions with transition: all: property <clip-path> from [path("M 5 5 A 10,20 0 0,0 15,-15 a 30,30 30 1,1 15,-5 A 10,5 0 0,0 25 20")] to [shape(from 15px 15px, arc to 5px -25px of 20px 30px, arc by 25px -15px of 20px cw rotate 270deg small, arc to 25px 20px of 10px 5px small cw)] at (1.5) should be [shape(from 20px 20px, arc to 0px -30px of 25px 35px ccw small, arc by 30px -20px of 15px rotate 390deg cw small, arc to 25px 20px of 10px 5px cw small)] - assert_equals: expected "shape ( from 20px 20px , arc to 0px - 30px of 25px 35px , arc by 30px - 20px of 15px rotate 390deg , arc to 25px 20px of 10px 5px ) " but got "shape ( from 15px 15px , arc to 5px - 25px of 20px 30px , arc by 25px - 15px of 20px rotate 270deg , arc to 25px 20px of 10px 5px ) " + assert_equals: expected "shape ( from 20px 20px , arc to 0px - 30px of 25px 35px , arc by 30px - 20px of 15px cw rotate 390deg , arc to 25px 20px of 10px 5px cw ) " but got "shape ( from 15px 15px , arc to 5px - 25px of 20px 30px , arc by 25px - 15px of 20px cw rotate 270deg , arc to 25px 20px of 10px 5px cw ) " [FAIL] CSS Animations: property <clip-path> from [path("M 5 5 A 10,20 0 0,0 15,-15 a 30,30 30 1,1 15,-5 A 10,5 0 0,0 25 20")] to [shape(from 15px 15px, arc to 5px -25px of 20px 30px, arc by 25px -15px of 20px cw rotate 270deg small, arc to 25px 20px of 10px 5px small cw)] at (-0.3) should be [shape(from 2px 2px, arc to 18px -12px of 7px 17px ccw small, arc by 12px -2px of 33px 33px rotate -42deg cw large, arc to 25px 20px of 10px 5px ccw small)] - assert_equals: expected "shape ( from 2px 2px , arc to 18px - 12px of 7px 17px , arc by 12px - 2px of 33px rotate - 42deg , arc to 25px 20px of 10px 5px ) " but got "path ( \\" M 5 5 A 10 20 0 0 0 15 - 15 A 30 30 30 1 1 30 - 20 A 10 5 0 0 0 25 20 \\" ) " + assert_equals: expected "shape ( from 2px 2px , arc to 18px - 12px of 7px 17px , arc by 12px - 2px of 33px cw large rotate - 42deg , arc to 25px 20px of 10px 5px ) " but got "path ( \\" M 5 5 A 10 20 0 0 0 15 - 15 A 30 30 30 1 1 30 - 20 A 10 5 0 0 0 25 20 \\" ) " [FAIL] CSS Animations: property <clip-path> from [path("M 5 5 A 10,20 0 0,0 15,-15 a 30,30 30 1,1 15,-5 A 10,5 0 0,0 25 20")] to [shape(from 15px 15px, arc to 5px -25px of 20px 30px, arc by 25px -15px of 20px cw rotate 270deg small, arc to 25px 20px of 10px 5px small cw)] at (0) should be [shape(from 5px 5px, arc to 15px -15px of 10px 20px, arc by 15px -5px of 30px cw rotate 30deg large, arc to 25px 20px of 10px 5px small)] - assert_equals: expected "shape ( from 5px 5px , arc to 15px - 15px of 10px 20px , arc by 15px - 5px of 30px rotate 30deg , arc to 25px 20px of 10px 5px ) " but got "path ( \\" M 5 5 A 10 20 0 0 0 15 - 15 A 30 30 30 1 1 30 - 20 A 10 5 0 0 0 25 20 \\" ) " + assert_equals: expected "shape ( from 5px 5px , arc to 15px - 15px of 10px 20px , arc by 15px - 5px of 30px cw large rotate 30deg , arc to 25px 20px of 10px 5px ) " but got "path ( \\" M 5 5 A 10 20 0 0 0 15 - 15 A 30 30 30 1 1 30 - 20 A 10 5 0 0 0 25 20 \\" ) " [FAIL] CSS Animations: property <clip-path> from [path("M 5 5 A 10,20 0 0,0 15,-15 a 30,30 30 1,1 15,-5 A 10,5 0 0,0 25 20")] to [shape(from 15px 15px, arc to 5px -25px of 20px 30px, arc by 25px -15px of 20px cw rotate 270deg small, arc to 25px 20px of 10px 5px small cw)] at (0.3) should be [shape(from 8px 8px, arc to 12px -18px of 13px 23px ccw small, arc by 18px -8px of 27px 27px rotate 102deg cw large, arc to 25px 20px of 10px 5px cw small )] - assert_equals: expected "shape ( from 8px 8px , arc to 12px - 18px of 13px 23px , arc by 18px - 8px of 27px rotate 102deg , arc to 25px 20px of 10px 5px ) " but got "path ( \\" M 5 5 A 10 20 0 0 0 15 - 15 A 30 30 30 1 1 30 - 20 A 10 5 0 0 0 25 20 \\" ) " + assert_equals: expected "shape ( from 8px 8px , arc to 12px - 18px of 13px 23px , arc by 18px - 8px of 27px cw large rotate 102deg , arc to 25px 20px of 10px 5px cw ) " but got "path ( \\" M 5 5 A 10 20 0 0 0 15 - 15 A 30 30 30 1 1 30 - 20 A 10 5 0 0 0 25 20 \\" ) " [FAIL] CSS Animations: property <clip-path> from [path("M 5 5 A 10,20 0 0,0 15,-15 a 30,30 30 1,1 15,-5 A 10,5 0 0,0 25 20")] to [shape(from 15px 15px, arc to 5px -25px of 20px 30px, arc by 25px -15px of 20px cw rotate 270deg small, arc to 25px 20px of 10px 5px small cw)] at (0.5) should be [shape(from 10px 10px, arc to 10px -20px of 15px 25px ccw small, arc by 20px -10px of 25px rotate 150deg cw large, arc to 25px 20px of 10px 5px cw small)] - assert_equals: expected "shape ( from 10px 10px , arc to 10px - 20px of 15px 25px , arc by 20px - 10px of 25px rotate 150deg , arc to 25px 20px of 10px 5px ) " but got "shape ( from 15px 15px , arc to 5px - 25px of 20px 30px , arc by 25px - 15px of 20px rotate 270deg , arc to 25px 20px of 10px 5px ) " + assert_equals: expected "shape ( from 10px 10px , arc to 10px - 20px of 15px 25px , arc by 20px - 10px of 25px cw large rotate 150deg , arc to 25px 20px of 10px 5px cw ) " but got "shape ( from 15px 15px , arc to 5px - 25px of 20px 30px , arc by 25px - 15px of 20px cw rotate 270deg , arc to 25px 20px of 10px 5px cw ) " [FAIL] CSS Animations: property <clip-path> from [path("M 5 5 A 10,20 0 0,0 15,-15 a 30,30 30 1,1 15,-5 A 10,5 0 0,0 25 20")] to [shape(from 15px 15px, arc to 5px -25px of 20px 30px, arc by 25px -15px of 20px cw rotate 270deg small, arc to 25px 20px of 10px 5px small cw)] at (1.5) should be [shape(from 20px 20px, arc to 0px -30px of 25px 35px ccw small, arc by 30px -20px of 15px rotate 390deg cw small, arc to 25px 20px of 10px 5px cw small)] - assert_equals: expected "shape ( from 20px 20px , arc to 0px - 30px of 25px 35px , arc by 30px - 20px of 15px rotate 390deg , arc to 25px 20px of 10px 5px ) " but got "shape ( from 15px 15px , arc to 5px - 25px of 20px 30px , arc by 25px - 15px of 20px rotate 270deg , arc to 25px 20px of 10px 5px ) " + assert_equals: expected "shape ( from 20px 20px , arc to 0px - 30px of 25px 35px , arc by 30px - 20px of 15px cw rotate 390deg , arc to 25px 20px of 10px 5px cw ) " but got "shape ( from 15px 15px , arc to 5px - 25px of 20px 30px , arc by 25px - 15px of 20px cw rotate 270deg , arc to 25px 20px of 10px 5px cw ) " [FAIL] Web Animations: property <clip-path> from [path("M 5 5 A 10,20 0 0,0 15,-15 a 30,30 30 1,1 15,-5 A 10,5 0 0,0 25 20")] to [shape(from 15px 15px, arc to 5px -25px of 20px 30px, arc by 25px -15px of 20px cw rotate 270deg small, arc to 25px 20px of 10px 5px small cw)] at (-0.3) should be [shape(from 2px 2px, arc to 18px -12px of 7px 17px ccw small, arc by 12px -2px of 33px 33px rotate -42deg cw large, arc to 25px 20px of 10px 5px ccw small)] - assert_equals: expected "shape ( from 2px 2px , arc to 18px - 12px of 7px 17px , arc by 12px - 2px of 33px rotate - 42deg , arc to 25px 20px of 10px 5px ) " but got "path ( \\" M 5 5 A 10 20 0 0 0 15 - 15 A 30 30 30 1 1 30 - 20 A 10 5 0 0 0 25 20 \\" ) " + assert_equals: expected "shape ( from 2px 2px , arc to 18px - 12px of 7px 17px , arc by 12px - 2px of 33px cw large rotate - 42deg , arc to 25px 20px of 10px 5px ) " but got "path ( \\" M 5 5 A 10 20 0 0 0 15 - 15 A 30 30 30 1 1 30 - 20 A 10 5 0 0 0 25 20 \\" ) " [FAIL] Web Animations: property <clip-path> from [path("M 5 5 A 10,20 0 0,0 15,-15 a 30,30 30 1,1 15,-5 A 10,5 0 0,0 25 20")] to [shape(from 15px 15px, arc to 5px -25px of 20px 30px, arc by 25px -15px of 20px cw rotate 270deg small, arc to 25px 20px of 10px 5px small cw)] at (0) should be [shape(from 5px 5px, arc to 15px -15px of 10px 20px, arc by 15px -5px of 30px cw rotate 30deg large, arc to 25px 20px of 10px 5px small)] - assert_equals: expected "shape ( from 5px 5px , arc to 15px - 15px of 10px 20px , arc by 15px - 5px of 30px rotate 30deg , arc to 25px 20px of 10px 5px ) " but got "path ( \\" M 5 5 A 10 20 0 0 0 15 - 15 A 30 30 30 1 1 30 - 20 A 10 5 0 0 0 25 20 \\" ) " + assert_equals: expected "shape ( from 5px 5px , arc to 15px - 15px of 10px 20px , arc by 15px - 5px of 30px cw large rotate 30deg , arc to 25px 20px of 10px 5px ) " but got "path ( \\" M 5 5 A 10 20 0 0 0 15 - 15 A 30 30 30 1 1 30 - 20 A 10 5 0 0 0 25 20 \\" ) " [FAIL] Web Animations: property <clip-path> from [path("M 5 5 A 10,20 0 0,0 15,-15 a 30,30 30 1,1 15,-5 A 10,5 0 0,0 25 20")] to [shape(from 15px 15px, arc to 5px -25px of 20px 30px, arc by 25px -15px of 20px cw rotate 270deg small, arc to 25px 20px of 10px 5px small cw)] at (0.3) should be [shape(from 8px 8px, arc to 12px -18px of 13px 23px ccw small, arc by 18px -8px of 27px 27px rotate 102deg cw large, arc to 25px 20px of 10px 5px cw small )] - assert_equals: expected "shape ( from 8px 8px , arc to 12px - 18px of 13px 23px , arc by 18px - 8px of 27px rotate 102deg , arc to 25px 20px of 10px 5px ) " but got "path ( \\" M 5 5 A 10 20 0 0 0 15 - 15 A 30 30 30 1 1 30 - 20 A 10 5 0 0 0 25 20 \\" ) " + assert_equals: expected "shape ( from 8px 8px , arc to 12px - 18px of 13px 23px , arc by 18px - 8px of 27px cw large rotate 102deg , arc to 25px 20px of 10px 5px cw ) " but got "path ( \\" M 5 5 A 10 20 0 0 0 15 - 15 A 30 30 30 1 1 30 - 20 A 10 5 0 0 0 25 20 \\" ) " [FAIL] Web Animations: property <clip-path> from [path("M 5 5 A 10,20 0 0,0 15,-15 a 30,30 30 1,1 15,-5 A 10,5 0 0,0 25 20")] to [shape(from 15px 15px, arc to 5px -25px of 20px 30px, arc by 25px -15px of 20px cw rotate 270deg small, arc to 25px 20px of 10px 5px small cw)] at (0.5) should be [shape(from 10px 10px, arc to 10px -20px of 15px 25px ccw small, arc by 20px -10px of 25px rotate 150deg cw large, arc to 25px 20px of 10px 5px cw small)] - assert_equals: expected "shape ( from 10px 10px , arc to 10px - 20px of 15px 25px , arc by 20px - 10px of 25px rotate 150deg , arc to 25px 20px of 10px 5px ) " but got "shape ( from 15px 15px , arc to 5px - 25px of 20px 30px , arc by 25px - 15px of 20px rotate 270deg , arc to 25px 20px of 10px 5px ) " + assert_equals: expected "shape ( from 10px 10px , arc to 10px - 20px of 15px 25px , arc by 20px - 10px of 25px cw large rotate 150deg , arc to 25px 20px of 10px 5px cw ) " but got "shape ( from 15px 15px , arc to 5px - 25px of 20px 30px , arc by 25px - 15px of 20px cw rotate 270deg , arc to 25px 20px of 10px 5px cw ) " [FAIL] Web Animations: property <clip-path> from [path("M 5 5 A 10,20 0 0,0 15,-15 a 30,30 30 1,1 15,-5 A 10,5 0 0,0 25 20")] to [shape(from 15px 15px, arc to 5px -25px of 20px 30px, arc by 25px -15px of 20px cw rotate 270deg small, arc to 25px 20px of 10px 5px small cw)] at (1.5) should be [shape(from 20px 20px, arc to 0px -30px of 25px 35px ccw small, arc by 30px -20px of 15px rotate 390deg cw small, arc to 25px 20px of 10px 5px cw small)] - assert_equals: expected "shape ( from 20px 20px , arc to 0px - 30px of 25px 35px , arc by 30px - 20px of 15px rotate 390deg , arc to 25px 20px of 10px 5px ) " but got "shape ( from 15px 15px , arc to 5px - 25px of 20px 30px , arc by 25px - 15px of 20px rotate 270deg , arc to 25px 20px of 10px 5px ) " + assert_equals: expected "shape ( from 20px 20px , arc to 0px - 30px of 25px 35px , arc by 30px - 20px of 15px cw rotate 390deg , arc to 25px 20px of 10px 5px cw ) " but got "shape ( from 15px 15px , arc to 5px - 25px of 20px 30px , arc by 25px - 15px of 20px cw rotate 270deg , arc to 25px 20px of 10px 5px cw ) " Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/css/css-masking/parsing/clip-path-shape-parsing-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-masking/parsing/clip-path-shape-parsing-expected.txt deleted file mode 100644 index 8b42929..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-masking/parsing/clip-path-shape-parsing-expected.txt +++ /dev/null
@@ -1,15 +0,0 @@ -This is a testharness.js-based test. -[FAIL] e.style['clip-path'] = "shape(from 10px 10px, curve to 50px 20px with 10rem 1%)" should set the property value - assert_not_equals: property should be set got disallowed value "" -[FAIL] e.style['clip-path'] = "shape(from 10px 10px, curve to 50px 20px with 10rem 1px / 20vh 1ch)" should set the property value - assert_not_equals: property should be set got disallowed value "" -[FAIL] e.style['clip-path'] = "shape(from 10px 10px, curve by 50px 20px with 10rem 1px / 20vh 1ch)" should set the property value - assert_not_equals: property should be set got disallowed value "" -[FAIL] e.style['clip-path'] = "shape(from 10px 10px, smooth to 50px 20px with 10rem 1%)" should set the property value - assert_not_equals: property should be set got disallowed value "" -[FAIL] e.style['clip-path'] = "shape(from 10px 10px, smooth to 50px 1pt)" should set the property value - assert_not_equals: property should be set got disallowed value "" -[FAIL] e.style['clip-path'] = "shape(from 10% 1rem, arc to 50px 1pt of 20% cw large rotate 25deg)" should set the property value - assert_equals: serialization should be canonical expected "shape(from 10% 1rem, arc to 50px 1pt of 20% cw large rotate 25deg)" but got "shape(from 10% 1rem, arc to 50px 1pt of 20% rotate 25deg)" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/css/css-shapes/shape-functions/shape-function-computed.tentative-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-shapes/shape-functions/shape-function-computed.tentative-expected.txt index f6c6513..b44fa2f5 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-shapes/shape-functions/shape-function-computed.tentative-expected.txt +++ b/third_party/blink/web_tests/external/wpt/css/css-shapes/shape-functions/shape-function-computed.tentative-expected.txt
@@ -1,37 +1,7 @@ This is a testharness.js-based test. -[FAIL] Property clip-path value 'shape(from 20px 40px, curve by 20px 20px with 10px 30px)' - assert_true: 'shape(from 20px 40px, curve by 20px 20px with 10px 30px)' is a supported value for clip-path. expected true got false -[FAIL] Property clip-path value 'shape(from 20px 40px, curve by 20px 20px with 10px 30px / 12px 32px)' - assert_true: 'shape(from 20px 40px, curve by 20px 20px with 10px 30px / 12px 32px)' is a supported value for clip-path. expected true got false -[FAIL] Property clip-path value 'shape(from center, curve to center bottom with top right / bottom right)' - assert_true: 'shape(from center, curve to center bottom with top right / bottom right)' is a supported value for clip-path. expected true got false [FAIL] Property clip-path value 'shape(from center, curve by 20px 20px with 10px 30px from end / 12px 32px from start)' - assert_true: 'shape(from center, curve by 20px 20px with 10px 30px from end / 12px 32px from start)' is a supported value for clip-path. expected true got false -[FAIL] Property clip-path value 'shape(from center right, curve by 20px 20px with 10px 30px from origin / 12px 32px from origin)' - assert_true: 'shape(from center right, curve by 20px 20px with 10px 30px from origin / 12px 32px from origin)' is a supported value for clip-path. expected true got false + assert_equals: expected "shape(from 50% 50%, curve by 20px 20px with 10px 30px from end / 12px 32px from start)" but got "shape(from 50% 50%, curve by 20px 20px with 10px 30px from end / 12px 32px)" [FAIL] Property clip-path value 'shape(from 20px 40px, curve to top right with 10px 30px from origin / 12px 32px from origin)' - assert_true: 'shape(from 20px 40px, curve to top right with 10px 30px from origin / 12px 32px from origin)' is a supported value for clip-path. expected true got false -[FAIL] Property clip-path value 'shape(from 20px 40px, smooth by 20px 20px)' - assert_true: 'shape(from 20px 40px, smooth by 20px 20px)' is a supported value for clip-path. expected true got false -[FAIL] Property clip-path value 'shape(from 20px 40px, smooth by 20px 20px with 12px 32px)' - assert_true: 'shape(from 20px 40px, smooth by 20px 20px with 12px 32px)' is a supported value for clip-path. expected true got false -[FAIL] Property clip-path value 'shape(from 20px 40px, arc by 20px 20px of 10% 20% cw)' - assert_equals: expected "shape(from 20px 40px, arc by 20px 20px of 10% 20% cw)" but got "shape(from 20px 40px, arc by 20px 20px of 10% 20%)" -[FAIL] Property clip-path value 'shape(from 20px 40px, arc by 20px 20px of 10% 20% large)' - assert_equals: expected "shape(from 20px 40px, arc by 20px 20px of 10% 20% large)" but got "shape(from 20px 40px, arc by 20px 20px of 10% 20%)" -[FAIL] Property clip-path value 'shape(from 20px 40px, arc by 20px 20px of -10% -20% large)' - assert_equals: expected "shape(from 20px 40px, arc by 20px 20px of -10% -20% large)" but got "shape(from 20px 40px, arc by 20px 20px of -10% -20%)" -[FAIL] Property clip-path value 'shape(from 20px 40px, arc by 20px 20px of 10% 20% cw rotate 12deg)' - assert_equals: expected "shape(from 20px 40px, arc by 20px 20px of 10% 20% cw rotate 12deg)" but got "shape(from 20px 40px, arc by 20px 20px of 10% 20% rotate 12deg)" -[FAIL] Property clip-path value 'shape(from 20px 40px, arc by 20px 20px of 10% 20% cw rotate 3.14159265rad)' - assert_equals: expected "shape(from 20px 40px, arc by 20px 20px of 10% 20% cw rotate 180deg)" but got "shape(from 20px 40px, arc by 20px 20px of 10% 20% rotate 180deg)" -[FAIL] Property clip-path value 'shape(from 20px 40px, arc by 20px 20px of 10% 20% large rotate 12deg)' - assert_equals: expected "shape(from 20px 40px, arc by 20px 20px of 10% 20% large rotate 12deg)" but got "shape(from 20px 40px, arc by 20px 20px of 10% 20% rotate 12deg)" -[FAIL] Property clip-path value 'shape(from 20px 40px, arc by 20px 20px of 10% 20% cw large)' - assert_equals: expected "shape(from 20px 40px, arc by 20px 20px of 10% 20% cw large)" but got "shape(from 20px 40px, arc by 20px 20px of 10% 20%)" -[FAIL] Property clip-path value 'shape(from 20px 40px, arc by 20px 20px of 10% 20% large cw)' - assert_equals: expected "shape(from 20px 40px, arc by 20px 20px of 10% 20% cw large)" but got "shape(from 20px 40px, arc by 20px 20px of 10% 20%)" -[FAIL] Property clip-path value 'shape(from 20px 40px, arc by 20px 20px of 10% 20% rotate 12deg large)' - assert_equals: expected "shape(from 20px 40px, arc by 20px 20px of 10% 20% large rotate 12deg)" but got "shape(from 20px 40px, arc by 20px 20px of 10% 20% rotate 12deg)" + assert_equals: expected "shape(from 20px 40px, curve to 100% 0% with 10px 30px from origin / 12px 32px from origin)" but got "shape(from 20px 40px, curve to 100% 0% with 10px 30px / 12px 32px)" Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/css/css-shapes/shape-functions/shape-function-valid.tentative-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-shapes/shape-functions/shape-function-valid.tentative-expected.txt index a4c2157..e9efdd2 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-shapes/shape-functions/shape-function-valid.tentative-expected.txt +++ b/third_party/blink/web_tests/external/wpt/css/css-shapes/shape-functions/shape-function-valid.tentative-expected.txt
@@ -1,72 +1,18 @@ This is a testharness.js-based test. -Found 34 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 7 FAIL, 0 TIMEOUT, 0 NOTRUN. [FAIL] e.style['clip-path'] = "shape(from 20px 40px, move to 20px 30px, hline to x-start, hline to y-start)" should set the property value assert_not_equals: property should be set got disallowed value "" [FAIL] e.style['clip-path'] = "shape(from 20px 40px, move to 20px 30px, vline to y-start, vline to y-end)" should set the property value assert_not_equals: property should be set got disallowed value "" -[FAIL] e.style['clip-path'] = "shape(from 20px 40px, curve to 20px 20px with 10px 30px)" should set the property value - assert_not_equals: property should be set got disallowed value "" -[FAIL] e.style['clip-path'] = "shape(from 20px 40px, curve to 20em 20pt with 10vw 30vh)" should set the property value - assert_not_equals: property should be set got disallowed value "" -[FAIL] e.style['clip-path'] = "shape(from 20px 40px, curve to 10% 20% with 10px 30px / 12px 32px)" should set the property value - assert_not_equals: property should be set got disallowed value "" -[FAIL] e.style['clip-path'] = "shape(from 20px 40px, curve to top left with 10px 30px / 12px 32px)" should set the property value - assert_not_equals: property should be set got disallowed value "" -[FAIL] e.style['clip-path'] = "shape(from 20% 40%, curve to center with center right / bottom center)" should set the property value - assert_not_equals: property should be set got disallowed value "" -[FAIL] e.style['clip-path'] = "shape(from bottom right, curve to left with center right / bottom center)" should set the property value - assert_not_equals: property should be set got disallowed value "" -[FAIL] e.style['clip-path'] = "shape(from 20px 40px, curve to bottom left with 10px 30px from end)" should set the property value - assert_not_equals: property should be set got disallowed value "" -[FAIL] e.style['clip-path'] = "shape(from 20px 40px, curve to right center with 10px 30px from start / 12px 32px from end)" should set the property value - assert_not_equals: property should be set got disallowed value "" -[FAIL] e.style['clip-path'] = "shape(from 20px 40px, curve to right center with 10px 30px from start/12px 32px from end)" should set the property value - assert_not_equals: property should be set got disallowed value "" [FAIL] e.style['clip-path'] = "shape(from 20px 40px, curve to right center with 10px 30px from end / 12px 32px from origin)" should set the property value - assert_not_equals: property should be set got disallowed value "" + assert_equals: serialization should be canonical expected "shape(from 20px 40px, curve to right center with 10px 30px from end / 12px 32px from origin)" but got "shape(from 20px 40px, curve to right center with 10px 30px from end / 12px 32px)" [FAIL] e.style['clip-path'] = "shape(from 20px 40px, curve to right center with 10px 30px from origin / 12px 32px from start)" should set the property value - assert_not_equals: property should be set got disallowed value "" -[FAIL] e.style['clip-path'] = "shape(from 20px 40px, curve by 20px 20px with 10px 30px)" should set the property value - assert_not_equals: property should be set got disallowed value "" -[FAIL] e.style['clip-path'] = "shape(from 20px 40px, curve by 20px 20px with 10px 30px from origin)" should set the property value - assert_not_equals: property should be set got disallowed value "" -[FAIL] e.style['clip-path'] = "shape(from 20px 40px, curve by 20px 20px with 10px 30px / 12px 32px)" should set the property value - assert_not_equals: property should be set got disallowed value "" + assert_equals: serialization should be canonical expected "shape(from 20px 40px, curve to right center with 10px 30px from origin / 12px 32px from start)" but got "shape(from 20px 40px, curve to right center with 10px 30px / 12px 32px from start)" [FAIL] e.style['clip-path'] = "shape(from 20px 40px, curve by 20% 20em with 10px 30px from start / 12px 32px from end)" should set the property value - assert_not_equals: property should be set got disallowed value "" + assert_equals: serialization should be canonical expected "shape(from 20px 40px, curve by 20% 20em with 10px 30px from start / 12px 32px from end)" but got "shape(from 20px 40px, curve by 20% 20em with 10px 30px / 12px 32px from end)" [FAIL] e.style['clip-path'] = "shape(from 20px 40px, curve by 20% 20em with 10.3% 30px from origin / 12pt 5.4% from start)" should set the property value - assert_not_equals: property should be set got disallowed value "" -[FAIL] e.style['clip-path'] = "shape(from top left, smooth to top right)" should set the property value - assert_not_equals: property should be set got disallowed value "" -[FAIL] e.style['clip-path'] = "shape(from 20px 40px, smooth to center 20%)" should set the property value - assert_not_equals: property should be set got disallowed value "" -[FAIL] e.style['clip-path'] = "shape(from 20px 40px, smooth by 20px 20px)" should set the property value - assert_not_equals: property should be set got disallowed value "" -[FAIL] e.style['clip-path'] = "shape(from right bottom, smooth by 20px 20px with 12px 32px)" should set the property value - assert_not_equals: property should be set got disallowed value "" + assert_equals: serialization should be canonical expected "shape(from 20px 40px, curve by 20% 20em with 10.3% 30px from origin / 12pt 5.4% from start)" but got "shape(from 20px 40px, curve by 20% 20em with 10.3% 30px from origin / 12pt 5.4%)" [FAIL] e.style['clip-path'] = "shape(from 20px 40px, smooth by 20pt 20px with 12px 32px from start)" should set the property value - assert_not_equals: property should be set got disallowed value "" -[FAIL] e.style['clip-path'] = "shape(from center 40px, smooth by 20% 20% with 12px 32px from end)" should set the property value - assert_not_equals: property should be set got disallowed value "" -[FAIL] e.style['clip-path'] = "shape(from center, smooth by 20px 20px with 12px 32px from origin)" should set the property value - assert_not_equals: property should be set got disallowed value "" -[FAIL] e.style['clip-path'] = "shape(from 20px 40px, arc by 20px 20px of 10% 20% cw)" should set the property value - assert_equals: serialization should be canonical expected "shape(from 20px 40px, arc by 20px 20px of 10% 20% cw)" but got "shape(from 20px 40px, arc by 20px 20px of 10% 20%)" -[FAIL] e.style['clip-path'] = "shape(from 20px 40px, arc by 20px 20px of 10% 20% large)" should set the property value - assert_equals: serialization should be canonical expected "shape(from 20px 40px, arc by 20px 20px of 10% 20% large)" but got "shape(from 20px 40px, arc by 20px 20px of 10% 20%)" -[FAIL] e.style['clip-path'] = "shape(from 20px 40px, arc by 20px 20px of -10% -20% large)" should set the property value - assert_equals: serialization should be canonical expected "shape(from 20px 40px, arc by 20px 20px of -10% -20% large)" but got "shape(from 20px 40px, arc by 20px 20px of -10% -20%)" -[FAIL] e.style['clip-path'] = "shape(from 20px 40px, arc by 20px 20px of 10% 20% cw rotate 12deg)" should set the property value - assert_equals: serialization should be canonical expected "shape(from 20px 40px, arc by 20px 20px of 10% 20% cw rotate 12deg)" but got "shape(from 20px 40px, arc by 20px 20px of 10% 20% rotate 12deg)" -[FAIL] e.style['clip-path'] = "shape(from 20px 40px, arc by 20px 20px of 10px 20px cw rotate 0.52rad)" should set the property value - assert_equals: serialization should be canonical expected "shape(from 20px 40px, arc by 20px 20px of 10px 20px cw rotate 0.52rad)" but got "shape(from 20px 40px, arc by 20px 20px of 10px 20px rotate 0.52rad)" -[FAIL] e.style['clip-path'] = "shape(from 20px 40px, arc by 20px 20px of 10% 20% large rotate 12deg)" should set the property value - assert_equals: serialization should be canonical expected "shape(from 20px 40px, arc by 20px 20px of 10% 20% large rotate 12deg)" but got "shape(from 20px 40px, arc by 20px 20px of 10% 20% rotate 12deg)" -[FAIL] e.style['clip-path'] = "shape(from 20px 40px, arc by 20px 20px of 10% 20% cw large)" should set the property value - assert_equals: serialization should be canonical expected "shape(from 20px 40px, arc by 20px 20px of 10% 20% cw large)" but got "shape(from 20px 40px, arc by 20px 20px of 10% 20%)" -[FAIL] e.style['clip-path'] = "shape(from 20px 40px, arc by 20px 20px of 10% 20% large cw)" should set the property value - assert_equals: serialization should be canonical expected "shape(from 20px 40px, arc by 20px 20px of 10% 20% cw large)" but got "shape(from 20px 40px, arc by 20px 20px of 10% 20%)" -[FAIL] e.style['clip-path'] = "shape(from 20px 40px, arc by 20px 20px of 10% 20% rotate 12deg large)" should set the property value - assert_equals: serialization should be canonical expected "shape(from 20px 40px, arc by 20px 20px of 10% 20% large rotate 12deg)" but got "shape(from 20px 40px, arc by 20px 20px of 10% 20% rotate 12deg)" + assert_equals: serialization should be canonical expected "shape(from 20px 40px, smooth by 20pt 20px with 12px 32px from start)" but got "shape(from 20px 40px, smooth by 20pt 20px with 12px 32px)" Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.decimal.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.decimal.html index 0de11e23..5e1bd8b5 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.decimal.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.decimal.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.canvas.host.size.attributes.parse.decimal</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.em.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.em.html index 315c8323..529837c 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.em.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.em.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.canvas.host.size.attributes.parse.em</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.empty.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.empty.html index b9568712..e1d83b69 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.empty.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.empty.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.canvas.host.size.attributes.parse.empty</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.exp.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.exp.html index 208ddec..ddc9290 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.exp.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.exp.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.canvas.host.size.attributes.parse.exp</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.hex.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.hex.html index 05f7030d4..50f1554 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.hex.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.hex.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.canvas.host.size.attributes.parse.hex</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.junk.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.junk.html index 3a55fd1..092c701 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.junk.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.junk.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.canvas.host.size.attributes.parse.junk</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.minus.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.minus.html index da5f21a..beba35fd 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.minus.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.minus.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.canvas.host.size.attributes.parse.minus</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.octal.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.octal.html index ccc7efaa..c1dc1217 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.octal.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.octal.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.canvas.host.size.attributes.parse.octal</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.onlyspace.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.onlyspace.html index da14fa2..ef8e179 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.onlyspace.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.onlyspace.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.canvas.host.size.attributes.parse.onlyspace</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.percent.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.percent.html index d699288f..205a2fb 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.percent.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.percent.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.canvas.host.size.attributes.parse.percent</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.plus.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.plus.html index 58fb07f..08e2f15 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.plus.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.plus.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.canvas.host.size.attributes.parse.plus</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.space.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.space.html index 52fadaad..fe496f3 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.space.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.space.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.canvas.host.size.attributes.parse.space</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.trailingjunk.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.trailingjunk.html index b18167c..15013d18 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.trailingjunk.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.trailingjunk.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.canvas.host.size.attributes.parse.trailingjunk</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.whitespace.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.whitespace.html index 79e81c1..d5726e0f 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.whitespace.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.whitespace.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.canvas.host.size.attributes.parse.whitespace</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.zero.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.zero.html index b7fd499..b492ecb 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.zero.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.parse.zero.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.canvas.host.size.attributes.parse.zero</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.decimal.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.decimal.html index b6c2130b..76e5a73 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.decimal.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.decimal.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.canvas.host.size.attributes.setAttribute.decimal</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.em.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.em.html index f70713f..8048c09 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.em.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.em.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.canvas.host.size.attributes.setAttribute.em</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.empty.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.empty.html index fab2394f..67483170 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.empty.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.empty.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.canvas.host.size.attributes.setAttribute.empty</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.exp.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.exp.html index cfa11eb..6fc087fb 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.exp.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.exp.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.canvas.host.size.attributes.setAttribute.exp</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.hex.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.hex.html index 80a1fbd..a7deb1f 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.hex.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.hex.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.canvas.host.size.attributes.setAttribute.hex</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.junk.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.junk.html index b583871..be462e2 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.junk.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.junk.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.canvas.host.size.attributes.setAttribute.junk</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.minus.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.minus.html index 90a31403..525b78a 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.minus.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.minus.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.canvas.host.size.attributes.setAttribute.minus</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.octal.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.octal.html index c5b263bd5..71fb6cd7 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.octal.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.octal.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.canvas.host.size.attributes.setAttribute.octal</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.onlyspace.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.onlyspace.html index ac4cdb0..62724d9 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.onlyspace.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.onlyspace.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.canvas.host.size.attributes.setAttribute.onlyspace</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.percent.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.percent.html index 5aebf5a..7781f41 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.percent.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.percent.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.canvas.host.size.attributes.setAttribute.percent</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.plus.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.plus.html index 60da44da..d979cc9 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.plus.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.plus.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.canvas.host.size.attributes.setAttribute.plus</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.space.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.space.html index fbfd4c33..d15e666 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.space.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.space.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.canvas.host.size.attributes.setAttribute.space</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.trailingjunk.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.trailingjunk.html index 1d230bd..a40c20ac 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.trailingjunk.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.trailingjunk.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.canvas.host.size.attributes.setAttribute.trailingjunk</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.whitespace.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.whitespace.html index 1aa86d6..646052cd 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.whitespace.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.whitespace.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.canvas.host.size.attributes.setAttribute.whitespace</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.zero.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.zero.html index 64b4811..44b6ce37 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.zero.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/canvas-host/2d.canvas.host.size.attributes.setAttribute.zero.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.canvas.host.size.attributes.setAttribute.zero</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.clear.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.clear.html index cb805b69..fbb7adb 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.clear.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.clear.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.canvas.clear</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.copy.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.copy.html index d4e75b7b..a769d1f 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.copy.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.copy.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.canvas.copy</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.destination-atop.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.destination-atop.html index 6fded39e..c285bfe3 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.destination-atop.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.destination-atop.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.canvas.destination-atop</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.destination-in.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.destination-in.html index 7277286d..7089c30 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.destination-in.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.destination-in.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.canvas.destination-in</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.destination-out.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.destination-out.html index 5860c3d..75db37c 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.destination-out.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.destination-out.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.canvas.destination-out</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.destination-over.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.destination-over.html index 76bad843..af0e0488 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.destination-over.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.destination-over.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.canvas.destination-over</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.lighter.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.lighter.html index 8d706df..9dfb759 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.lighter.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.lighter.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.canvas.lighter</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.source-atop.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.source-atop.html index cf3e449..120cd64c 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.source-atop.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.source-atop.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.canvas.source-atop</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.source-in.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.source-in.html index dabcced..3424136 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.source-in.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.source-in.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.canvas.source-in</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.source-out.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.source-out.html index 2fcf708..f82e4577 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.source-out.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.source-out.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.canvas.source-out</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.source-over.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.source-over.html index b9dca65..44b30c0f 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.source-over.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.source-over.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.canvas.source-over</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.xor.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.xor.html index c252e17..b55a605 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.xor.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.canvas.xor.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.canvas.xor</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.clear.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.clear.html index 65cfd95..0c353f5 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.clear.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.clear.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.clip.clear</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.copy.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.copy.html index b38397a2..afc73376 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.copy.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.copy.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.clip.copy</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.destination-atop.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.destination-atop.html index 79fb3af..82e6e1a 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.destination-atop.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.destination-atop.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.clip.destination-atop</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.destination-in.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.destination-in.html index 63e8d3ac..519dec7 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.destination-in.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.destination-in.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.clip.destination-in</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.destination-out.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.destination-out.html index 8392464..95c6be7 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.destination-out.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.destination-out.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.clip.destination-out</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.destination-over.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.destination-over.html index fc7f1ab..f3b83e30 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.destination-over.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.destination-over.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.clip.destination-over</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.lighter.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.lighter.html index b3acab0..87ddf28 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.lighter.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.lighter.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.clip.lighter</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.source-atop.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.source-atop.html index 49c3eb0..be9ccbd 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.source-atop.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.source-atop.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.clip.source-atop</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.source-in.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.source-in.html index afe92ba..e1837904 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.source-in.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.source-in.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.clip.source-in</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.source-out.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.source-out.html index 43b352fb..e943a7eb 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.source-out.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.source-out.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.clip.source-out</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.source-over.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.source-over.html index 4973f8e..fa50543 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.source-over.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.source-over.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.clip.source-over</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.xor.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.xor.html index 5239d6f..3464088c 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.xor.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.clip.xor.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.clip.xor</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.clear.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.clear.html index a44f8e3..1a562e2 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.clear.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.clear.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.image.clear</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.copy.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.copy.html index d3c972b..809b8e37 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.copy.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.copy.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.image.copy</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.destination-atop.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.destination-atop.html index 7c6f9344..b23f9fa 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.destination-atop.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.destination-atop.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.image.destination-atop</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.destination-in.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.destination-in.html index a2bf972..707d3e17 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.destination-in.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.destination-in.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.image.destination-in</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.destination-out.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.destination-out.html index d0d08fa..7bbc3c1 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.destination-out.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.destination-out.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.image.destination-out</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.destination-over.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.destination-over.html index 7ac98904..88290edf 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.destination-over.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.destination-over.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.image.destination-over</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.lighter.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.lighter.html index 1df4c68..c5f3585 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.lighter.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.lighter.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.image.lighter</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.source-atop.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.source-atop.html index 86833df6..204365b2 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.source-atop.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.source-atop.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.image.source-atop</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.source-in.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.source-in.html index 0b6ca4b5..c14a5d3 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.source-in.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.source-in.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.image.source-in</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.source-out.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.source-out.html index 31dfe47..ccc1b0b5 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.source-out.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.source-out.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.image.source-out</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.source-over.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.source-over.html index e396faa..e9250a3 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.source-over.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.source-over.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.image.source-over</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.xor.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.xor.html index d43742c27..df435be5 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.xor.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.image.xor.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.image.xor</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.clear.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.clear.html index a946989..c396739 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.clear.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.clear.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.solid.clear</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.copy.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.copy.html index 14bee74..ccc94ae 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.copy.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.copy.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.solid.copy</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.destination-atop.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.destination-atop.html index d82fb44c..eaff08a 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.destination-atop.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.destination-atop.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.solid.destination-atop</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.destination-in.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.destination-in.html index 6a491f5..08cde7a 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.destination-in.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.destination-in.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.solid.destination-in</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.destination-out.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.destination-out.html index bcc7f24..db3fca4 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.destination-out.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.destination-out.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.solid.destination-out</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.destination-over.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.destination-over.html index 6e634e6..42d5ded 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.destination-over.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.destination-over.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.solid.destination-over</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.lighter.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.lighter.html index fddbe92..3efda4a 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.lighter.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.lighter.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.solid.lighter</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.source-atop.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.source-atop.html index 4bb0e3d..23297cf 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.source-atop.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.source-atop.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.solid.source-atop</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.source-in.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.source-in.html index f8fee40..1b240aa 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.source-in.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.source-in.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.solid.source-in</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.source-out.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.source-out.html index 2c9d0861..758c5ec 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.source-out.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.source-out.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.solid.source-out</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.source-over.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.source-over.html index 335987b1..b7b31905 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.source-over.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.source-over.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.solid.source-over</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.xor.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.xor.html index d9da430..f4e6dfc 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.xor.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.solid.xor.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.solid.xor</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.clear.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.clear.html index de417ee..1297f7e 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.clear.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.clear.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.transparent.clear</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.copy.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.copy.html index 2048975..437e9ca 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.copy.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.copy.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.transparent.copy</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.destination-atop.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.destination-atop.html index 1da1f1a..6c02a62 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.destination-atop.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.destination-atop.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.transparent.destination-atop</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.destination-in.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.destination-in.html index b0f8abe..b0526835 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.destination-in.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.destination-in.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.transparent.destination-in</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.destination-out.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.destination-out.html index badbfc4..8c9f95ff 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.destination-out.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.destination-out.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.transparent.destination-out</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.destination-over.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.destination-over.html index e8e0051..fa8cf83 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.destination-over.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.destination-over.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.transparent.destination-over</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.lighter.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.lighter.html index 6e4c42a..2670d908 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.lighter.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.lighter.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.transparent.lighter</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.source-atop.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.source-atop.html index d3d3fbd..79a6f87 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.source-atop.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.source-atop.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.transparent.source-atop</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.source-in.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.source-in.html index 27c66cb6..58c87ce3b 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.source-in.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.source-in.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.transparent.source-in</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.source-out.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.source-out.html index 31bb6a2..5f8317e 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.source-out.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.source-out.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.transparent.source-out</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.source-over.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.source-over.html index ee20f52..625d9d0 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.source-over.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.source-over.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.transparent.source-over</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.xor.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.xor.html index d181875..f211f7d 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.xor.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.transparent.xor.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.transparent.xor</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.fill.copy.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.fill.copy.html index 9dfd650b..9f2e3152 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.fill.copy.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.fill.copy.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.uncovered.fill.copy</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.fill.destination-atop.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.fill.destination-atop.html index 685a139..cc0fc611 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.fill.destination-atop.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.fill.destination-atop.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.uncovered.fill.destination-atop</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.fill.destination-in.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.fill.destination-in.html index 9ca8021..408e80a 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.fill.destination-in.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.fill.destination-in.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.uncovered.fill.destination-in</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.fill.source-in.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.fill.source-in.html index 9f1a5f9..259c8c9a 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.fill.source-in.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.fill.source-in.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.uncovered.fill.source-in</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.fill.source-out.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.fill.source-out.html index 7653677..7cb7341 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.fill.source-out.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.fill.source-out.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.uncovered.fill.source-out</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.image.copy.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.image.copy.html index 61dd038..4f8ade8a 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.image.copy.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.image.copy.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.uncovered.image.copy</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.image.destination-atop.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.image.destination-atop.html index 440c832c..d728a4f 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.image.destination-atop.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.image.destination-atop.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.uncovered.image.destination-atop</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.image.destination-in.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.image.destination-in.html index 03e2e807..644be0b 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.image.destination-in.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.image.destination-in.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.uncovered.image.destination-in</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.image.source-in.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.image.source-in.html index de2e5fa..8828c42 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.image.source-in.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.image.source-in.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.uncovered.image.source-in</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.image.source-out.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.image.source-out.html index 5cb9b07..7bb4734 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.image.source-out.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.image.source-out.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.uncovered.image.source-out</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.nocontext.copy.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.nocontext.copy.html index cac66ad..748ee28 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.nocontext.copy.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.nocontext.copy.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.uncovered.nocontext.copy</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.nocontext.destination-atop.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.nocontext.destination-atop.html index c7cecc2e..c46ffbf 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.nocontext.destination-atop.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.nocontext.destination-atop.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.uncovered.nocontext.destination-atop</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.nocontext.destination-in.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.nocontext.destination-in.html index e090d7d4..87a9978 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.nocontext.destination-in.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.nocontext.destination-in.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.uncovered.nocontext.destination-in</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.nocontext.source-in.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.nocontext.source-in.html index 0436b40..2787477 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.nocontext.source-in.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.nocontext.source-in.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.uncovered.nocontext.source-in</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.nocontext.source-out.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.nocontext.source-out.html index efbc8ab..f7047a7 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.nocontext.source-out.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.nocontext.source-out.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.uncovered.nocontext.source-out</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.pattern.copy.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.pattern.copy.html index aaee920..9dd5d0bc 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.pattern.copy.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.pattern.copy.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.uncovered.pattern.copy</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.pattern.destination-atop.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.pattern.destination-atop.html index aded018f..a0637ff 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.pattern.destination-atop.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.pattern.destination-atop.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.uncovered.pattern.destination-atop</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.pattern.destination-in.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.pattern.destination-in.html index e520e1ff..ed65ba9 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.pattern.destination-in.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.pattern.destination-in.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.uncovered.pattern.destination-in</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.pattern.source-in.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.pattern.source-in.html index bee6548..cc42f36d 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.pattern.source-in.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.pattern.source-in.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.uncovered.pattern.source-in</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.pattern.source-out.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.pattern.source-out.html index 9478930..b192208 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.pattern.source-out.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/compositing/2d.composite.uncovered.pattern.source-out.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.composite.uncovered.pattern.source-out</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-1.html index 87b5bc93..bdb6b528 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.css-color-4-hsl-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-2.html index 746c358..badad04 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.css-color-4-hsl-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-3.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-3.html index b8a9cd5..683f0c6 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-3.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-3.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.css-color-4-hsl-3</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-4.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-4.html index d5e58b9..0576d51 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-4.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-4.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.css-color-4-hsl-4</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-5.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-5.html index 85bbb802..d0e2b378 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-5.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-5.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.css-color-4-hsl-5</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-6.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-6.html index 154bdcd..aa703a3 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-6.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-6.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.css-color-4-hsl-6</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-7.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-7.html index 5cf81e4..4eeaa95 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-7.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-7.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.css-color-4-hsl-7</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-8.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-8.html index 17d0782df..8e702a6 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-8.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-8.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.css-color-4-hsl-8</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-9.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-9.html index 2f4b1e8e..ea2c204a 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-9.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-9.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.css-color-4-hsl-9</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-1.html index bc70e21..03d961b 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.css-color-4-hsla-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-2.html index 7f77498..d02a7307 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.css-color-4-hsla-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-3.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-3.html index c33a50a..aadf27a9 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-3.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-3.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.css-color-4-hsla-3</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-4.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-4.html index 3d0cafc..262a498 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-4.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-4.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.css-color-4-hsla-4</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-5.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-5.html index a70613b..693050a 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-5.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-5.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.css-color-4-hsla-5</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-6.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-6.html index 8c46d88..37ad193 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-6.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-6.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.css-color-4-hsla-6</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-7.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-7.html index b6b4760..09ce0e4cc 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-7.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-7.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.css-color-4-hsla-7</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-8.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-8.html index 7933d47..d17be05 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-8.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-8.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.css-color-4-hsla-8</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-9.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-9.html index 8a4e29d4..4cbd8ec 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-9.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-9.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.css-color-4-hsla-9</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-1.html index 632b7f5..98a65af 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.css-color-4-rgb-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-2.html index 1d3e683..0f5b072a 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.css-color-4-rgb-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-3.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-3.html index 8a6f3523..c636a03a 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-3.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-3.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.css-color-4-rgb-3</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-4.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-4.html index 1fdf9ecf..2cbb25b0 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-4.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-4.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.css-color-4-rgb-4</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-5.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-5.html index a1d99d5..c35df14 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-5.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-5.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.css-color-4-rgb-5</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-6.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-6.html index ad2c5f5..d34ac6f 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-6.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-6.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.css-color-4-rgb-6</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-1.html index f394dbf..1ac6208 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.css-color-4-rgba-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-2.html index 5529bc1..3f656a7 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.css-color-4-rgba-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-3.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-3.html index 82047a56..9e2834b 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-3.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-3.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.css-color-4-rgba-3</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-4.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-4.html index 5fea546..caaaf7d 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-4.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-4.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.css-color-4-rgba-4</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-5.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-5.html index d048566..f1221a5 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-5.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-5.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.css-color-4-rgba-5</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-6.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-6.html index 28feb2e..e347166 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-6.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-6.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.css-color-4-rgba-6</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hex3.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hex3.html index 017bfc8..ae33d37a 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hex3.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hex3.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.hex3</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hex4.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hex4.html index c8704edb..7e0ad65 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hex4.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hex4.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.hex4</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hex6.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hex6.html index 9644a46..65c35e6 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hex6.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hex6.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.hex6</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hex8.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hex8.html index b2dd069..222d4fb7 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hex8.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hex8.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.hex8</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-1.html index ceb3da5..f701b2b5 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.hsl-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-2.html index 22e67e3..c098983 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.hsl-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-3.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-3.html index e182952..e8058ed 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-3.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-3.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.hsl-3</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-4.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-4.html index b320c1c..e78cebb 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-4.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-4.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.hsl-4</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-5.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-5.html index 1264f626..0f71bcd 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-5.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-5.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.hsl-5</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-6.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-6.html index e0fc787..84c7a70 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-6.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-6.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.hsl-6</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-negative-saturation.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-negative-saturation.html index 65440c6..c6b10917 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-negative-saturation.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-negative-saturation.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.hsl-clamp-negative-saturation</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-1.html index dbc738f..24a314b3 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.hsla-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-2.html index aa21789..e104c75 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.hsla-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-1.html index e5dc98d4..e3d1621 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.hsla-clamp-alpha-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-2.html index 26139a5..984bb64 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.hsla-clamp-alpha-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-negative-saturation.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-negative-saturation.html index 2d9b9d3b..3196c3a 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-negative-saturation.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-negative-saturation.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.hsla-clamp-negative-saturation</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.html4.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.html4.html index 65d0d20..8b86280 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.html4.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.html4.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.html4</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsl-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsl-1.html index 4046f82..e798886 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsl-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsl-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.css-color-4-hsl-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsl-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsl-2.html index 2075f8e..6318968 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsl-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsl-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.css-color-4-hsl-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsl-3.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsl-3.html index 53bbf6c..6be6283 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsl-3.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsl-3.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.css-color-4-hsl-3</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsl-4.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsl-4.html index e8be93b..aea149a 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsl-4.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsl-4.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.css-color-4-hsl-4</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsl-5.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsl-5.html index b8938ad..3fa3ddf 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsl-5.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsl-5.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.css-color-4-hsl-5</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsla-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsla-1.html index 7104ca6..9094ec66 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsla-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsla-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.css-color-4-hsla-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsla-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsla-2.html index c340e74..4fb51d2 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsla-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsla-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.css-color-4-hsla-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsla-3.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsla-3.html index 3f94ec1..1097b4b 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsla-3.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsla-3.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.css-color-4-hsla-3</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgb-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgb-1.html index 6950359..ceb4860 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgb-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgb-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.css-color-4-rgb-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgb-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgb-2.html index 96af643e..ad05d50 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgb-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgb-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.css-color-4-rgb-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgb-3.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgb-3.html index a2691ac..1b20ebe7 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgb-3.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgb-3.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.css-color-4-rgb-3</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgb-4.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgb-4.html index eb5f566..b9b7ec0 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgb-4.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgb-4.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.css-color-4-rgb-4</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgb-5.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgb-5.html index 7de9dd4..ca9dcf83 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgb-5.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgb-5.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.css-color-4-rgb-5</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgba-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgba-1.html index 20b889c..e13d68f 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgba-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgba-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.css-color-4-rgba-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgba-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgba-2.html index 908545c..28e51f64 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgba-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgba-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.css-color-4-rgba-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgba-3.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgba-3.html index 851314f..86450c08 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgba-3.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgba-3.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.css-color-4-rgba-3</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex1.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex1.html index 9aba392..e5e7bbf 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.hex1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex2.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex2.html index 361db1de..db859c9 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.hex2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex3.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex3.html index 7df089d..9cf0cb6 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex3.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex3.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.hex3</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex4.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex4.html index 6089675b..0aaeb50c 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex4.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex4.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.hex4</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex5.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex5.html index 488daf4..fa2b14fc 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex5.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex5.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.hex5</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex6.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex6.html index ec0def2..161ca0b9 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex6.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex6.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.hex6</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex7.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex7.html index 2b07b8d..cafd6ac 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex7.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex7.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.hex7</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex8.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex8.html index f886d4a6..5b9a1388 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex8.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex8.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.hex8</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-1.html index 153f9cb5..724859ed 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.hsl-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-2.html index 7a2bd4f9..e1e4c19 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.hsl-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-3.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-3.html index 8ad0f54..c10c709c 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-3.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-3.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.hsl-3</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-4.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-4.html index 780b83b..19170fa 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-4.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-4.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.hsl-4</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-5.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-5.html index ad5944f..b23ff44a 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-5.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-5.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.hsl-5</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-6.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-6.html index 948a9d8..4338d04 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-6.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-6.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.hsl-6</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsla-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsla-1.html index 7a4bdb3..c9b3304 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsla-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsla-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.hsla-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsla-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsla-2.html index 4164de3..04bd692 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsla-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsla-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.hsla-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsla-3.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsla-3.html index 109a22cd..23051d1 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsla-3.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsla-3.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.hsla-3</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-1.html index acdd4d4c..6ed9ac9f 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.name-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-2.html index 292f909..5836df7b 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.name-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-3.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-3.html index f47ec43..dd76fa4 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-3.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-3.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.name-3</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-4.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-4.html index d15d787f..45a6c25 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-4.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-4.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.name-4</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-5.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-5.html index ce391d0..bf880a8 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-5.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-5.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.name-5</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-1.html index 934f725..d8b7a125 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.rgb-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-2.html index f92a06b4..8463bc7 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.rgb-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-3.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-3.html index 8ebde17..60444830 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-3.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-3.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.rgb-3</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-1.html index 6e3d135..6751fe3 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.rgba-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-2.html index a6a6100..3b6ea3d3 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.rgba-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-3.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-3.html index 464d562..bfb613d 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-3.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-3.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.rgba-3</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-4.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-4.html index 815ce2f..47f473da 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-4.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-4.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.rgba-4</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-5.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-5.html index 33c3e33..50eb15e 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-5.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-5.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.invalid.rgba-5</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-1.html index 0432a3b..0b3268e 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.rgb-clamp-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-2.html index cf81e3c7..d4eda1b 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.rgb-clamp-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-3.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-3.html index b3c609f..ad0d1431 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-3.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-3.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.rgb-clamp-3</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-4.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-4.html index 60aa8563..bc6ac31 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-4.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-4.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.rgb-clamp-4</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-5.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-5.html index 242ca393..7071282 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-5.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-5.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.rgb-clamp-5</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgb-eof.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgb-eof.html index 201874c..47845a14 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgb-eof.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgb-eof.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.rgb-eof</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgb-num.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgb-num.html index 0ce1db8..56f3051c 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgb-num.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgb-num.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.rgb-num</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgb-percent.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgb-percent.html index 9b3de61..4e4c591274 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgb-percent.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgb-percent.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.rgb-percent</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgba-clamp-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgba-clamp-1.html index 587253a..5310bd6 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgba-clamp-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgba-clamp-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.rgba-clamp-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgba-clamp-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgba-clamp-2.html index 4e8156e..a5e58588 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgba-clamp-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgba-clamp-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.rgba-clamp-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgba-eof.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgba-eof.html index 5f07d38b..fde5dbfe 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgba-eof.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgba-eof.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.rgba-eof</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgba-num-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgba-num-1.html index 0c329c96e..18dc4525 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgba-num-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgba-num-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.rgba-num-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgba-num-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgba-num-2.html index 384a7f412..0d21dc0b 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgba-num-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgba-num-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.rgba-num-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgba-percent.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgba-percent.html index 60ee007..f1eb208 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgba-percent.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgba-percent.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.rgba-percent</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-1.html index eaec0de..cc734a59 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.rgba-solid-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-2.html index 947bbbc..8d04a91 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.rgba-solid-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-3.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-3.html index 052a12b..34a32c9 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-3.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-3.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.rgba-solid-3</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-4.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-4.html index ee9cd4e..7f18015 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-4.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-4.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.rgba-solid-4</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.svg-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.svg-1.html index 0ff839b..b8e3dc00e 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.svg-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.svg-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.svg-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.svg-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.svg-2.html index 141f4bf..c425f10 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.svg-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.svg-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.svg-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.system.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.system.html index 3a563899..e286a01 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.system.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.system.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.system</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.transparent-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.transparent-1.html index 5b9a834..c765d213 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.transparent-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.transparent-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.transparent-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.transparent-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.transparent-2.html index a077534c..497d0aee 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.transparent-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.transparent-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>Canvas test: 2d.fillStyle.parse.transparent-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.decimal.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.decimal.html index c3fa3b4..c131a9d 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.decimal.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.decimal.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.canvas.host.size.attributes.parse.decimal</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.em.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.em.html index ea6f811..df6884a 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.em.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.em.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.canvas.host.size.attributes.parse.em</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.empty.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.empty.html index d38c159a..7a3fcbc 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.empty.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.empty.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.canvas.host.size.attributes.parse.empty</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.exp.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.exp.html index 2aa8245..5a5886e 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.exp.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.exp.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.canvas.host.size.attributes.parse.exp</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.hex.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.hex.html index 4b0e47b..6eb9226 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.hex.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.hex.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.canvas.host.size.attributes.parse.hex</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.junk.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.junk.html index a619651f..a05a180 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.junk.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.junk.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.canvas.host.size.attributes.parse.junk</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.minus.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.minus.html index c7f12fd..245ffd48 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.minus.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.minus.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.canvas.host.size.attributes.parse.minus</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.octal.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.octal.html index 7bfb7658..8a2b7fc2 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.octal.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.octal.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.canvas.host.size.attributes.parse.octal</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.onlyspace.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.onlyspace.html index 16dace1..e64771d6 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.onlyspace.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.onlyspace.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.canvas.host.size.attributes.parse.onlyspace</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.percent.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.percent.html index 040a775..ea887975 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.percent.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.percent.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.canvas.host.size.attributes.parse.percent</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.plus.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.plus.html index 50c8467e..a00845dc 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.plus.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.plus.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.canvas.host.size.attributes.parse.plus</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.space.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.space.html index cb1f3ae8..0f3037f 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.space.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.space.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.canvas.host.size.attributes.parse.space</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.trailingjunk.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.trailingjunk.html index 8d8d481..ed1b3de 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.trailingjunk.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.trailingjunk.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.canvas.host.size.attributes.parse.trailingjunk</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.whitespace.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.whitespace.html index f6e29d6..413d81f 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.whitespace.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.whitespace.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.canvas.host.size.attributes.parse.whitespace</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.zero.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.zero.html index 07e924a..0506f13 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.zero.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/canvas-host/2d.canvas.host.size.attributes.parse.zero.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.canvas.host.size.attributes.parse.zero</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.clear.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.clear.html index eac9dbd..72dc4bb 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.clear.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.clear.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.canvas.clear</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.copy.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.copy.html index 7c9771c..cfc5a33 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.copy.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.copy.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.canvas.copy</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.destination-atop.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.destination-atop.html index d9c34ded..3a1f86c8 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.destination-atop.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.destination-atop.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.canvas.destination-atop</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.destination-in.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.destination-in.html index 9c1a8db..c8480a96 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.destination-in.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.destination-in.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.canvas.destination-in</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.destination-out.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.destination-out.html index 10c5baf..f35bc25 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.destination-out.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.destination-out.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.canvas.destination-out</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.destination-over.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.destination-over.html index 0e2ece9e..676b436 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.destination-over.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.destination-over.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.canvas.destination-over</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.lighter.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.lighter.html index 392bb85..4c91350 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.lighter.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.lighter.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.canvas.lighter</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.source-atop.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.source-atop.html index f7d4da4..f6e0387 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.source-atop.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.source-atop.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.canvas.source-atop</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.source-in.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.source-in.html index 69e57e2..ea7acd8b 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.source-in.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.source-in.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.canvas.source-in</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.source-out.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.source-out.html index eb9dbd08..7b2de94 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.source-out.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.source-out.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.canvas.source-out</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.source-over.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.source-over.html index 98629de8..fe833737 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.source-over.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.source-over.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.canvas.source-over</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.xor.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.xor.html index bc69c8a..d89e6de2 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.xor.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.canvas.xor.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.canvas.xor</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.clear.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.clear.html index f0e9989..ba555fee 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.clear.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.clear.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.clip.clear</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.copy.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.copy.html index 2471cd7..061a256 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.copy.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.copy.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.clip.copy</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.destination-atop.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.destination-atop.html index efb5e7a..19b05ef 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.destination-atop.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.destination-atop.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.clip.destination-atop</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.destination-in.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.destination-in.html index bc467a1..f574146 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.destination-in.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.destination-in.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.clip.destination-in</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.destination-out.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.destination-out.html index 674ec3a..bdf8c7bc 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.destination-out.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.destination-out.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.clip.destination-out</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.destination-over.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.destination-over.html index 6abd0af..4c484b6 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.destination-over.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.destination-over.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.clip.destination-over</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.lighter.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.lighter.html index 00782a6..8a1ed3f2 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.lighter.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.lighter.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.clip.lighter</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.source-atop.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.source-atop.html index a7dc6a3..0bc3e975 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.source-atop.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.source-atop.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.clip.source-atop</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.source-in.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.source-in.html index 3f24076..f91862b 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.source-in.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.source-in.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.clip.source-in</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.source-out.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.source-out.html index 4033893b..b93ebf3 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.source-out.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.source-out.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.clip.source-out</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.source-over.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.source-over.html index 5b48161..90125c00 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.source-over.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.source-over.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.clip.source-over</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.xor.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.xor.html index 0156e4a..d35b53c 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.xor.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.clip.xor.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.clip.xor</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.clear.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.clear.html index f001c44..2582a6b 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.clear.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.clear.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.image.clear</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.copy.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.copy.html index d472a06..d0fe687 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.copy.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.copy.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.image.copy</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.destination-atop.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.destination-atop.html index 753c460..78d352ea 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.destination-atop.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.destination-atop.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.image.destination-atop</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.destination-in.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.destination-in.html index df9f1ae7..8f8e188 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.destination-in.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.destination-in.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.image.destination-in</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.destination-out.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.destination-out.html index 6981ca1..410a019 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.destination-out.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.destination-out.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.image.destination-out</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.destination-over.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.destination-over.html index 3360115..c9e33da 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.destination-over.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.destination-over.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.image.destination-over</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.lighter.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.lighter.html index 25f2a76..15176dc 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.lighter.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.lighter.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.image.lighter</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.source-atop.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.source-atop.html index cfa386c..9d8b850 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.source-atop.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.source-atop.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.image.source-atop</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.source-in.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.source-in.html index cc44706..1d63fc1 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.source-in.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.source-in.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.image.source-in</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.source-out.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.source-out.html index bc2f7f26..5ab29d01 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.source-out.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.source-out.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.image.source-out</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.source-over.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.source-over.html index 88a8176..55ad292 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.source-over.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.source-over.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.image.source-over</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.xor.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.xor.html index ef149b2..edc42d5 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.xor.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.image.xor.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.image.xor</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.clear.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.clear.html index 9bb03097..69f7b82 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.clear.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.clear.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.solid.clear</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.copy.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.copy.html index a5bcda9..f278e2f 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.copy.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.copy.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.solid.copy</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.destination-atop.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.destination-atop.html index c5554ff..ed04124 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.destination-atop.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.destination-atop.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.solid.destination-atop</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.destination-in.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.destination-in.html index 8e620e2..4c605eac 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.destination-in.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.destination-in.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.solid.destination-in</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.destination-out.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.destination-out.html index 06da4d3..7a940b0c 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.destination-out.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.destination-out.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.solid.destination-out</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.destination-over.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.destination-over.html index e62c3fe..ff642c19 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.destination-over.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.destination-over.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.solid.destination-over</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.lighter.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.lighter.html index 2e09805c..b8554d41 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.lighter.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.lighter.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.solid.lighter</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.source-atop.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.source-atop.html index dd36e0e..ec9da02c 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.source-atop.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.source-atop.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.solid.source-atop</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.source-in.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.source-in.html index 83dcc8e..75a9024 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.source-in.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.source-in.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.solid.source-in</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.source-out.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.source-out.html index 3067c44f..ec039f1 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.source-out.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.source-out.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.solid.source-out</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.source-over.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.source-over.html index 0596553..4f219fd8 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.source-over.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.source-over.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.solid.source-over</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.xor.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.xor.html index 822c9c7..dac3766 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.xor.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.solid.xor.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.solid.xor</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.clear.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.clear.html index 81d781a..1dcf7cb 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.clear.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.clear.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.transparent.clear</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.copy.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.copy.html index ab3a972..55b60df 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.copy.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.copy.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.transparent.copy</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.destination-atop.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.destination-atop.html index 5e580f5..82740c37 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.destination-atop.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.destination-atop.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.transparent.destination-atop</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.destination-in.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.destination-in.html index 9f0ec56..019f1f8 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.destination-in.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.destination-in.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.transparent.destination-in</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.destination-out.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.destination-out.html index a1abe3e..7c71188 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.destination-out.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.destination-out.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.transparent.destination-out</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.destination-over.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.destination-over.html index 4f0305f..b0d2af3 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.destination-over.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.destination-over.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.transparent.destination-over</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.lighter.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.lighter.html index 6a2f5df7..61cf66d0 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.lighter.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.lighter.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.transparent.lighter</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.source-atop.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.source-atop.html index bac035c..dacd508 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.source-atop.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.source-atop.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.transparent.source-atop</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.source-in.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.source-in.html index 5dd6704..db3b49d5 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.source-in.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.source-in.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.transparent.source-in</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.source-out.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.source-out.html index 56b1d4a..226039c6 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.source-out.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.source-out.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.transparent.source-out</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.source-over.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.source-over.html index f038d44..02e0ace 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.source-over.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.source-over.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.transparent.source-over</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.xor.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.xor.html index bbab8a0..fcb1f77 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.xor.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.transparent.xor.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.transparent.xor</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.fill.copy.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.fill.copy.html index 0ff9d851dd..62d9b68 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.fill.copy.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.fill.copy.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.uncovered.fill.copy</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.fill.destination-atop.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.fill.destination-atop.html index 2d2f92ed..07c87f8 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.fill.destination-atop.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.fill.destination-atop.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.uncovered.fill.destination-atop</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.fill.destination-in.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.fill.destination-in.html index 5670b32..badd41313 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.fill.destination-in.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.fill.destination-in.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.uncovered.fill.destination-in</title> <meta name="timeout" content="long"> <script src="/resources/testharness.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.fill.source-in.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.fill.source-in.html index 58347442..80c77bd 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.fill.source-in.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.fill.source-in.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.uncovered.fill.source-in</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.fill.source-out.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.fill.source-out.html index ea44ca4..05a3b962 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.fill.source-out.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.fill.source-out.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.uncovered.fill.source-out</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.image.copy.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.image.copy.html index 0ecb5ed0..4311bb3 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.image.copy.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.image.copy.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.uncovered.image.copy</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.image.destination-atop.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.image.destination-atop.html index 00a4465..6453ff3c 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.image.destination-atop.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.image.destination-atop.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.uncovered.image.destination-atop</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.image.destination-in.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.image.destination-in.html index f5f8c68..aebd6f8 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.image.destination-in.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.image.destination-in.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.uncovered.image.destination-in</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.image.source-in.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.image.source-in.html index 2e1fe84..95d23038 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.image.source-in.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.image.source-in.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.uncovered.image.source-in</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.image.source-out.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.image.source-out.html index 1f5be066..573ab8ac 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.image.source-out.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.image.source-out.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.uncovered.image.source-out</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.nocontext.copy.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.nocontext.copy.html index 10a9960..50243ce4 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.nocontext.copy.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.nocontext.copy.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.uncovered.nocontext.copy</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.nocontext.destination-atop.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.nocontext.destination-atop.html index ead1299..0c4e8cb 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.nocontext.destination-atop.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.nocontext.destination-atop.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.uncovered.nocontext.destination-atop</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.nocontext.destination-in.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.nocontext.destination-in.html index 0322bfe2..0258ed8 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.nocontext.destination-in.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.nocontext.destination-in.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.uncovered.nocontext.destination-in</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.nocontext.source-in.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.nocontext.source-in.html index 0d93a036..1f081e43 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.nocontext.source-in.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.nocontext.source-in.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.uncovered.nocontext.source-in</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.nocontext.source-out.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.nocontext.source-out.html index b6ab8cbd..93fdb52b 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.nocontext.source-out.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.nocontext.source-out.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.uncovered.nocontext.source-out</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.pattern.copy.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.pattern.copy.html index c698c251..bf15282 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.pattern.copy.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.pattern.copy.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.uncovered.pattern.copy</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.pattern.destination-atop.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.pattern.destination-atop.html index 887570f..015d6b6 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.pattern.destination-atop.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.pattern.destination-atop.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.uncovered.pattern.destination-atop</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.pattern.destination-in.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.pattern.destination-in.html index 7aa9e66..2747f85 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.pattern.destination-in.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.pattern.destination-in.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.uncovered.pattern.destination-in</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.pattern.source-in.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.pattern.source-in.html index 3830e92..edcd6bf6 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.pattern.source-in.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.pattern.source-in.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.uncovered.pattern.source-in</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.pattern.source-out.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.pattern.source-out.html index 3c202dd..35e7b58 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.pattern.source-out.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/compositing/2d.composite.uncovered.pattern.source-out.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.composite.uncovered.pattern.source-out</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-1.html index 222d7f6..a3f2d64 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.css-color-4-hsl-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-2.html index b2c93c1..1a463fd 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.css-color-4-hsl-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-3.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-3.html index fc87269..c8259c64 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-3.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-3.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.css-color-4-hsl-3</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-4.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-4.html index 71cb327..76cdabe 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-4.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-4.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.css-color-4-hsl-4</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-5.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-5.html index 787d5e76..302a4d6 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-5.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-5.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.css-color-4-hsl-5</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-6.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-6.html index 8acc67f..5aa69c4 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-6.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-6.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.css-color-4-hsl-6</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-7.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-7.html index dc295d0..08d700b4 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-7.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-7.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.css-color-4-hsl-7</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-8.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-8.html index 50970585..cb0d0f7 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-8.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-8.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.css-color-4-hsl-8</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-9.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-9.html index 47cd157c..4d8c741 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-9.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsl-9.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.css-color-4-hsl-9</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-1.html index 2d1e46f..e6ef6db 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.css-color-4-hsla-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-2.html index f5531f6..62e6435 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.css-color-4-hsla-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-3.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-3.html index fde2328..e0a860cd 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-3.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-3.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.css-color-4-hsla-3</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-4.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-4.html index 3b6e1f13..efc6760 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-4.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-4.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.css-color-4-hsla-4</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-5.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-5.html index b0677c16..25ceb2f 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-5.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-5.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.css-color-4-hsla-5</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-6.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-6.html index 809d11c..578e37e 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-6.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-6.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.css-color-4-hsla-6</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-7.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-7.html index 48c3c69..728f90d2 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-7.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-7.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.css-color-4-hsla-7</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-8.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-8.html index f49b313..714569f 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-8.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-8.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.css-color-4-hsla-8</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-9.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-9.html index 68c4e22..5016f84 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-9.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-hsla-9.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.css-color-4-hsla-9</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-1.html index c9d75ca..ad28d26 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.css-color-4-rgb-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-2.html index 0acc23e..0fc785e 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.css-color-4-rgb-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-3.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-3.html index 85c2606c..e06440a4 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-3.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-3.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.css-color-4-rgb-3</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-4.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-4.html index e028260e..3368cecd 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-4.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-4.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.css-color-4-rgb-4</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-5.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-5.html index 51ace91..e23e7b9 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-5.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-5.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.css-color-4-rgb-5</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-6.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-6.html index 6df2f914..2632706 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-6.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgb-6.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.css-color-4-rgb-6</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-1.html index 19d726e..85cb76d 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.css-color-4-rgba-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-2.html index 1603ae93..981213a6 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.css-color-4-rgba-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-3.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-3.html index 53ad717..87d19daf 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-3.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-3.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.css-color-4-rgba-3</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-4.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-4.html index 3dc9f9c..1aec9f78 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-4.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-4.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.css-color-4-rgba-4</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-5.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-5.html index db0e891f..aa3cea6c 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-5.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-5.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.css-color-4-rgba-5</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-6.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-6.html index c4ec462..0e02f26 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-6.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.css-color-4-rgba-6.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.css-color-4-rgba-6</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hex3.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hex3.html index 90c4d4f..a536ae57 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hex3.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hex3.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.hex3</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hex4.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hex4.html index 8a6260fa..3e788a7 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hex4.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hex4.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.hex4</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hex6.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hex6.html index 02f698e..162ec89 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hex6.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hex6.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.hex6</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hex8.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hex8.html index 1563bab..7be693fe 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hex8.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hex8.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.hex8</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsl-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsl-1.html index 96e6515..c057f4f1 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsl-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsl-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.hsl-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsl-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsl-2.html index b6f8f2b..ff1258ac 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsl-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsl-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.hsl-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsl-3.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsl-3.html index 5ed3b96..2a6e4588 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsl-3.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsl-3.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.hsl-3</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsl-4.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsl-4.html index f91edd7..fffe940 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsl-4.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsl-4.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.hsl-4</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsl-5.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsl-5.html index c4624da..49a274e 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsl-5.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsl-5.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.hsl-5</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsl-6.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsl-6.html index 5baa5b3..76a42ad8 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsl-6.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsl-6.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.hsl-6</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-negative-saturation.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-negative-saturation.html index 6927767..4165c097 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-negative-saturation.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-negative-saturation.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.hsl-clamp-negative-saturation</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-1.html index 67a65da..0ce6677 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.hsla-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-2.html index c63fac5..6b0fbad 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.hsla-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-1.html index 5d73d34c..38baff2 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.hsla-clamp-alpha-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-2.html index eaf7a6a..38c2b015 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-alpha-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.hsla-clamp-alpha-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-negative-saturation.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-negative-saturation.html index 04749fb..f3df5ae6 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-negative-saturation.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-negative-saturation.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.hsla-clamp-negative-saturation</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.html4.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.html4.html index fc1c1af..66f4392 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.html4.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.html4.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.html4</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsl-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsl-1.html index 3edffc6d..2b6482a7 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsl-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsl-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.css-color-4-hsl-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsl-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsl-2.html index 477b318..e112313 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsl-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsl-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.css-color-4-hsl-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsl-3.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsl-3.html index e209266..1c4f25e5 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsl-3.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsl-3.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.css-color-4-hsl-3</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsl-4.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsl-4.html index 5bcc175..47e292fe 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsl-4.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsl-4.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.css-color-4-hsl-4</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsl-5.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsl-5.html index ba465408..07dc187 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsl-5.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsl-5.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.css-color-4-hsl-5</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsla-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsla-1.html index a5f8f3f..2d95b05 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsla-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsla-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.css-color-4-hsla-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsla-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsla-2.html index bd54322..71e7c69 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsla-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsla-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.css-color-4-hsla-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsla-3.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsla-3.html index e33b9415..0ae09a5 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsla-3.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-hsla-3.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.css-color-4-hsla-3</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgb-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgb-1.html index 8fbbc7a..0735285 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgb-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgb-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.css-color-4-rgb-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgb-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgb-2.html index adc82974..f56e5e86 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgb-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgb-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.css-color-4-rgb-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgb-3.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgb-3.html index 4d385d5..adf4bd00 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgb-3.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgb-3.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.css-color-4-rgb-3</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgb-4.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgb-4.html index 6b855b43..481c9698 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgb-4.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgb-4.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.css-color-4-rgb-4</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgb-5.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgb-5.html index 13fadb9..5fcb82e 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgb-5.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgb-5.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.css-color-4-rgb-5</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgba-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgba-1.html index 5353f77..02e1f8df 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgba-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgba-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.css-color-4-rgba-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgba-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgba-2.html index aaa555a..e4c909f 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgba-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgba-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.css-color-4-rgba-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgba-3.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgba-3.html index e8c0588..d8e4d95 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgba-3.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.css-color-4-rgba-3.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.css-color-4-rgba-3</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex1.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex1.html index 28a7ff473..1dcb851a 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.hex1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex2.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex2.html index 0dcf0f8..12116de2b 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.hex2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex3.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex3.html index 8e1bd9fa..0f3c01d 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex3.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex3.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.hex3</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex4.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex4.html index f59991d3..63d6225 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex4.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex4.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.hex4</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex5.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex5.html index 9567114..416e9bfa 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex5.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex5.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.hex5</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex6.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex6.html index b36d0c86..4653e58 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex6.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex6.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.hex6</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex7.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex7.html index 5b38e78..dc65056 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex7.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex7.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.hex7</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex8.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex8.html index 1eda0c7..77f150d9 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex8.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex8.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.hex8</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-1.html index 9ff3c68..3b6a8ca 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.hsl-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-2.html index 46fac5f..932626cb 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.hsl-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-3.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-3.html index 1f05e8d..b721588 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-3.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-3.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.hsl-3</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-4.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-4.html index dd2cec79..a02de5c 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-4.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-4.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.hsl-4</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-5.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-5.html index 909e230b1..1d00de2 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-5.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-5.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.hsl-5</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-6.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-6.html index 9bb652c..c36817f 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-6.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-6.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.hsl-6</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsla-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsla-1.html index 9b553c6..5362f472 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsla-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsla-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.hsla-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsla-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsla-2.html index d894bc42..86b77558 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsla-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsla-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.hsla-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsla-3.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsla-3.html index 8901a112..8faaa595a 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsla-3.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsla-3.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.hsla-3</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-1.html index ceb6c53a..4b387735 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.name-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-2.html index 684a6655..335b4da 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.name-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-3.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-3.html index ebf508f..506e0ab 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-3.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-3.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.name-3</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-4.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-4.html index ba1f71b..6df03a7 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-4.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-4.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.name-4</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-5.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-5.html index a889a387..a4f393b 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-5.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-5.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.name-5</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-1.html index e1fb32a..4a2fb7c 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.rgb-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-2.html index 54d7daf..fb40d0ed 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.rgb-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-3.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-3.html index 9874fc6..dff626a 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-3.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-3.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.rgb-3</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-1.html index fbfa4ba..b8cf07f7 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.rgba-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-2.html index 43cd1763c..d8284256 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.rgba-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-3.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-3.html index 9695522..ea7332e 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-3.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-3.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.rgba-3</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-4.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-4.html index 9334d69..afdb2d84 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-4.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-4.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.rgba-4</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-5.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-5.html index 7b53652..a1206519 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-5.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-5.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.invalid.rgba-5</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-1.html index c9e9e4c..8f3a1e06 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.rgb-clamp-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-2.html index 98df8d67..41d06f2 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.rgb-clamp-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-3.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-3.html index 70f5ed0..60cddd69 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-3.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-3.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.rgb-clamp-3</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-4.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-4.html index 1f387998..8d3a767 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-4.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-4.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.rgb-clamp-4</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-5.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-5.html index c2ac0b94..3b4f629 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-5.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-5.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.rgb-clamp-5</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgb-eof.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgb-eof.html index 2979d7d..7361ea9a 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgb-eof.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgb-eof.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.rgb-eof</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgb-num.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgb-num.html index 67ba77f..ac52aaf 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgb-num.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgb-num.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.rgb-num</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgb-percent.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgb-percent.html index 8fe3be55..62cd80f 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgb-percent.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgb-percent.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.rgb-percent</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgba-clamp-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgba-clamp-1.html index af3acb9..636f00f 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgba-clamp-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgba-clamp-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.rgba-clamp-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgba-clamp-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgba-clamp-2.html index 32ee979..6409156 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgba-clamp-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgba-clamp-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.rgba-clamp-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgba-eof.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgba-eof.html index baa42cde..25e29f7d 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgba-eof.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgba-eof.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.rgba-eof</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgba-num-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgba-num-1.html index eaa83e18..b71f403 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgba-num-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgba-num-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.rgba-num-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgba-num-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgba-num-2.html index 47bf3ddc..9cc37ef 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgba-num-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgba-num-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.rgba-num-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgba-percent.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgba-percent.html index 068befd..8ea3f8f 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgba-percent.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgba-percent.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.rgba-percent</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-1.html index 0e58836..7debab0 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.rgba-solid-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-2.html index 8da29ee..923bcc9 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.rgba-solid-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-3.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-3.html index e67374c..a26c984f 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-3.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-3.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.rgba-solid-3</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-4.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-4.html index 777aacea..eb10244f 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-4.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-4.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.rgba-solid-4</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.svg-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.svg-1.html index 8dc6844..94f8128 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.svg-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.svg-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.svg-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.svg-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.svg-2.html index 2833565..4eb9963 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.svg-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.svg-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.svg-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.system.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.system.html index 6e12406..28d8f96 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.system.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.system.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.system</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.transparent-1.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.transparent-1.html index a595d70..d5dffed 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.transparent-1.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.transparent-1.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.transparent-1</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.transparent-2.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.transparent-2.html index 0f2a7e0..2d345a5 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.transparent-2.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.parse.transparent-2.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> +<meta charset="UTF-8"> <title>OffscreenCanvas test: 2d.fillStyle.parse.transparent-2</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/tools/templates.yaml b/third_party/blink/web_tests/external/wpt/html/canvas/tools/templates.yaml index 0806872..4ca690e 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/tools/templates.yaml +++ b/third_party/blink/web_tests/external/wpt/html/canvas/tools/templates.yaml
@@ -1,6 +1,7 @@ offscreen: | <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> + <meta charset="UTF-8"> <title>OffscreenCanvas test: %(name)s</title>%(timeout)s <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> @@ -54,6 +55,7 @@ element: | <!DOCTYPE html> <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> + <meta charset="UTF-8"> <title>Canvas test: %(name)s</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/widgets/input-date-whitespace-pre-1.html b/third_party/blink/web_tests/external/wpt/html/rendering/widgets/input-date-whitespace-pre-1.html new file mode 100644 index 0000000..6118987 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/rendering/widgets/input-date-whitespace-pre-1.html
@@ -0,0 +1,10 @@ +<!DOCTYPE html> + +<meta charset="utf-8"> +<title>input type=date test</title> +<meta name="assert" content="CSS white-space property does not disrupt rendering of <input type=date>"> +<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1940063"> +<link rel="match" href="input-date-whitespace-pre-ref.html"> + +<body> +<input type="date" style="white-space: pre">
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/widgets/input-date-whitespace-pre-2.html b/third_party/blink/web_tests/external/wpt/html/rendering/widgets/input-date-whitespace-pre-2.html new file mode 100644 index 0000000..f4b6eba --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/rendering/widgets/input-date-whitespace-pre-2.html
@@ -0,0 +1,9 @@ +<!DOCTYPE html> + +<meta charset="utf-8"> +<title>input type=date test</title> +<meta name="assert" content="CSS white-space property does not disrupt rendering of <input type=date>"> +<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1940063"> +<link rel="match" href="input-date-whitespace-pre-ref.html"> + +<body style="white-space: pre"><input type="date">
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/widgets/input-date-whitespace-pre-ref.html b/third_party/blink/web_tests/external/wpt/html/rendering/widgets/input-date-whitespace-pre-ref.html new file mode 100644 index 0000000..64f0162 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/rendering/widgets/input-date-whitespace-pre-ref.html
@@ -0,0 +1,7 @@ +<!DOCTYPE html> + +<meta charset="utf-8"> +<title>input type=date reference</title> + +<body> +<input type="date">
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-input-element/radio-disconnected-group-owner.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-input-element/radio-disconnected-group-owner.html index 60feb2b..8e2c988 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-input-element/radio-disconnected-group-owner.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-input-element/radio-disconnected-group-owner.html
@@ -162,6 +162,50 @@ radio1.checked = true; assert_false(radio2.checked, "Element should no longer be checked"); }, "Disconnected document fragments can serve as radio group containers."); + + test(() => { + const container = document.createElement("div"); + const radio1 = document.createElement("input"); + radio1.type = "radio"; + radio1.name = "group"; + radio1.checked = true; + const radio2 = document.createElement("input"); + radio2.type = "radio"; + radio2.name = "group"; + radio2.checked = true; + + container.appendChild(radio1); + assert_true(radio1.checked, "radio1 should be checked"); + container.appendChild(radio2); + assert_true(radio1.checked, "radio1 should still be checked"); + assert_true(radio2.checked, "radio2 should be checked, too"); + + container.innerHTML = `<input type="radio" name="group" checked><input type="radio" name="group" checked>`; + assert_true(container.children[0].checked, "first radio child should be checked"); + assert_true(container.children[1].checked, "second radio child should be checked"); + }, "Appending input radio input into a disconnect tree don't update the other radio inputs in the same radio group."); + + test(() => { + const form = document.createElement("form"); + const radio1 = document.createElement("input"); + radio1.type = "radio"; + radio1.name = "group"; + radio1.checked = true; + const radio2 = document.createElement("input"); + radio2.type = "radio"; + radio2.name = "group"; + radio2.checked = true; + + form.appendChild(radio1); + assert_true(radio1.checked, "radio1 should be checked"); + form.appendChild(radio2); + assert_false(radio1.checked, "radio1 should no longer be checked"); + assert_true(radio2.checked, "radio2 should be checked"); + + form.innerHTML = `<input type="radio" name="group" checked><input type="radio" name="group" checked>`; + assert_false(form.children[0].checked, "first radio child should no longer be checked"); + assert_true(form.children[1].checked, "second radio child should be checked"); + }, "Appending input radio input into a disconnect form should update the other radio inputs in the same radio group."); </script> </body>
diff --git a/third_party/blink/web_tests/external/wpt/trusted-types/block-string-assignment-to-DOMWindowTimers-setTimeout-setInterval-expected.txt b/third_party/blink/web_tests/external/wpt/trusted-types/block-string-assignment-to-DOMWindowTimers-setTimeout-setInterval-expected.txt deleted file mode 100644 index d56d73fa..0000000 --- a/third_party/blink/web_tests/external/wpt/trusted-types/block-string-assignment-to-DOMWindowTimers-setTimeout-setInterval-expected.txt +++ /dev/null
@@ -1,7 +0,0 @@ -This is a testharness.js-based test. -[FAIL] DedicatedWorkerGlobalScope.setTimeout and DedicatedWorkerGlobalScope.setInterval pass the correct sink to the default policy - assert_equals: expected "Worker setTimeout" but got "WorkerGlobalScope setTimeout" -[FAIL] SharedWorkerGlobalScope.setTimeout and SharedWorkerGlobalScope.setInterval pass the correct sink to the default policy - assert_equals: expected "Worker setTimeout" but got "WorkerGlobalScope setTimeout" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/trusted-types/support/DOMWindowTimers-setTimeout-setInterval.js b/third_party/blink/web_tests/external/wpt/trusted-types/support/DOMWindowTimers-setTimeout-setInterval.js index e03329c..2905c23 100644 --- a/third_party/blink/web_tests/external/wpt/trusted-types/support/DOMWindowTimers-setTimeout-setInterval.js +++ b/third_party/blink/web_tests/external/wpt/trusted-types/support/DOMWindowTimers-setTimeout-setInterval.js
@@ -17,7 +17,7 @@ globalThis.trustedTypes.createPolicy("default", {createScript: (s, _, sink) => { // https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timer-initialisation-steps, // step 9.6.1.1. - const expectedSink = globalThisStr.includes("Window") ? "Window" : "Worker"; + const expectedSink = globalThisStr.includes("Window") ? "Window" : "WorkerGlobalScope"; if (s === "timeoutStringTest") { assert_equals(sink, `${expectedSink} setTimeout`);
diff --git a/third_party/blink/web_tests/external/wpt/trusted-types/support/WorkerGlobalScope-importScripts.https.js b/third_party/blink/web_tests/external/wpt/trusted-types/support/WorkerGlobalScope-importScripts.https.js index a3ecfc48..06548da 100644 --- a/third_party/blink/web_tests/external/wpt/trusted-types/support/WorkerGlobalScope-importScripts.https.js +++ b/third_party/blink/web_tests/external/wpt/trusted-types/support/WorkerGlobalScope-importScripts.https.js
@@ -65,7 +65,7 @@ // Test default policy application: trustedTypes.createPolicy("default", { createScriptURL: (url, _, sink) => { - assert_equals(sink, "Worker importScripts"); + assert_equals(sink, "WorkerGlobalScope importScripts"); return url.replace("play", "work"); } }, true);
diff --git a/third_party/blink/web_tests/external/wpt/trusted-types/support/block-string-assignment-to-DOMWindowTimers-setTimeout-setInterval.js b/third_party/blink/web_tests/external/wpt/trusted-types/support/block-string-assignment-to-DOMWindowTimers-setTimeout-setInterval.js index 3ddefd8d..5660dea 100644 --- a/third_party/blink/web_tests/external/wpt/trusted-types/support/block-string-assignment-to-DOMWindowTimers-setTimeout-setInterval.js +++ b/third_party/blink/web_tests/external/wpt/trusted-types/support/block-string-assignment-to-DOMWindowTimers-setTimeout-setInterval.js
@@ -54,7 +54,7 @@ let policy = globalThis.trustedTypes.createPolicy("default", { createScript: (x, _, sink) => { // https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timer-initialisation-steps, // step 9.6.1.1. - const expectedSink = globalThisStr.includes("Window") ? "Window" : "Worker"; + const expectedSink = globalThisStr.includes("Window") ? "Window" : "WorkerGlobalScope"; if (x === kTimeoutTestString) { assert_equals(sink, `${expectedSink} setTimeout`); } else if (x === kIntervalTestString) {
diff --git a/third_party/blink/web_tests/external/wpt/trusted-types/trusted-types-eval-reporting.html b/third_party/blink/web_tests/external/wpt/trusted-types/trusted-types-eval-reporting.html index fbe9425..0f4d406 100644 --- a/third_party/blink/web_tests/external/wpt/trusted-types/trusted-types-eval-reporting.html +++ b/third_party/blink/web_tests/external/wpt/trusted-types/trusted-types-eval-reporting.html
@@ -85,17 +85,5 @@ return p; }, "Trusted Type violation report: evaluating a Trusted Script."); - promise_test(t => { - let beacon = 'never_overwritten'; - trustedTypes.createPolicy('default', { - createScript: s => s.replace('payload', 'default policy'), - }, true); - let p = promise_flush()(); - eval('beacon="payload"'); - assert_equals(beacon, 'default policy'); - flush(); - return p; - }, "Trusted Type violation report: default policy transforms the script before CSP checks runs."); - </script> </body>
diff --git a/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audionode-interface/different-contexts.html b/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audionode-interface/different-contexts.html index f763d34..0b54c47 100644 --- a/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audionode-interface/different-contexts.html +++ b/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audionode-interface/different-contexts.html
@@ -90,7 +90,7 @@ () => {g2 = new GainNode(c2)}, 'Test 4: g2 = new GainNode(c2)') .notThrow(); should( - () => {g2.disconnect(g1.gain)}, 'Test 4: g2.connect(g1.gain)') + () => {g2.disconnect(g1.gain)}, 'Test 4: g2.disconnect(g1.gain)') .throw(DOMException, 'InvalidAccessError'); task.done(); });
diff --git a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt index 41028d53..31cde90 100644 --- a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt +++ b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -142,6 +142,16 @@ method constructor method throwIfAborted setter onabort +interface AsyncDisposableStack + attribute @@toStringTag + getter disposed + method Symbol(Symbol.asyncDispose) + method adopt + method constructor + method defer + method disposeAsync + method move + method use interface BackgroundFetchEvent : ExtendableEvent attribute @@toStringTag getter registration @@ -524,6 +534,16 @@ getter readable getter writable method constructor +interface DisposableStack + attribute @@toStringTag + getter disposed + method Symbol(Symbol.dispose) + method adopt + method constructor + method defer + method dispose + method move + method use interface ErrorEvent : Event attribute @@toStringTag getter colno @@ -1505,6 +1525,7 @@ method fillRect method fillText method fillTextCluster + method getContextAttributes method getImageData method getLineDash method getTextureFormat @@ -1986,6 +2007,10 @@ method unwrapKey method verify method wrapKey +interface SuppressedError : Error + attribute message + attribute name + method constructor interface SyncEvent : ExtendableEvent attribute @@toStringTag getter lastChance
diff --git a/third_party/blink/web_tests/http/tests/shadowrealm/webexposed/global-interface-listing-shadow-realm-expected.txt b/third_party/blink/web_tests/http/tests/shadowrealm/webexposed/global-interface-listing-shadow-realm-expected.txt index d68c8e8..3ead062 100644 --- a/third_party/blink/web_tests/http/tests/shadowrealm/webexposed/global-interface-listing-shadow-realm-expected.txt +++ b/third_party/blink/web_tests/http/tests/shadowrealm/webexposed/global-interface-listing-shadow-realm-expected.txt
@@ -15,6 +15,16 @@ CONSOLE MESSAGE: method constructor CONSOLE MESSAGE: method throwIfAborted CONSOLE MESSAGE: setter onabort +CONSOLE MESSAGE: interface AsyncDisposableStack +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter disposed +CONSOLE MESSAGE: method Symbol(Symbol.asyncDispose) +CONSOLE MESSAGE: method adopt +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method defer +CONSOLE MESSAGE: method disposeAsync +CONSOLE MESSAGE: method move +CONSOLE MESSAGE: method use CONSOLE MESSAGE: interface ByteLengthQueuingStrategy CONSOLE MESSAGE: attribute @@toStringTag CONSOLE MESSAGE: getter highWaterMark @@ -61,6 +71,16 @@ CONSOLE MESSAGE: getter message CONSOLE MESSAGE: getter name CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface DisposableStack +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter disposed +CONSOLE MESSAGE: method Symbol(Symbol.dispose) +CONSOLE MESSAGE: method adopt +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method defer +CONSOLE MESSAGE: method dispose +CONSOLE MESSAGE: method move +CONSOLE MESSAGE: method use CONSOLE MESSAGE: interface ErrorEvent : Event CONSOLE MESSAGE: attribute @@toStringTag CONSOLE MESSAGE: getter colno @@ -192,6 +212,10 @@ CONSOLE MESSAGE: method constructor CONSOLE MESSAGE: method error CONSOLE MESSAGE: method next +CONSOLE MESSAGE: interface SuppressedError : Error +CONSOLE MESSAGE: attribute message +CONSOLE MESSAGE: attribute name +CONSOLE MESSAGE: method constructor CONSOLE MESSAGE: interface TransformStream CONSOLE MESSAGE: attribute @@toStringTag CONSOLE MESSAGE: getter readable
diff --git a/third_party/blink/web_tests/http/tests/worklet/webexposed/global-interface-listing-audio-worklet-expected.txt b/third_party/blink/web_tests/http/tests/worklet/webexposed/global-interface-listing-audio-worklet-expected.txt index 8b0df25..cc21eb9 100644 --- a/third_party/blink/web_tests/http/tests/worklet/webexposed/global-interface-listing-audio-worklet-expected.txt +++ b/third_party/blink/web_tests/http/tests/worklet/webexposed/global-interface-listing-audio-worklet-expected.txt
@@ -1,5 +1,15 @@ CONSOLE MESSAGE: This test logs exposed APIs from AudioWorkletGlobalScope CONSOLE MESSAGE: [INTERFACES] +CONSOLE MESSAGE: interface AsyncDisposableStack +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter disposed +CONSOLE MESSAGE: method Symbol(Symbol.asyncDispose) +CONSOLE MESSAGE: method adopt +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method defer +CONSOLE MESSAGE: method disposeAsync +CONSOLE MESSAGE: method move +CONSOLE MESSAGE: method use CONSOLE MESSAGE: interface AudioWorkletGlobalScope : WorkletGlobalScope CONSOLE MESSAGE: attribute @@toStringTag CONSOLE MESSAGE: method constructor @@ -17,6 +27,16 @@ CONSOLE MESSAGE: getter highWaterMark CONSOLE MESSAGE: getter size CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface DisposableStack +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter disposed +CONSOLE MESSAGE: method Symbol(Symbol.dispose) +CONSOLE MESSAGE: method adopt +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method defer +CONSOLE MESSAGE: method dispose +CONSOLE MESSAGE: method move +CONSOLE MESSAGE: method use CONSOLE MESSAGE: interface Event CONSOLE MESSAGE: attribute @@toStringTag CONSOLE MESSAGE: attribute AT_TARGET @@ -118,6 +138,10 @@ CONSOLE MESSAGE: method constructor CONSOLE MESSAGE: method read CONSOLE MESSAGE: method releaseLock +CONSOLE MESSAGE: interface SuppressedError : Error +CONSOLE MESSAGE: attribute message +CONSOLE MESSAGE: attribute name +CONSOLE MESSAGE: method constructor CONSOLE MESSAGE: interface TransformStream CONSOLE MESSAGE: attribute @@toStringTag CONSOLE MESSAGE: getter readable
diff --git a/third_party/blink/web_tests/http/tests/worklet/webexposed/global-interface-listing-layout-worklet-expected.txt b/third_party/blink/web_tests/http/tests/worklet/webexposed/global-interface-listing-layout-worklet-expected.txt index 6fd19e0..cc07a62c 100644 --- a/third_party/blink/web_tests/http/tests/worklet/webexposed/global-interface-listing-layout-worklet-expected.txt +++ b/third_party/blink/web_tests/http/tests/worklet/webexposed/global-interface-listing-layout-worklet-expected.txt
@@ -1,5 +1,15 @@ CONSOLE MESSAGE: This test logs exposed APIs from LayoutWorkletGlobalScope CONSOLE MESSAGE: [INTERFACES] +CONSOLE MESSAGE: interface AsyncDisposableStack +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter disposed +CONSOLE MESSAGE: method Symbol(Symbol.asyncDispose) +CONSOLE MESSAGE: method adopt +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method defer +CONSOLE MESSAGE: method disposeAsync +CONSOLE MESSAGE: method move +CONSOLE MESSAGE: method use CONSOLE MESSAGE: interface ByteLengthQueuingStrategy CONSOLE MESSAGE: attribute @@toStringTag CONSOLE MESSAGE: getter highWaterMark @@ -219,6 +229,16 @@ CONSOLE MESSAGE: getter highWaterMark CONSOLE MESSAGE: getter size CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface DisposableStack +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter disposed +CONSOLE MESSAGE: method Symbol(Symbol.dispose) +CONSOLE MESSAGE: method adopt +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method defer +CONSOLE MESSAGE: method dispose +CONSOLE MESSAGE: method move +CONSOLE MESSAGE: method use CONSOLE MESSAGE: interface IntrinsicSizes CONSOLE MESSAGE: attribute @@toStringTag CONSOLE MESSAGE: getter maxContentSize @@ -317,6 +337,10 @@ CONSOLE MESSAGE: method has CONSOLE MESSAGE: method keys CONSOLE MESSAGE: method values +CONSOLE MESSAGE: interface SuppressedError : Error +CONSOLE MESSAGE: attribute message +CONSOLE MESSAGE: attribute name +CONSOLE MESSAGE: method constructor CONSOLE MESSAGE: interface TransformStream CONSOLE MESSAGE: attribute @@toStringTag CONSOLE MESSAGE: getter readable @@ -386,6 +410,16 @@ CONSOLE MESSAGE: method gc CONSOLE MESSAGE: method registerLayout CONSOLE MESSAGE: [INTERFACES] +CONSOLE MESSAGE: interface AsyncDisposableStack +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter disposed +CONSOLE MESSAGE: method Symbol(Symbol.asyncDispose) +CONSOLE MESSAGE: method adopt +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method defer +CONSOLE MESSAGE: method disposeAsync +CONSOLE MESSAGE: method move +CONSOLE MESSAGE: method use CONSOLE MESSAGE: interface ByteLengthQueuingStrategy CONSOLE MESSAGE: attribute @@toStringTag CONSOLE MESSAGE: getter highWaterMark @@ -605,6 +639,16 @@ CONSOLE MESSAGE: getter highWaterMark CONSOLE MESSAGE: getter size CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface DisposableStack +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter disposed +CONSOLE MESSAGE: method Symbol(Symbol.dispose) +CONSOLE MESSAGE: method adopt +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method defer +CONSOLE MESSAGE: method dispose +CONSOLE MESSAGE: method move +CONSOLE MESSAGE: method use CONSOLE MESSAGE: interface IntrinsicSizes CONSOLE MESSAGE: attribute @@toStringTag CONSOLE MESSAGE: getter maxContentSize @@ -703,6 +747,10 @@ CONSOLE MESSAGE: method has CONSOLE MESSAGE: method keys CONSOLE MESSAGE: method values +CONSOLE MESSAGE: interface SuppressedError : Error +CONSOLE MESSAGE: attribute message +CONSOLE MESSAGE: attribute name +CONSOLE MESSAGE: method constructor CONSOLE MESSAGE: interface TransformStream CONSOLE MESSAGE: attribute @@toStringTag CONSOLE MESSAGE: getter readable
diff --git a/third_party/blink/web_tests/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt b/third_party/blink/web_tests/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt index c6a4102..1223737 100644 --- a/third_party/blink/web_tests/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt +++ b/third_party/blink/web_tests/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt
@@ -1,5 +1,15 @@ CONSOLE MESSAGE: This test logs exposed APIs once from each PaintWorkletGlobalScope CONSOLE MESSAGE: [INTERFACES] +CONSOLE MESSAGE: interface AsyncDisposableStack +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter disposed +CONSOLE MESSAGE: method Symbol(Symbol.asyncDispose) +CONSOLE MESSAGE: method adopt +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method defer +CONSOLE MESSAGE: method disposeAsync +CONSOLE MESSAGE: method move +CONSOLE MESSAGE: method use CONSOLE MESSAGE: interface ByteLengthQueuingStrategy CONSOLE MESSAGE: attribute @@toStringTag CONSOLE MESSAGE: getter highWaterMark @@ -222,6 +232,16 @@ CONSOLE MESSAGE: getter highWaterMark CONSOLE MESSAGE: getter size CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface DisposableStack +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter disposed +CONSOLE MESSAGE: method Symbol(Symbol.dispose) +CONSOLE MESSAGE: method adopt +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method defer +CONSOLE MESSAGE: method dispose +CONSOLE MESSAGE: method move +CONSOLE MESSAGE: method use CONSOLE MESSAGE: interface Mesh2DIndexBuffer CONSOLE MESSAGE: attribute @@toStringTag CONSOLE MESSAGE: method constructor @@ -388,6 +408,10 @@ CONSOLE MESSAGE: method has CONSOLE MESSAGE: method keys CONSOLE MESSAGE: method values +CONSOLE MESSAGE: interface SuppressedError : Error +CONSOLE MESSAGE: attribute message +CONSOLE MESSAGE: attribute name +CONSOLE MESSAGE: method constructor CONSOLE MESSAGE: interface TransformStream CONSOLE MESSAGE: attribute @@toStringTag CONSOLE MESSAGE: getter readable @@ -458,6 +482,16 @@ CONSOLE MESSAGE: method gc CONSOLE MESSAGE: method registerPaint CONSOLE MESSAGE: [INTERFACES] +CONSOLE MESSAGE: interface AsyncDisposableStack +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter disposed +CONSOLE MESSAGE: method Symbol(Symbol.asyncDispose) +CONSOLE MESSAGE: method adopt +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method defer +CONSOLE MESSAGE: method disposeAsync +CONSOLE MESSAGE: method move +CONSOLE MESSAGE: method use CONSOLE MESSAGE: interface ByteLengthQueuingStrategy CONSOLE MESSAGE: attribute @@toStringTag CONSOLE MESSAGE: getter highWaterMark @@ -680,6 +714,16 @@ CONSOLE MESSAGE: getter highWaterMark CONSOLE MESSAGE: getter size CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface DisposableStack +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter disposed +CONSOLE MESSAGE: method Symbol(Symbol.dispose) +CONSOLE MESSAGE: method adopt +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method defer +CONSOLE MESSAGE: method dispose +CONSOLE MESSAGE: method move +CONSOLE MESSAGE: method use CONSOLE MESSAGE: interface Mesh2DIndexBuffer CONSOLE MESSAGE: attribute @@toStringTag CONSOLE MESSAGE: method constructor @@ -846,6 +890,10 @@ CONSOLE MESSAGE: method has CONSOLE MESSAGE: method keys CONSOLE MESSAGE: method values +CONSOLE MESSAGE: interface SuppressedError : Error +CONSOLE MESSAGE: attribute message +CONSOLE MESSAGE: attribute name +CONSOLE MESSAGE: method constructor CONSOLE MESSAGE: interface TransformStream CONSOLE MESSAGE: attribute @@toStringTag CONSOLE MESSAGE: getter readable
diff --git a/third_party/blink/web_tests/platform/mac-mac12/external/wpt/FileAPI/BlobURL/cross-partition-navigation.https-expected.txt b/third_party/blink/web_tests/platform/mac-mac12/external/wpt/FileAPI/BlobURL/cross-partition-navigation.https-expected.txt new file mode 100644 index 0000000..0735952 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac12/external/wpt/FileAPI/BlobURL/cross-partition-navigation.https-expected.txt
@@ -0,0 +1,11 @@ +This is a testharness.js-based test. +[FAIL] Blob URL window.open should enforce noopener for a cross-top-level-site navigation + promise_test: Unhandled rejection with value: "Blob URL handle wasn't null in not-same-top-level-site iframe: Navigation handle returns not null" +[FAIL] Blob URL should partition subframe navigation. + promise_test: Unhandled rejection with value: "Blob URL subframe navigation succeeded in not-same-top-level-site iframe." +[FAIL] Blob URL link click should enforce noopener for a cross-top-level-site navigation + promise_test: Unhandled rejection with value: "Blob URL page opener wasn't null in not-same-top-level-site iframe." +[FAIL] Blob URL area element click should enforce noopener for a cross-top-level-site navigation + promise_test: Unhandled rejection with value: "Blob URL page opener wasn't null in not-same-top-level-site iframe." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac-mac13-arm64/external/wpt/FileAPI/BlobURL/cross-partition-navigation.https-expected.txt b/third_party/blink/web_tests/platform/mac-mac13-arm64/external/wpt/FileAPI/BlobURL/cross-partition-navigation.https-expected.txt new file mode 100644 index 0000000..0735952 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac13-arm64/external/wpt/FileAPI/BlobURL/cross-partition-navigation.https-expected.txt
@@ -0,0 +1,11 @@ +This is a testharness.js-based test. +[FAIL] Blob URL window.open should enforce noopener for a cross-top-level-site navigation + promise_test: Unhandled rejection with value: "Blob URL handle wasn't null in not-same-top-level-site iframe: Navigation handle returns not null" +[FAIL] Blob URL should partition subframe navigation. + promise_test: Unhandled rejection with value: "Blob URL subframe navigation succeeded in not-same-top-level-site iframe." +[FAIL] Blob URL link click should enforce noopener for a cross-top-level-site navigation + promise_test: Unhandled rejection with value: "Blob URL page opener wasn't null in not-same-top-level-site iframe." +[FAIL] Blob URL area element click should enforce noopener for a cross-top-level-site navigation + promise_test: Unhandled rejection with value: "Blob URL page opener wasn't null in not-same-top-level-site iframe." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac-mac13/external/wpt/FileAPI/BlobURL/cross-partition-navigation.https-expected.txt b/third_party/blink/web_tests/platform/mac-mac13/external/wpt/FileAPI/BlobURL/cross-partition-navigation.https-expected.txt new file mode 100644 index 0000000..7a01c00 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac13/external/wpt/FileAPI/BlobURL/cross-partition-navigation.https-expected.txt
@@ -0,0 +1,9 @@ +This is a testharness.js-based test. +[FAIL] Blob URL window.open should enforce noopener for a cross-top-level-site navigation + promise_test: Unhandled rejection with value: "Blob URL handle wasn't null in not-same-top-level-site iframe: Navigation handle returns not null" +[FAIL] Blob URL link click should enforce noopener for a cross-top-level-site navigation + promise_test: Unhandled rejection with value: "Blob URL page opener wasn't null in not-same-top-level-site iframe." +[FAIL] Blob URL area element click should enforce noopener for a cross-top-level-site navigation + promise_test: Unhandled rejection with value: "Blob URL page opener wasn't null in not-same-top-level-site iframe." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt index 51ce684..7c0a7fe 100644 --- a/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -24,6 +24,16 @@ method constructor method throwIfAborted setter onabort +interface AsyncDisposableStack + attribute @@toStringTag + getter disposed + method Symbol(Symbol.asyncDispose) + method adopt + method constructor + method defer + method disposeAsync + method move + method use interface BackgroundFetchEvent : ExtendableEvent attribute @@toStringTag getter registration @@ -392,6 +402,16 @@ getter readable getter writable method constructor +interface DisposableStack + attribute @@toStringTag + getter disposed + method Symbol(Symbol.dispose) + method adopt + method constructor + method defer + method dispose + method move + method use interface ErrorEvent : Event attribute @@toStringTag getter colno @@ -1663,6 +1683,10 @@ method unwrapKey method verify method wrapKey +interface SuppressedError : Error + attribute message + attribute name + method constructor interface SyncEvent : ExtendableEvent attribute @@toStringTag getter lastChance
diff --git a/third_party/blink/web_tests/virtual/stable/http/tests/worklet/webexposed/global-interface-listing-audio-worklet-expected.txt b/third_party/blink/web_tests/virtual/stable/http/tests/worklet/webexposed/global-interface-listing-audio-worklet-expected.txt index 47736c8..daaa675 100644 --- a/third_party/blink/web_tests/virtual/stable/http/tests/worklet/webexposed/global-interface-listing-audio-worklet-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/http/tests/worklet/webexposed/global-interface-listing-audio-worklet-expected.txt
@@ -1,5 +1,15 @@ CONSOLE MESSAGE: This test logs exposed APIs from AudioWorkletGlobalScope CONSOLE MESSAGE: [INTERFACES] +CONSOLE MESSAGE: interface AsyncDisposableStack +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter disposed +CONSOLE MESSAGE: method Symbol(Symbol.asyncDispose) +CONSOLE MESSAGE: method adopt +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method defer +CONSOLE MESSAGE: method disposeAsync +CONSOLE MESSAGE: method move +CONSOLE MESSAGE: method use CONSOLE MESSAGE: interface AudioWorkletGlobalScope : WorkletGlobalScope CONSOLE MESSAGE: attribute @@toStringTag CONSOLE MESSAGE: method constructor @@ -17,6 +27,16 @@ CONSOLE MESSAGE: getter highWaterMark CONSOLE MESSAGE: getter size CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface DisposableStack +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter disposed +CONSOLE MESSAGE: method Symbol(Symbol.dispose) +CONSOLE MESSAGE: method adopt +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method defer +CONSOLE MESSAGE: method dispose +CONSOLE MESSAGE: method move +CONSOLE MESSAGE: method use CONSOLE MESSAGE: interface Event CONSOLE MESSAGE: attribute @@toStringTag CONSOLE MESSAGE: attribute AT_TARGET @@ -115,6 +135,10 @@ CONSOLE MESSAGE: method constructor CONSOLE MESSAGE: method read CONSOLE MESSAGE: method releaseLock +CONSOLE MESSAGE: interface SuppressedError : Error +CONSOLE MESSAGE: attribute message +CONSOLE MESSAGE: attribute name +CONSOLE MESSAGE: method constructor CONSOLE MESSAGE: interface TransformStream CONSOLE MESSAGE: attribute @@toStringTag CONSOLE MESSAGE: getter readable
diff --git a/third_party/blink/web_tests/virtual/stable/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt b/third_party/blink/web_tests/virtual/stable/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt index 4dbfd0e..9574c6c 100644 --- a/third_party/blink/web_tests/virtual/stable/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt
@@ -1,5 +1,15 @@ CONSOLE MESSAGE: This test logs exposed APIs once from each PaintWorkletGlobalScope CONSOLE MESSAGE: [INTERFACES] +CONSOLE MESSAGE: interface AsyncDisposableStack +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter disposed +CONSOLE MESSAGE: method Symbol(Symbol.asyncDispose) +CONSOLE MESSAGE: method adopt +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method defer +CONSOLE MESSAGE: method disposeAsync +CONSOLE MESSAGE: method move +CONSOLE MESSAGE: method use CONSOLE MESSAGE: interface ByteLengthQueuingStrategy CONSOLE MESSAGE: attribute @@toStringTag CONSOLE MESSAGE: getter highWaterMark @@ -180,6 +190,16 @@ CONSOLE MESSAGE: getter highWaterMark CONSOLE MESSAGE: getter size CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface DisposableStack +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter disposed +CONSOLE MESSAGE: method Symbol(Symbol.dispose) +CONSOLE MESSAGE: method adopt +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method defer +CONSOLE MESSAGE: method dispose +CONSOLE MESSAGE: method move +CONSOLE MESSAGE: method use CONSOLE MESSAGE: interface PaintRenderingContext2D CONSOLE MESSAGE: attribute @@toStringTag CONSOLE MESSAGE: getter fillStyle @@ -331,6 +351,10 @@ CONSOLE MESSAGE: method has CONSOLE MESSAGE: method keys CONSOLE MESSAGE: method values +CONSOLE MESSAGE: interface SuppressedError : Error +CONSOLE MESSAGE: attribute message +CONSOLE MESSAGE: attribute name +CONSOLE MESSAGE: method constructor CONSOLE MESSAGE: interface TransformStream CONSOLE MESSAGE: attribute @@toStringTag CONSOLE MESSAGE: getter readable @@ -401,6 +425,16 @@ CONSOLE MESSAGE: method gc CONSOLE MESSAGE: method registerPaint CONSOLE MESSAGE: [INTERFACES] +CONSOLE MESSAGE: interface AsyncDisposableStack +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter disposed +CONSOLE MESSAGE: method Symbol(Symbol.asyncDispose) +CONSOLE MESSAGE: method adopt +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method defer +CONSOLE MESSAGE: method disposeAsync +CONSOLE MESSAGE: method move +CONSOLE MESSAGE: method use CONSOLE MESSAGE: interface ByteLengthQueuingStrategy CONSOLE MESSAGE: attribute @@toStringTag CONSOLE MESSAGE: getter highWaterMark @@ -581,6 +615,16 @@ CONSOLE MESSAGE: getter highWaterMark CONSOLE MESSAGE: getter size CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface DisposableStack +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter disposed +CONSOLE MESSAGE: method Symbol(Symbol.dispose) +CONSOLE MESSAGE: method adopt +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method defer +CONSOLE MESSAGE: method dispose +CONSOLE MESSAGE: method move +CONSOLE MESSAGE: method use CONSOLE MESSAGE: interface PaintRenderingContext2D CONSOLE MESSAGE: attribute @@toStringTag CONSOLE MESSAGE: getter fillStyle @@ -732,6 +776,10 @@ CONSOLE MESSAGE: method has CONSOLE MESSAGE: method keys CONSOLE MESSAGE: method values +CONSOLE MESSAGE: interface SuppressedError : Error +CONSOLE MESSAGE: attribute message +CONSOLE MESSAGE: attribute name +CONSOLE MESSAGE: method constructor CONSOLE MESSAGE: interface TransformStream CONSOLE MESSAGE: attribute @@toStringTag CONSOLE MESSAGE: getter readable
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt index 9f5965ae..f85a8447 100644 --- a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -25,6 +25,16 @@ [Worker] method constructor [Worker] method throwIfAborted [Worker] setter onabort +[Worker] interface AsyncDisposableStack +[Worker] attribute @@toStringTag +[Worker] getter disposed +[Worker] method Symbol(Symbol.asyncDispose) +[Worker] method adopt +[Worker] method constructor +[Worker] method defer +[Worker] method disposeAsync +[Worker] method move +[Worker] method use [Worker] interface AudioData [Worker] attribute @@toStringTag [Worker] getter duration @@ -397,6 +407,16 @@ [Worker] attribute PERSISTENT [Worker] attribute TEMPORARY [Worker] method constructor +[Worker] interface DisposableStack +[Worker] attribute @@toStringTag +[Worker] getter disposed +[Worker] method Symbol(Symbol.dispose) +[Worker] method adopt +[Worker] method constructor +[Worker] method defer +[Worker] method dispose +[Worker] method move +[Worker] method use [Worker] interface EncodedAudioChunk [Worker] attribute @@toStringTag [Worker] getter byteLength @@ -1846,6 +1866,10 @@ [Worker] method unwrapKey [Worker] method verify [Worker] method wrapKey +[Worker] interface SuppressedError : Error +[Worker] attribute message +[Worker] attribute name +[Worker] method constructor [Worker] interface SyncManager [Worker] attribute @@toStringTag [Worker] method constructor
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt index 02f2e4a..9d3ba790 100644 --- a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -118,6 +118,16 @@ getter currentTime getter duration method constructor +interface AsyncDisposableStack + attribute @@toStringTag + getter disposed + method Symbol(Symbol.asyncDispose) + method adopt + method constructor + method defer + method disposeAsync + method move + method use interface Attr : Node attribute @@toStringTag getter localName @@ -1638,6 +1648,16 @@ getter type method constructor setter onchange +interface DisposableStack + attribute @@toStringTag + getter disposed + method Symbol(Symbol.dispose) + method adopt + method constructor + method defer + method dispose + method move + method use interface Document : Node static method parseHTMLUnsafe attribute @@toStringTag @@ -8982,6 +9002,10 @@ method unwrapKey method verify method wrapKey +interface SuppressedError : Error + attribute message + attribute name + method constructor interface SyncManager attribute @@toStringTag method constructor
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt index 13e657db..87d5bcf 100644 --- a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -25,6 +25,16 @@ [Worker] method constructor [Worker] method throwIfAborted [Worker] setter onabort +[Worker] interface AsyncDisposableStack +[Worker] attribute @@toStringTag +[Worker] getter disposed +[Worker] method Symbol(Symbol.asyncDispose) +[Worker] method adopt +[Worker] method constructor +[Worker] method defer +[Worker] method disposeAsync +[Worker] method move +[Worker] method use [Worker] interface BackgroundFetchManager [Worker] attribute @@toStringTag [Worker] method constructor @@ -353,6 +363,16 @@ [Worker] getter readable [Worker] getter writable [Worker] method constructor +[Worker] interface DisposableStack +[Worker] attribute @@toStringTag +[Worker] getter disposed +[Worker] method Symbol(Symbol.dispose) +[Worker] method adopt +[Worker] method constructor +[Worker] method defer +[Worker] method dispose +[Worker] method move +[Worker] method use [Worker] interface ErrorEvent : Event [Worker] attribute @@toStringTag [Worker] getter colno @@ -1578,6 +1598,10 @@ [Worker] method unwrapKey [Worker] method verify [Worker] method wrapKey +[Worker] interface SuppressedError : Error +[Worker] attribute message +[Worker] attribute name +[Worker] method constructor [Worker] interface SyncManager [Worker] attribute @@toStringTag [Worker] method constructor
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt index 7ad2195..959b4d0 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -143,6 +143,16 @@ [Worker] method constructor [Worker] method throwIfAborted [Worker] setter onabort +[Worker] interface AsyncDisposableStack +[Worker] attribute @@toStringTag +[Worker] getter disposed +[Worker] method Symbol(Symbol.asyncDispose) +[Worker] method adopt +[Worker] method constructor +[Worker] method defer +[Worker] method disposeAsync +[Worker] method move +[Worker] method use [Worker] interface AudioData [Worker] attribute @@toStringTag [Worker] getter duration @@ -524,6 +534,16 @@ [Worker] attribute PERSISTENT [Worker] attribute TEMPORARY [Worker] method constructor +[Worker] interface DisposableStack +[Worker] attribute @@toStringTag +[Worker] getter disposed +[Worker] method Symbol(Symbol.dispose) +[Worker] method adopt +[Worker] method constructor +[Worker] method defer +[Worker] method dispose +[Worker] method move +[Worker] method use [Worker] interface EncodedAudioChunk [Worker] attribute @@toStringTag [Worker] getter byteLength @@ -1602,6 +1622,7 @@ [Worker] method fillRect [Worker] method fillText [Worker] method fillTextCluster +[Worker] method getContextAttributes [Worker] method getImageData [Worker] method getLineDash [Worker] method getTextureFormat @@ -2190,6 +2211,10 @@ [Worker] method unwrapKey [Worker] method verify [Worker] method wrapKey +[Worker] interface SuppressedError : Error +[Worker] attribute message +[Worker] attribute name +[Worker] method constructor [Worker] interface SyncManager [Worker] attribute @@toStringTag [Worker] method constructor
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt index 0864526..f38fb83 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -241,6 +241,16 @@ getter duration method constructor method getCurrentTime +interface AsyncDisposableStack + attribute @@toStringTag + getter disposed + method Symbol(Symbol.asyncDispose) + method adopt + method constructor + method defer + method disposeAsync + method move + method use interface Attr : Node attribute @@toStringTag getter localName @@ -1964,6 +1974,16 @@ getter type method constructor method toString +interface DisposableStack + attribute @@toStringTag + getter disposed + method Symbol(Symbol.dispose) + method adopt + method constructor + method defer + method dispose + method move + method use interface Document : Node static method parseHTML static method parseHTMLUnsafe @@ -6972,6 +6992,7 @@ method fillRect method fillText method fillTextCluster + method getContextAttributes method getImageData method getLineDash method getTextureFormat @@ -9816,6 +9837,10 @@ method unwrapKey method verify method wrapKey +interface SuppressedError : Error + attribute message + attribute name + method constructor interface SyncManager attribute @@toStringTag method constructor
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt index 4e74585..18fa309 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -143,6 +143,16 @@ [Worker] method constructor [Worker] method throwIfAborted [Worker] setter onabort +[Worker] interface AsyncDisposableStack +[Worker] attribute @@toStringTag +[Worker] getter disposed +[Worker] method Symbol(Symbol.asyncDispose) +[Worker] method adopt +[Worker] method constructor +[Worker] method defer +[Worker] method disposeAsync +[Worker] method move +[Worker] method use [Worker] interface BackgroundFetchManager [Worker] attribute @@toStringTag [Worker] method constructor @@ -480,6 +490,16 @@ [Worker] getter readable [Worker] getter writable [Worker] method constructor +[Worker] interface DisposableStack +[Worker] attribute @@toStringTag +[Worker] getter disposed +[Worker] method Symbol(Symbol.dispose) +[Worker] method adopt +[Worker] method constructor +[Worker] method defer +[Worker] method dispose +[Worker] method move +[Worker] method use [Worker] interface ErrorEvent : Event [Worker] attribute @@toStringTag [Worker] getter colno @@ -1437,6 +1457,7 @@ [Worker] method fillRect [Worker] method fillText [Worker] method fillTextCluster +[Worker] method getContextAttributes [Worker] method getImageData [Worker] method getLineDash [Worker] method getTextureFormat @@ -1892,6 +1913,10 @@ [Worker] method unwrapKey [Worker] method verify [Worker] method wrapKey +[Worker] interface SuppressedError : Error +[Worker] attribute message +[Worker] attribute name +[Worker] method constructor [Worker] interface SyncManager [Worker] attribute @@toStringTag [Worker] method constructor
diff --git a/third_party/boringssl/src b/third_party/boringssl/src index 305e5c5..571a743 160000 --- a/third_party/boringssl/src +++ b/third_party/boringssl/src
@@ -1 +1 @@ -Subproject commit 305e5c570be4b142e8590d37dd9136b60f12b9bc +Subproject commit 571a7432a19592c620fa316abde47770dad4f82b
diff --git a/third_party/chromium-variations b/third_party/chromium-variations index ad31f7e..c9db27d 160000 --- a/third_party/chromium-variations +++ b/third_party/chromium-variations
@@ -1 +1 @@ -Subproject commit ad31f7ef5295293b73ada2c9da59fb550429061e +Subproject commit c9db27d92e6a8f2428ca22f77ecc7942b35902f2
diff --git a/third_party/depot_tools b/third_party/depot_tools index 4c54361..9a91427 160000 --- a/third_party/depot_tools +++ b/third_party/depot_tools
@@ -1 +1 @@ -Subproject commit 4c54361841933e29ec19a3104e4f11f0e898674a +Subproject commit 9a9142793a90d65cd1424f6826be89ec15bfa233
diff --git a/third_party/devtools-frontend/src b/third_party/devtools-frontend/src index f606d0b..0783a8d 160000 --- a/third_party/devtools-frontend/src +++ b/third_party/devtools-frontend/src
@@ -1 +1 @@ -Subproject commit f606d0ba4b8e681aab76ac63a1b643366de1aaa2 +Subproject commit 0783a8d746d9264a8ee949cca7549ddff26d49cb
diff --git a/third_party/libc++abi/src b/third_party/libc++abi/src index cbada99..8205ccf0 160000 --- a/third_party/libc++abi/src +++ b/third_party/libc++abi/src
@@ -1 +1 @@ -Subproject commit cbada99a33f015cb8333d63a88ff0c10cbbc6f38 +Subproject commit 8205ccf0f23545ebcd8846363ea1d29e77917a22
diff --git a/third_party/llvm-libc/src b/third_party/llvm-libc/src index 96cdfc1..b90022f 160000 --- a/third_party/llvm-libc/src +++ b/third_party/llvm-libc/src
@@ -1 +1 @@ -Subproject commit 96cdfc15f0f8fc44cf40bd264278c09a5c243819 +Subproject commit b90022fc6a2c5309fae1a48d6db26bcd655cdb37
diff --git a/third_party/pdfium b/third_party/pdfium index 3cd0a26..aacaea1 160000 --- a/third_party/pdfium +++ b/third_party/pdfium
@@ -1 +1 @@ -Subproject commit 3cd0a262ce17171069d69eb839a0ab9f284c329c +Subproject commit aacaea19d27cf8eca108348fe1e94dc03fc4aee8
diff --git a/third_party/perfetto b/third_party/perfetto index efc96bb..17e065a 160000 --- a/third_party/perfetto +++ b/third_party/perfetto
@@ -1 +1 @@ -Subproject commit efc96bb32403e5bd6200905cfb2b855d6e33959a +Subproject commit 17e065a2f2b5997ed31042edbc7a73e639fe6bd3
diff --git a/third_party/skia b/third_party/skia index e7b8d07..123e9e7 160000 --- a/third_party/skia +++ b/third_party/skia
@@ -1 +1 @@ -Subproject commit e7b8d078851fd505475fe74359e31a421e6968ea +Subproject commit 123e9e755027e173fc3dc63ea0a9fd28d1dc81ce
diff --git a/third_party/widevine/cdm/widevine.gni b/third_party/widevine/cdm/widevine.gni index 8b97b7a..e31de0a 100644 --- a/third_party/widevine/cdm/widevine.gni +++ b/third_party/widevine/cdm/widevine.gni
@@ -39,8 +39,7 @@ enable_widevine && enable_library_cdms && library_widevine_cdm_available # Widevine CDM can be deployed as a component. Currently only supported on -# desktop platforms. Not enabled for lacros (as it is changing to use the -# ash updated version). The CDM can be bundled regardless whether it's a +# desktop platforms. The CDM can be bundled regardless whether it's a # component. See below. enable_widevine_cdm_component = enable_library_widevine_cdm &&
diff --git a/tools/gritsettings/resource_ids.spec b/tools/gritsettings/resource_ids.spec index 154c0fed3..e7160e66 100644 --- a/tools/gritsettings/resource_ids.spec +++ b/tools/gritsettings/resource_ids.spec
@@ -1016,6 +1016,10 @@ "META": {"sizes": {"includes": [10]}}, "includes": [7360], }, + "<(SHARED_INTERMEDIATE_DIR)/components/management/resources/resources.grd": { + "META": {"sizes": {"includes": [5]}}, + "includes": [7370], + }, "<(SHARED_INTERMEDIATE_DIR)/components/metrics/debug/resources.grd": { "META": {"sizes": {"includes": [15]}}, "includes": [7380],
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 415b2404..4d460c86 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -10689,7 +10689,7 @@ <int value="4973" label="V8ModelGenericSession_Destroy_Method"/> <int value="4974" label="UsedDeviceScaleAdjustment"/> <int value="4975" label="OBSOLETE_DisableThirdPartyStoragePartitioning2"/> - <int value="4976" label="LinkRelPayment"/> + <int value="4976" label="LinkRelFacilitatedPayment"/> <int value="4977" label="OBSOLETE_V8GPUAdapter_RequestAdapterInfo_Method"/> <int value="4978" label="OBSOLETE_V8ModelGenericSession_Destroy_Method"/> <int value="4979" label="OBSOLETE_V8AITextSession_Execute_Method"/> @@ -17320,6 +17320,7 @@ <int value="-1261972671" label="OmniboxDocumentProvider:disabled"/> <int value="-1261263046" label="RemoveUsageOfDeprecatedGaiaSigninEndpoint:disabled"/> + <int value="-1261165904" label="PermissionsAIv1:enabled"/> <int value="-1261110018" label="AllowDisableTouchpadHapticFeedback:disabled"/> <int value="-1260211490" label="FastPairLowPower:disabled"/> <int value="-1259901957" label="VrBrowserKeyboard:disabled"/> @@ -22654,6 +22655,7 @@ <int value="867061581" label="AllowWindowDragUsingSystemDragDrop:enabled"/> <int value="867512869" label="mark-non-secure-as"/> <int value="868009556" label="AutofillUpstream:enabled"/> + <int value="868791094" label="PermissionsAIv1:disabled"/> <int value="868879861" label="TpcdMetadataGrants:disabled"/> <int value="869531646" label="enable-session-crashed-bubble"/> <int value="869770301" label="MessagesForAndroidPasswords:enabled"/>
diff --git a/tools/metrics/histograms/metadata/collaboration_service/enums.xml b/tools/metrics/histograms/metadata/collaboration_service/enums.xml index b78d881..64a07c8 100644 --- a/tools/metrics/histograms/metadata/collaboration_service/enums.xml +++ b/tools/metrics/histograms/metadata/collaboration_service/enums.xml
@@ -31,6 +31,9 @@ <enum name="CollaborationServiceJoinEvent"> <int value="0" label="Unknown"/> <int value="1" label="Started"/> + <int value="2" label="Canceled - after sign in requirement"/> + <int value="3" label="Canceled - due to sign in requirement"/> + <int value="4" label="Not signed in on join attempt"/> </enum> <!-- LINT.ThenChange(//components/collaboration/internal/metrics.h:CollaborationServiceJoinEvent) -->
diff --git a/tools/metrics/histograms/metadata/gpu/histograms.xml b/tools/metrics/histograms/metadata/gpu/histograms.xml index dd6e544..0ad4ad2 100644 --- a/tools/metrics/histograms/metadata/gpu/histograms.xml +++ b/tools/metrics/histograms/metadata/gpu/histograms.xml
@@ -1418,17 +1418,6 @@ </summary> </histogram> -<histogram name="GPU.SharedImage.ContentConsumed" enum="BooleanMatched" - expires_after="2025-07-13"> - <owner>penghuang@chromium.org</owner> - <owner>chrome-gpu-metric-alerts@chromium.org</owner> - <summary> - Whether or not the content of a SharedImage is consumed. False indicates the - content of a SharedImage is never used due to destroying the SharedImage or - writing new content to it before using it. - </summary> -</histogram> - <histogram name="GPU.SharedImage.SharedImageFormat" enum="SharedImageFormatUMA" expires_after="2026-02-01"> <owner>hitawala@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/lens/enums.xml b/tools/metrics/histograms/metadata/lens/enums.xml index 3dd529f7..99153b0 100644 --- a/tools/metrics/histograms/metadata/lens/enums.xml +++ b/tools/metrics/histograms/metadata/lens/enums.xml
@@ -26,6 +26,20 @@ <enums> +<!-- LINT.IfChange(LensOverlayContextMenuOption) --> + +<enum name="LensOverlayContextMenuOption"> + <summary>The context menu option that was shown in the Lens Overlay.</summary> + <int value="0" label="Copy text"/> + <int value="1" label="Translate text"/> + <int value="2" label="Select text in region"/> + <int value="3" label="Translate text in region"/> + <int value="4" label="Copy as image"/> + <int value="5" label="Save as image"/> +</enum> + +<!-- LINT.ThenChange(//chrome/browser/resources/lens/overlay/metrics_utils.ts:ContextMenuOption) --> + <!-- LINT.IfChange(LensOverlayDismissalSource) --> <enum name="LensOverlayDismissalSource">
diff --git a/tools/metrics/histograms/metadata/lens/histograms.xml b/tools/metrics/histograms/metadata/lens/histograms.xml index e2c5f68..30175ef4 100644 --- a/tools/metrics/histograms/metadata/lens/histograms.xml +++ b/tools/metrics/histograms/metadata/lens/histograms.xml
@@ -120,6 +120,20 @@ </histogram> <histogram + name="Lens.Overlay.ByInvocationSource.{InvocationSource}.ContextMenuOption.Shown" + enum="LensOverlayContextMenuOption" expires_after="2025-07-06"> + <owner>hujasonx@chromium.org</owner> + <owner>lens-chrome@google.com</owner> + <summary> + Recorded once when a context menu option is shown in the Lens overlay. This + is triggered when the user selects a region of the page, or after the user + right-clicks to restore an already-used context menu. This histogram is + sliced by invocation source. + </summary> + <token key="InvocationSource" variants="InvocationSources"/> +</histogram> + +<histogram name="Lens.Overlay.ByInvocationSource.{InvocationSource}.InvocationResultedInSearch" enum="Boolean" expires_after="2025-07-06"> <owner>jdonnelly@chromium.org</owner> @@ -195,6 +209,17 @@ <token key="PageContentType" variants="MimeTypes"/> </histogram> +<histogram name="Lens.Overlay.ContextMenuOption.Shown" + enum="LensOverlayContextMenuOption" expires_after="2025-07-06"> + <owner>hujasonx@chromium.org</owner> + <owner>lens-chrome@google.com</owner> + <summary> + Recorded once when a context menu option is shown in the Lens overlay. This + is triggered when the user selects a region of the page, or after the user + right-clicks to restore an already-used context menu. + </summary> +</histogram> + <histogram name="Lens.Overlay.ContextualSearchBox.ByPageContentType.{PageContentType}.FocusedInSession" enum="Boolean" expires_after="2025-05-06">
diff --git a/tools/metrics/histograms/metadata/media/enums.xml b/tools/metrics/histograms/metadata/media/enums.xml index 93a69bc..0194cf4 100644 --- a/tools/metrics/histograms/metadata/media/enums.xml +++ b/tools/metrics/histograms/metadata/media/enums.xml
@@ -1059,12 +1059,6 @@ <int value="3" label="Failed using photo stream"/> </enum> -<enum name="LacrosBundledWidevine"> - <int value="0" label="None found"/> - <int value="1" label="Lacros bundled"/> - <int value="2" label="Ash bundled"/> -</enum> - <enum name="MakeAudioStreamStatus"> <int value="0" label="Success"/> <int value="1" label="Error: Had switch fail-audio-stream-creation"/>
diff --git a/tools/metrics/histograms/metadata/media/histograms.xml b/tools/metrics/histograms/metadata/media/histograms.xml index b4917bda..7533f44 100644 --- a/tools/metrics/histograms/metadata/media/histograms.xml +++ b/tools/metrics/histograms/metadata/media/histograms.xml
@@ -3282,16 +3282,6 @@ <token key="VideoCodec" variants="VideoCodec"/> </histogram> -<histogram name="Media.EME.Widevine.LacrosBundledCdm" - enum="LacrosBundledWidevine" expires_after="2025-02-27"> - <owner>jrummell@chromium.org</owner> - <owner>media-dev-uma@chromium.org</owner> - <summary> - Reports which Widevine CDM was used by Lacros. Only reported by the browser - process when registering available CDMs during startup. - </summary> -</histogram> - <histogram name="Media.EME.Widevine.SoftwareSecure.SystemCode" enum="CdmSystemCode" expires_after="2025-07-06"> <owner>xhwang@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/optimization/histograms.xml b/tools/metrics/histograms/metadata/optimization/histograms.xml index f154cb8..13a1ded5 100644 --- a/tools/metrics/histograms/metadata/optimization/histograms.xml +++ b/tools/metrics/histograms/metadata/optimization/histograms.xml
@@ -49,6 +49,7 @@ <variant name="TextSafety" summary="Text Safety"/> <variant name="Unknown" summary="Unknown"/> <variant name="WallpaperSearch" summary="Wallpaper search"/> + <variant name="WritingAssistance" summary="Writing Assistance APIs"/> </variants> <variants name="OptimizationTarget"> @@ -78,6 +79,8 @@ summary="Model Execution Feature: Scam Detection"/> <variant name="ModelExecutionFeatureSummarize" summary="Model Execution Feature: Summarize"/> + <variant name="ModelExecutionFeatureWritingAssistanceApi" + summary="Model Execution Feature: Writing Assistance APIs"/> <variant name="ModelValidation" summary="Model validation triggered via CLI"/> <variant name="NewTabPageHistoryClustersModuleRanking" summary="New Tab Page History Clusters Module Ranking"/>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index f7076e5..e7989fb 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -6,7 +6,7 @@ }, "win": { "hash": "970b237fe5e31af7a880a6221a2923db3054f154", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/efc96bb32403e5bd6200905cfb2b855d6e33959a/trace_processor_shell.exe" + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/bec70ee1a566e6bd0c856dc4a46396692c2e6ec1/trace_processor_shell.exe" }, "linux_arm": { "hash": "a15d8362d80cfd7cd8d785cf6afc22586de688cd", @@ -22,7 +22,7 @@ }, "linux": { "hash": "9a272b02446abc0b8546f2fd5b3045d3bd9b2038", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/efc96bb32403e5bd6200905cfb2b855d6e33959a/trace_processor_shell" + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/bec70ee1a566e6bd0c856dc4a46396692c2e6ec1/trace_processor_shell" } }, "power_profile.sql": {
diff --git a/tools/typescript/validate_tsconfig.py b/tools/typescript/validate_tsconfig.py index 772ae2e..756a420e 100644 --- a/tools/typescript/validate_tsconfig.py +++ b/tools/typescript/validate_tsconfig.py
@@ -155,6 +155,7 @@ 'chrome/test/data/webui/chromeos/ash_common', 'chrome/test/data/webui/chromeos/nearby_share', 'chrome/test/data/webui/cr_components/chromeos', + 'components/management/resources', # TODO(crbug.com/373951324): Migrate offline dino game to TypeScript. 'components/neterror/resources', 'components/net_log/resources',
diff --git a/ui/accessibility/accessibility_features.cc b/ui/accessibility/accessibility_features.cc index b8b3f6b6..9c54cbe2 100644 --- a/ui/accessibility/accessibility_features.cc +++ b/ui/accessibility/accessibility_features.cc
@@ -59,6 +59,13 @@ ::features::kAccessibilityPruneRedundantInlineConnectivity); } +BASE_FEATURE(kAccessibilityTreeForViews, + "AccessibilityTreeForViews", + base::FEATURE_DISABLED_BY_DEFAULT); +bool IsAccessibilityTreeForViewsEnabled() { + return base::FeatureList::IsEnabled(::features::kAccessibilityTreeForViews); +} + BASE_FEATURE(kImageDescriptionsAlternateRouting, "ImageDescriptionsAlternateRouting", base::FEATURE_DISABLED_BY_DEFAULT); @@ -90,14 +97,6 @@ ::features::kEnableAccessibilityLanguageDetection); } -BASE_FEATURE(kEnableAccessibilityRestrictiveIA2AXModes, - "AccessibilityRestrictiveIA2AXModes", - base::FEATURE_ENABLED_BY_DEFAULT); -bool IsAccessibilityRestrictiveIA2AXModesEnabled() { - return base::FeatureList::IsEnabled( - ::features::kEnableAccessibilityRestrictiveIA2AXModes); -} - BASE_FEATURE(kExtensionManifestV3NetworkSpeechSynthesis, "ExtensionManifestV3NetworkSpeechSynthesis", base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/ui/accessibility/accessibility_features.h b/ui/accessibility/accessibility_features.h index 76419da2..6d71158 100644 --- a/ui/accessibility/accessibility_features.h +++ b/ui/accessibility/accessibility_features.h
@@ -59,6 +59,10 @@ kAccessibilityPruneRedundantInlineConnectivity); AX_BASE_EXPORT bool IsAccessibilityPruneRedundantInlineConnectivityEnabled(); +// Expose the accessibility tree for views via an AXTree of AXNodes. +AX_BASE_EXPORT BASE_DECLARE_FEATURE(kAccessibilityTreeForViews); +AX_BASE_EXPORT bool IsAccessibilityTreeForViewsEnabled(); + // Use Alternative mechanism for acquiring image descriptions. AX_BASE_EXPORT BASE_DECLARE_FEATURE(kImageDescriptionsAlternateRouting); AX_BASE_EXPORT bool IsImageDescriptionsAlternateRoutingEnabled(); @@ -89,13 +93,6 @@ AX_BASE_EXPORT BASE_DECLARE_FEATURE(kEnableAccessibilityLanguageDetection); AX_BASE_EXPORT bool IsAccessibilityLanguageDetectionEnabled(); -// Restrict AXModes to web content related modes only when an IA2 -// query is performed on a web content node. -// TODO(crbug.com/40266474): Remove flag once the change has been confirmed -// safe. -AX_BASE_EXPORT BASE_DECLARE_FEATURE(kEnableAccessibilityRestrictiveIA2AXModes); -AX_BASE_EXPORT bool IsAccessibilityRestrictiveIA2AXModesEnabled(); - // Extension manifest v3 migration for network speech synthesis. AX_BASE_EXPORT BASE_DECLARE_FEATURE(kExtensionManifestV3NetworkSpeechSynthesis); AX_BASE_EXPORT bool IsExtensionManifestV3NetworkSpeechSynthesisEnabled();
diff --git a/ui/accessibility/platform/ax_platform_node_cocoa.h b/ui/accessibility/platform/ax_platform_node_cocoa.h index 61b0bce..df89eab 100644 --- a/ui/accessibility/platform/ax_platform_node_cocoa.h +++ b/ui/accessibility/platform/ax_platform_node_cocoa.h
@@ -82,6 +82,9 @@ // Returns true if the given action is supported on the node. - (BOOL)hasAction:(ax::mojom::Action)action; +// Performs the given action if supported. +- (BOOL)performAction:(ax::mojom::Action)action; + // Returns all accessibility attribute names. This is analogous to the // deprecated NSAccessibility accessibilityAttributeNames method, which // functions identically when the migration flag is off (see
diff --git a/ui/accessibility/platform/ax_platform_node_cocoa.mm b/ui/accessibility/platform/ax_platform_node_cocoa.mm index b47b4d5..899a46824c 100644 --- a/ui/accessibility/platform/ax_platform_node_cocoa.mm +++ b/ui/accessibility/platform/ax_platform_node_cocoa.mm
@@ -312,6 +312,7 @@ dispatch_once(&onceToken, ^{ dict = @{ @"accessibilityPerformPress" : NSAccessibilityPressAction, + @"accessibilityPerformShowMenu" : NSAccessibilityShowMenuAction, }; }); return dict; @@ -1017,6 +1018,17 @@ return _node->HasAction(action) || HasImplicitAction(*_node, action); } +- (BOOL)performAction:(ax::mojom::Action)action { + if (![self hasAction:action]) { + return NO; + } + + ui::AXActionData data; + data.action = action; + _node->GetDelegate()->AccessibilityPerformAction(data); + return YES; +} + - (AXPlatformNodeCocoa*)fromNodeID:(ui::AXNodeID)id { ui::AXPlatformNode* cell = _node->GetDelegate()->GetFromNodeID(id); if (cell) @@ -1383,15 +1395,25 @@ } - (BOOL)accessibilityPerformPress { - ax::mojom::Action action = ax::mojom::Action::kDoDefault; - if (![self hasAction:action]) { + if (![self instanceActive]) { + return NO; + } + return [self performAction:ax::mojom::Action::kDoDefault]; +} + +- (BOOL)accessibilityPerformShowMenu { + if (![self instanceActive]) { return NO; } - ui::AXActionData data; - data.action = action; - _node->GetDelegate()->AccessibilityPerformAction(data); - return YES; + if (AlsoUseShowMenuActionForDefaultAction(*_node)) { + return [self accessibilityPerformPress]; + } + + if ([self performAction:ax::mojom::Action::kShowContextMenu]) { + return YES; + } + return NO; } - (NSMutableArray*)internalAccessibilityAttributeNames { @@ -2369,11 +2391,6 @@ // Parameterized text-specific attributes. -- (id)AXLineForIndex:(id)parameter { - // TODO: multiline is not supported on views. - return @0; -} - - (id)AXRangeForLine:(id)parameter { if (![parameter isKindOfClass:[NSNumber class]] || [parameter intValue] != 0) return nil; @@ -3287,6 +3304,11 @@ return [[self getAXValueAsString] substringWithRange:range]; } +- (NSInteger)accessibilityLineForIndex:(NSInteger)index { + // TODO: multiline is not supported on views. + return 0; +} + - (NSAttributedString*)accessibilityAttributedStringForRange:(NSRange)range { if (!_node) return nil; @@ -3294,11 +3316,12 @@ return [self AXAttributedStringForRange:[NSValue valueWithRange:range]]; } -- (NSInteger)accessibilityLineForIndex:(NSInteger)index { - if (!_node) - return 0; - - return [[self AXLineForIndex:@(index)] integerValue]; +- (id)AXLineForIndex:(id)parameter { + NSNumber* lineNumber = base::apple::ObjCCast<NSNumber>(parameter); + if (!lineNumber) { + return nil; + } + return @([self accessibilityLineForIndex:[lineNumber intValue]]); } - (NSRange)accessibilityRangeForIndex:(NSInteger)index {
diff --git a/ui/accessibility/platform/ax_platform_node_cocoa_unittest.mm b/ui/accessibility/platform/ax_platform_node_cocoa_unittest.mm index a604262..4c10d59 100644 --- a/ui/accessibility/platform/ax_platform_node_cocoa_unittest.mm +++ b/ui/accessibility/platform/ax_platform_node_cocoa_unittest.mm
@@ -797,6 +797,17 @@ [row node]->GetUniqueId()); } +// accessibilityLineForIndex +TEST_P(AXPlatformNodeCocoaTest, AccessibilityLineForIndex) { + Init(std::string(R"HTML( + ++1 kRootWebArea + ++++2 kStaticText name="heybullfrog" + )HTML")); + + AXPlatformNodeCocoa* text_field = GetCocoaNode(2); + EXPECT_EQ([text_field accessibilityLineForIndex:0], 0); +} + // accessibilityStringForRange TEST_P(AXPlatformNodeCocoaTest, AccessibilityStringForRange) { Init(std::string(R"HTML(
diff --git a/ui/accessibility/platform/ax_platform_node_win.cc b/ui/accessibility/platform/ax_platform_node_win.cc index c3bfd6d..0e98c2d9 100644 --- a/ui/accessibility/platform/ax_platform_node_win.cc +++ b/ui/accessibility/platform/ax_platform_node_win.cc
@@ -5809,11 +5809,6 @@ if (riid == IID_IAccessible2) { for (WinAccessibilityAPIUsageObserver& observer : GetWinAccessibilityAPIUsageObserverList()) { - if (!features::IsAccessibilityRestrictiveIA2AXModesEnabled()) { - observer.OnAdvancedIAccessible2Used(); - continue; - } - if (GetDelegate()->IsWebContent()) { observer.OnAdvancedIAccessible2Used(); } else { @@ -8408,12 +8403,10 @@ void AXPlatformNodeWin::NotifyAddAXModeFlagsForIA2( const uint32_t ax_modes) const { - if (features::IsAccessibilityRestrictiveIA2AXModesEnabled()) { - // Non-web content is always enabled, if a client isn't looking for web - // content, don't enable. - if (!GetDelegate() || !GetDelegate()->IsWebContent()) { - return; - } + // Non-web content is always enabled, if a client isn't looking for web + // content, don't enable. + if (!GetDelegate() || !GetDelegate()->IsWebContent()) { + return; } AXPlatformNode::NotifyAddAXModeFlags(ax_modes);
diff --git a/ui/accessibility/platform/browser_accessibility_cocoa.mm b/ui/accessibility/platform/browser_accessibility_cocoa.mm index e2ddf42..f4ecdaf51 100644 --- a/ui/accessibility/platform/browser_accessibility_cocoa.mm +++ b/ui/accessibility/platform/browser_accessibility_cocoa.mm
@@ -1750,14 +1750,11 @@ textContent.substr(range.location, range.length)); } -- (id)AXLineForIndex:(id)parameter { - DCHECK([parameter isKindOfClass:[NSNumber class]]); - int lineIndex = [(NSNumber*)parameter intValue]; +- (NSInteger)accessibilityLineForIndex:(NSInteger)index { const std::vector<int> lineStarts = _owner->GetIntListAttribute(ax::mojom::IntListAttribute::kLineStarts); - auto iterator = - std::lower_bound(lineStarts.begin(), lineStarts.end(), lineIndex); - return @(std::distance(lineStarts.begin(), iterator)); + auto iterator = std::lower_bound(lineStarts.begin(), lineStarts.end(), index); + return std::distance(lineStarts.begin(), iterator); } - (id)AXRangeForLine:(id)parameter { @@ -1810,11 +1807,6 @@ } if ([attribute - isEqualToString:NSAccessibilityLineForIndexParameterizedAttribute]) { - return [self AXLineForIndex:parameter]; - } - - if ([attribute isEqualToString:NSAccessibilityRangeForLineParameterizedAttribute]) { return [self AXRangeForLine:parameter]; } @@ -2779,6 +2771,16 @@ return YES; } +- (BOOL)accessibilityPerformShowMenu { + if (![self instanceActive]) { + return NO; + } + BrowserAccessibility* actionTarget = [self actionTarget]; + BrowserAccessibilityManager* manager = actionTarget->manager(); + manager->ShowContextMenu(*actionTarget); + return YES; +} + // Returns the description of the given action. - (NSString*)accessibilityActionDescription:(NSString*)action { TRACE_EVENT2("accessibility",
diff --git a/ui/gfx/canvas.cc b/ui/gfx/canvas.cc index 3008881..c38f96d 100644 --- a/ui/gfx/canvas.cc +++ b/ui/gfx/canvas.cc
@@ -478,7 +478,7 @@ return bitmap_.value(); } -bool Canvas::IntersectsClipRect(const SkRect& rect) { +bool Canvas::IntersectsClipRect(const SkRect& rect) const { SkRect clip; return canvas_->getLocalClipBounds(&clip) && clip.intersects(rect); }
diff --git a/ui/gfx/canvas.h b/ui/gfx/canvas.h index fb1e850..b7ef01b 100644 --- a/ui/gfx/canvas.h +++ b/ui/gfx/canvas.h
@@ -430,17 +430,21 @@ // Apply transformation on the canvas. void Transform(const Transform& transform); + // Text will be clipped when the canvas is scaled. See crbug.com/1469229. + // This method prevents clipping by increasing the clip rect size by 0.5f. + void AdjustClipRectForTextBounds(const Rect& text_bounds); + // Note that writing to this bitmap will modify pixels stored in this canvas. SkBitmap GetBitmap() const; + // Tests whether the provided rectangle intersects the current clip rect. + bool IntersectsClipRect(const SkRect& rect) const; + // TODO(enne): rename sk_canvas members and interface. cc::PaintCanvas* sk_canvas() { return canvas_; } float image_scale() const { return image_scale_; } private: - // Tests whether the provided rectangle intersects the current clip rect. - bool IntersectsClipRect(const SkRect& rect); - // Helper for the DrawImageInt functions declared above. The // |remove_image_scale| parameter indicates if the scale of the |image_rep| // should be removed when drawing the image, to avoid double-scaling it.
diff --git a/ui/gfx/canvas_skia.cc b/ui/gfx/canvas_skia.cc index 11d71214..7c6ed0b 100644 --- a/ui/gfx/canvas_skia.cc +++ b/ui/gfx/canvas_skia.cc
@@ -156,16 +156,7 @@ } } -void Canvas::DrawStringRectWithFlags(const std::u16string& text, - const FontList& font_list, - SkColor color, - const Rect& text_bounds, - int flags) { - if (!IntersectsClipRect(RectToSkRect(text_bounds))) - return; - - canvas_->save(); - +void Canvas::AdjustClipRectForTextBounds(const Rect& text_bounds) { gfx::RectF clip_rect(text_bounds); // Pixels on the border of `text_bounds` will get clipped if the @@ -176,6 +167,20 @@ clip_rect.Outset(0.5f); } ClipRect(clip_rect); +} + +void Canvas::DrawStringRectWithFlags(const std::u16string& text, + const FontList& font_list, + SkColor color, + const Rect& text_bounds, + int flags) { + if (!IntersectsClipRect(RectToSkRect(text_bounds))) + return; + + canvas_->save(); + + AdjustClipRectForTextBounds(text_bounds); + Rect rect(text_bounds); std::unique_ptr<RenderText> render_text = RenderText::CreateRenderText();
diff --git a/ui/gl/BUILD.gn b/ui/gl/BUILD.gn index 93bb1e4..5d471a4 100644 --- a/ui/gl/BUILD.gn +++ b/ui/gl/BUILD.gn
@@ -161,6 +161,7 @@ deps = [ ":buildflags", + "//build:android_buildflags", "//mojo/public/cpp/bindings", "//ui/base:ozone_buildflags", "//ui/gfx/mojom",
diff --git a/ui/gl/features.gni b/ui/gl/features.gni index 78cd481..f4f3f98 100644 --- a/ui/gl/features.gni +++ b/ui/gl/features.gni
@@ -20,7 +20,9 @@ # Independent of use_dawn, which controls whether Dawn is used in Chromium. build_dawn_tests = is_mac || is_win || is_linux || is_chromeos || is_android - enable_validating_command_decoder = is_android + # desktop android devices exclusively use angle and thus should not use + # the validating command decoder + enable_validating_command_decoder = is_android && !is_desktop_android } declare_args() {
diff --git a/ui/gl/gl_features.cc b/ui/gl/gl_features.cc index 70cbbcb..8db0302 100644 --- a/ui/gl/gl_features.cc +++ b/ui/gl/gl_features.cc
@@ -29,7 +29,7 @@ namespace features { namespace { -#if BUILDFLAG(IS_ANDROID) +#if BUILDFLAG(IS_ANDROID) && BUILDFLAG(ENABLE_VALIDATING_COMMAND_DECODER) const base::FeatureParam<std::string> kPassthroughCommandDecoderBlockListByBrand{ &kDefaultPassthroughCommandDecoder, "BlockListByBrand", ""};
diff --git a/ui/gl/gl_switches.cc b/ui/gl/gl_switches.cc index 6c02946..34afeacd 100644 --- a/ui/gl/gl_switches.cc +++ b/ui/gl/gl_switches.cc
@@ -4,6 +4,7 @@ #include "ui/gl/gl_switches.h" +#include "build/android_buildflags.h" #include "build/build_config.h" #include "ui/gl/gl_display_manager.h" #include "ui/gl/startup_trace.h" @@ -265,7 +266,11 @@ // Default to using ANGLE's Vulkan backend. BASE_FEATURE(kDefaultANGLEVulkan, "DefaultANGLEVulkan", +#if BUILDFLAG(IS_DESKTOP_ANDROID) + base::FEATURE_ENABLED_BY_DEFAULT); +#else base::FEATURE_DISABLED_BY_DEFAULT); +#endif // Track current program's shaders at glUseProgram() call for crash report // purpose. Only effective on Windows because the attached shaders may only @@ -277,7 +282,11 @@ // Enable sharing Vulkan device queue with ANGLE's Vulkan backend. BASE_FEATURE(kVulkanFromANGLE, "VulkanFromANGLE", +#if BUILDFLAG(IS_DESKTOP_ANDROID) + base::FEATURE_ENABLED_BY_DEFAULT); +#else base::FEATURE_DISABLED_BY_DEFAULT); +#endif bool IsDefaultANGLEVulkan() { // Force on if DefaultANGLEVulkan feature is enabled from command line.
diff --git a/ui/views/controls/table/table_view.cc b/ui/views/controls/table/table_view.cc index c8497dffd..1fe86fe 100644 --- a/ui/views/controls/table/table_view.cc +++ b/ui/views/controls/table/table_view.cc
@@ -38,6 +38,7 @@ #include "ui/gfx/geometry/rect_f.h" #include "ui/gfx/geometry/skia_conversions.h" #include "ui/gfx/image/image_skia.h" +#include "ui/gfx/scoped_canvas.h" #include "ui/gfx/text_utils.h" #include "ui/strings/grit/ui_strings.h" #include "ui/views/accessibility/ax_virtual_view.h" @@ -283,6 +284,7 @@ void TableView::SetColumns(const std::vector<ui::TableColumn>& columns) { columns_ = columns; visible_columns_.clear(); + visible_columns_.reserve(columns.size()); for (const auto& column : columns) { VisibleColumn visible_column; visible_column.column = column; @@ -1071,9 +1073,85 @@ OnPaintImpl(canvas); } +void TableView::DrawString(gfx::Canvas* canvas, + const std::u16string& text, + SkColor color, + const gfx::Rect& text_bounds, + int flags, + size_t row, + size_t col) { + if (!canvas->IntersectsClipRect(RectToSkRect(text_bounds))) { + return; + } + + gfx::ScopedCanvas scoped(canvas); + + canvas->AdjustClipRectForTextBounds(text_bounds); + + // Resize the vector to accommodate the desired index + if (row >= render_text_cache_.size()) { + render_text_cache_.resize(row + 1); + } + if (col >= render_text_cache_[row].size()) { + render_text_cache_[row].resize(col + 1); + } + // Get or create the Render Text if it doesn't already exist. + std::unique_ptr<gfx::RenderText>& render_text = render_text_cache_[row][col]; + if (!render_text) { + render_text = gfx::RenderText::CreateRenderText(); + render_text->set_clip_to_display_rect(false); + render_text->SetFontList(font_list_); + } + + UpdateRenderText(gfx::Rect(text_bounds), text, flags, color, + render_text.get()); + render_text->Draw(canvas); +} + +// Updates |render_text| from the specified parameters. +void TableView::UpdateRenderText(const gfx::Rect& rect, + const std::u16string& text, + int flags, + SkColor color, + gfx::RenderText* render_text) { + render_text->SetText(text); + render_text->SetCursorEnabled(false); + render_text->SetDisplayRect(rect); + + // Set the text alignment explicitly based on the directionality of the UI, + // if not specified. + if (!(flags & + (gfx::Canvas::TEXT_ALIGN_LEFT | gfx::Canvas::TEXT_ALIGN_CENTER | + gfx::Canvas::TEXT_ALIGN_RIGHT | gfx::Canvas::TEXT_ALIGN_TO_HEAD))) { + flags |= gfx::Canvas::DefaultCanvasTextAlignment(); + } + + if (flags & gfx::Canvas::TEXT_ALIGN_LEFT) { + render_text->SetHorizontalAlignment(gfx::ALIGN_LEFT); + } else if (flags & gfx::Canvas::TEXT_ALIGN_CENTER) { + render_text->SetHorizontalAlignment(gfx::ALIGN_CENTER); + } else if (flags & gfx::Canvas::TEXT_ALIGN_RIGHT) { + render_text->SetHorizontalAlignment(gfx::ALIGN_RIGHT); + } else { + render_text->SetHorizontalAlignment(gfx::ALIGN_TO_HEAD); + } + + render_text->set_subpixel_rendering_suppressed( + (flags & gfx::Canvas::NO_SUBPIXEL_RENDERING) != 0); + + render_text->SetColor(color); + const int font_style = font_list_.GetFontStyle(); + render_text->SetStyle(gfx::TEXT_STYLE_ITALIC, + (font_style & gfx::Font::ITALIC) != 0); + render_text->SetStyle(gfx::TEXT_STYLE_UNDERLINE, + (font_style & gfx::Font::UNDERLINE) != 0); + render_text->SetStyle(gfx::TEXT_STYLE_STRIKE, + (font_style & gfx::Font::STRIKE_THROUGH) != 0); + render_text->SetWeight(font_list_.GetFontWeight()); +} + void TableView::OnPaintImpl(gfx::Canvas* canvas) { // Don't invoke View::OnPaint so that we can render our own focus border. - if (sort_on_paint_) { SortItemsAndUpdateMapping(/*schedule_paint=*/false); } @@ -1116,6 +1194,7 @@ canvas->FillRect(GetRowBounds(i), alternate_bg_color); } for (size_t j = region.min_column; j < region.max_column; ++j) { + const ui::TableColumn column = visible_columns_[j].column; const gfx::Rect cell_bounds = GetCellBounds(i, j); gfx::Rect text_bounds = cell_bounds; text_bounds.Inset(gfx::Insets::VH(0, cell_margin)); @@ -1152,13 +1231,12 @@ // Paint text if there is still room for it after all that insetting. if (!text_bounds.IsEmpty()) { - canvas->DrawStringRectWithFlags( - model_->GetText(model_index, visible_columns_[j].column.id), - font_list_, is_selected ? selected_fg_color : fg_color, - GetMirroredRect(text_bounds), - TableColumnAlignmentToCanvasAlignment( - GetMirroredTableColumnAlignment( - visible_columns_[j].column.alignment))); + DrawString(canvas, model_->GetText(model_index, column.id), + is_selected ? selected_fg_color : fg_color, + GetMirroredRect(text_bounds), + TableColumnAlignmentToCanvasAlignment( + GetMirroredTableColumnAlignment(column.alignment)), + i, j); } } }
diff --git a/ui/views/controls/table/table_view.h b/ui/views/controls/table/table_view.h index e103346..f738a622 100644 --- a/ui/views/controls/table/table_view.h +++ b/ui/views/controls/table/table_view.h
@@ -14,6 +14,7 @@ #include "ui/base/models/table_model.h" #include "ui/base/models/table_model_observer.h" #include "ui/gfx/font_list.h" +#include "ui/gfx/render_text.h" #include "ui/views/metadata/view_factory.h" #include "ui/views/view.h" #include "ui/views/views_export.h" @@ -315,6 +316,23 @@ void OnPaintImpl(gfx::Canvas* canvas); + // Draws a string with the desired parameters in an efficient way by reusing + // RenderTexts for each cell. + void DrawString(gfx::Canvas* canvas, + const std::u16string& text, + SkColor color, + const gfx::Rect& text_bounds, + int flags, + size_t row, + size_t col); + + // Updates |render_text| from the specified parameters. + void UpdateRenderText(const gfx::Rect& rect, + const std::u16string& text, + int flags, + SkColor color, + gfx::RenderText* render_text); + // Returns the horizontal margin between the bounds of a cell and its // contents. int GetCellMargin() const; @@ -600,6 +618,9 @@ // tokens are refined on all platforms. bool hovering_enabled_ = false; + // RenderText cache from row,col. + std::vector<std::vector<std::unique_ptr<gfx::RenderText>>> render_text_cache_; + // Weak pointer factory, enables using PostTask safely. base::WeakPtrFactory<TableView> weak_factory_; };
diff --git a/ui/views/widget/DEPS b/ui/views/widget/DEPS new file mode 100644 index 0000000..63ababc --- /dev/null +++ b/ui/views/widget/DEPS
@@ -0,0 +1,5 @@ +specific_include_rules = { + "widget_hwnd_utils\.cc": [ + "+components/viz/common" + ] +}
diff --git a/ui/views/widget/widget_hwnd_utils.cc b/ui/views/widget/widget_hwnd_utils.cc index 1c4bdf4..d402e40 100644 --- a/ui/views/widget/widget_hwnd_utils.cc +++ b/ui/views/widget/widget_hwnd_utils.cc
@@ -8,6 +8,7 @@ #include "base/command_line.h" #include "build/build_config.h" +#include "components/viz/common/features.h" #include "ui/base/l10n/l10n_util_win.h" #include "ui/base/mojom/window_show_state.mojom.h" #include "ui/base/ui_base_features.h" @@ -31,6 +32,10 @@ *ex_style = 0; *class_style = CS_DBLCLKS; + if (features::ShouldRemoveRedirectionBitmap()) { + *ex_style |= WS_EX_NOREDIRECTIONBITMAP; + } + // Set type-independent style attributes. if (params.child) { *style |= WS_CHILD;
diff --git a/ui/webui/resources/cr_components/searchbox/searchbox.ts b/ui/webui/resources/cr_components/searchbox/searchbox.ts index 3ef5719..d1851ea 100644 --- a/ui/webui/resources/cr_components/searchbox/searchbox.ts +++ b/ui/webui/resources/cr_components/searchbox/searchbox.ts
@@ -23,6 +23,10 @@ import type {SearchboxIconElement} from './searchbox_icon.js'; import {decodeString16, mojoString16} from './utils.js'; +// LINT.IfChange(GhostLoaderTagName) +const LENS_GHOST_LOADER_TAG_NAME = 'cr-searchbox-ghost-loader'; +// LINT.ThenChange(/chrome/browser/resources/lens/shared/searchbox_ghost_loader.ts:GhostLoaderTagName) + interface Input { text: string; inline: string; @@ -270,6 +274,7 @@ searchboxSteadyStateShadow: boolean; showThumbnail: boolean; private inputAriaLive_: string; + private isLensSearchbox_: boolean; private isDeletingInput_: boolean; private queryAutocompleteOnEmptyInput_: boolean; private lastIgnoredEnterEvent_: KeyboardEvent|null; @@ -548,26 +553,40 @@ } private onInputWrapperFocusout_(e: FocusEvent) { + const newlyFocusedEl = e.relatedTarget as Element; // Hide the matches and stop autocomplete only when the focus goes outside - // of the searchbox wrapper. - if (!this.$.inputWrapper.contains(e.relatedTarget as Element)) { - if (this.lastQueriedInput_ === '') { - // Clear the input as well as the matches if the input was empty when - // the matches arrived. - this.updateInput_({text: '', inline: ''}); - this.clearAutocompleteMatches_(); - } else { - this.dropdownIsVisible = false; - - // Stop autocomplete but leave (potentially stale) results and continue - // listening for key presses. These stale results should never be shown. - // They correspond to the potentially stale suggestion left in the - // searchbox when blurred. That stale result may be navigated to by - // focusing and pressing 'Enter'. - this.pageHandler_.stopAutocomplete(/*clearResult=*/ false); - } - this.pageHandler_.onFocusChanged(false); + // of the searchbox wrapper. If focus is still in the searchbox wrapper, + // exit early. + if (this.$.inputWrapper.contains(newlyFocusedEl)) { + return; } + + // If this is a Lens searchbox, treat the ghost loader as keeping searchbox + // focus. + // TODO(380467089): This workaround wouldn't be needed if the ghost loader + // was part of the searchbox element. Remove this workaround once they are + // combined. + if (this.isLensSearchbox_ && + newlyFocusedEl?.tagName.toLowerCase() === LENS_GHOST_LOADER_TAG_NAME) { + return; + } + + if (this.lastQueriedInput_ === '') { + // Clear the input as well as the matches if the input was empty when + // the matches arrived. + this.updateInput_({text: '', inline: ''}); + this.clearAutocompleteMatches_(); + } else { + this.dropdownIsVisible = false; + + // Stop autocomplete but leave (potentially stale) results and continue + // listening for key presses. These stale results should never be shown. + // They correspond to the potentially stale suggestion left in the + // searchbox when blurred. That stale result may be navigated to by + // focusing and pressing 'Enter'. + this.pageHandler_.stopAutocomplete(/*clearResult=*/ false); + } + this.pageHandler_.onFocusChanged(false); } private onInputWrapperKeydown_(e: KeyboardEvent) {